From 976a925ff5836d709b81a1bcc85a0216fffab5ce Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Tue, 2 Feb 2021 23:35:29 +0100 Subject: [PATCH 1/5] chore: automate Docker build & push --- .dockerignore | 2 + Dockerfile | 2 + README.md | 2 +- package-lock.json | 406 ++++++++++++++++++++++++++++++++++ package.json | 11 +- tools/docker-utils.js | 149 +++++++++++++ tools/release.js | 95 ++++++++ tools/unleash-server-utils.js | 18 ++ 8 files changed, 683 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 tools/docker-utils.js create mode 100755 tools/release.js create mode 100644 tools/unleash-server-utils.js diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8e43d96 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +tools/ +node_modules/ diff --git a/Dockerfile b/Dockerfile index 1080fe8..2151f7a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM node:12-alpine +ENV NODE_ENV production + COPY package.json package-lock.json ./ RUN npm ci diff --git a/README.md b/README.md index 2884467..a211f57 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ We have set up `docker-compose` to start postgres and the unleash server togethe unleash locally without setting up a database or node. ```bash -$ docker-compose build +$ docker-compose build $ docker-compose up ``` diff --git a/package-lock.json b/package-lock.json index 6e905f8..d1c1d57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,32 @@ "@hapi/hoek": "^9.0.0" } }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, "@passport-next/passport": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@passport-next/passport/-/passport-3.1.0.tgz", @@ -82,6 +108,16 @@ "negotiator": "0.6.2" } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -138,6 +174,12 @@ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -403,6 +445,12 @@ } } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -599,6 +647,34 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "cycle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", @@ -750,6 +826,33 @@ } } }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -797,6 +900,15 @@ } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "dotenv": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-5.0.1.tgz", @@ -851,6 +963,23 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -1023,6 +1152,74 @@ "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fastq": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz", + "integrity": "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -1165,6 +1362,12 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -1188,6 +1391,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -1210,6 +1422,20 @@ "which": "^1.2.14" } }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -1298,6 +1524,12 @@ } } }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, "i": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", @@ -1311,6 +1543,18 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -1461,6 +1705,18 @@ } } }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1477,6 +1733,12 @@ "is-unc-path": "^1.0.0" } }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -1685,6 +1947,18 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -1728,6 +2002,12 @@ "mime-db": "1.45.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1836,6 +2116,15 @@ "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=" }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, "oauth": { "version": "0.9.15", "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", @@ -1931,6 +2220,15 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1947,6 +2245,15 @@ "p-limit": "^2.2.0" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -2026,6 +2333,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2049,6 +2362,12 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", @@ -2108,6 +2427,12 @@ "split2": "^3.1.1" } }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pkginfo": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", @@ -2313,6 +2638,12 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "revalidator": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", @@ -2331,6 +2662,12 @@ "glob": "^7.1.3" } }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2457,6 +2794,33 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2712,6 +3076,12 @@ "ansi-regex": "^5.0.0" } }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -2730,6 +3100,33 @@ "bintrees": "1.0.1" } }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "tempy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.0.tgz", + "integrity": "sha512-eLXG5B1G0mRPHmgH2WydPl5v4jH35qEn3y/rA/aahKhIa91Pn119SsU7n7v/433gtT9ONzC8ISvNHIh2JSTm0w==", + "dev": true, + "requires": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true + } + } + }, "tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -2833,6 +3230,15 @@ "set-value": "^2.0.1" } }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", diff --git a/package.json b/package.json index 87a707c..b81327c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "main": "index.js", "scripts": { "start": "NODE_ENV=production node index.js", - "test:ci": "echo 'no tests for unleash-docker';" + "test:ci": "echo 'no tests for unleash-docker';", + "docker:build": "./tools/release build.js", + "docker:build-default": "./tools/release.js build --node-docker-versions 12-alpine,14-alpine --default-node-docker-version 12-alpine", + "docker:publish": "./tools/release publish.js", + "docker:publish-default": "./tools/release.js publish --node-docker-versions 12-alpine,14-alpine --default-node-docker-version 12-alpine" }, "engines": { "node": ">=12" @@ -18,5 +22,10 @@ "basic-auth": "^2.0.1", "passport": "^0.4.1", "unleash-server": "^3.10.1" + }, + "devDependencies": { + "execa": "^5.0.0", + "tempy": "^1.0.0", + "yargs": "^16.2.0" } } diff --git a/tools/docker-utils.js b/tools/docker-utils.js new file mode 100644 index 0000000..1d9b7cc --- /dev/null +++ b/tools/docker-utils.js @@ -0,0 +1,149 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const tempy = require('tempy'); +const execa = require('execa'); +const { getUnleashServerVersion } = require('./unleash-server-utils'); + +const tempDirPath = tempy.directory(); + +/** @type {string} */ +const dockerfileTemplate = fs.readFileSync( + path.resolve(__dirname, '..', 'Dockerfile'), + { encoding: 'utf8' }, +); + +const fromLineRegExp = /FROM node:.*?\n/g; + +/** + * Render a Dockerfile with the correct base image. + * + * @param nodeDockerVersion {string} + * @returns {string} the Dockerfile content with the correct base image + */ +function renderDockerfile({nodeDockerVersion}) { + return dockerfileTemplate.replace(fromLineRegExp, `FROM node:${nodeDockerVersion}`); +} + +const unleashImageName = `unleashorg/unleash-server`; + +/** + * Renders a Dockerfile to a temporary location on disk + * with the specified content. + * + * @param unleashServerVersion {string} the version of unleash-server that will be included in the image + * @param nodeDockerVersion {string} the Node Docker image tag version to base this image on + * @returns {Promise<{dockerfilePath: string, unleashDockerTag: string}>} + */ +async function createDockerfile({ unleashServerVersion, nodeDockerVersion }) { + const unleashDockerTagVersion = `${unleashServerVersion}-node${nodeDockerVersion}`; + const unleashDockerTag = `unleashorg/unleash-server:${unleashDockerTagVersion}`; + + const dockerfilePath = path.join( + tempDirPath, + `Dockerfile.${unleashDockerTagVersion}`, + ); + await fs.promises.writeFile( + dockerfilePath, + renderDockerfile({ nodeDockerVersion }), + ); + + return { + unleashDockerTag, + dockerfilePath, + }; +} + +/** + * Builds an unleash-server Docker image based on a Node docker tag version. + * + * @param nodeDockerVersion {string} the version of the Node docker image to base this image on + * @param unleashServerVersion {string} the version of unleash-server that will be included + * @param isDefaultNodeVersion {boolean} whether this version should be used for the tags `latest` and without `-nodeXY-distro` + * @returns {Promise<{unleashDockerTags: string[]}>} + */ +async function buildDockerImage({ + nodeDockerVersion, + unleashServerVersion, + isDefaultNodeVersion, +}) { + console.log(`\nBuilding Docker image based on node:${nodeDockerVersion}`); + + const { dockerfilePath, unleashDockerTag } = await createDockerfile({ + unleashServerVersion, + nodeDockerVersion, + }); + + const contextDirectory = path.resolve(__dirname, '..'); + + await execa( + 'docker', + ['build', '-f', dockerfilePath, '-t', unleashDockerTag, contextDirectory], + { stdio: 'inherit' }, + ); + + const additionalUnleashDockerTags = []; + + if (isDefaultNodeVersion) { + additionalUnleashDockerTags.push( + `${unleashImageName}:${unleashServerVersion}`, + ); + additionalUnleashDockerTags.push(`${unleashImageName}:latest`); + } + + for (const tag of additionalUnleashDockerTags) { + await execa('docker', ['tag', unleashDockerTag, tag], { stdio: 'inherit' }); + } + + const unleashDockerTags = [unleashDockerTag, ...additionalUnleashDockerTags]; + + return { + unleashDockerTags, + }; +} + +/** + * Builds unleash-server Docker images for the given Node Docker versions. + * + * @param nodeDockerVersions {string[]} the versions of the Node docker image to base the unleash-server images on + * @param defaultNodeDockerVersion {string} any additional Docker tags for unleash-server + * @returns {Promise<{tag: string, nodeDockerVersion: string}[]>} + */ +async function buildDockerImages({ + nodeDockerVersions, + defaultNodeDockerVersion, +}) { + const unleashServerVersion = await getUnleashServerVersion(); + + /** @type {{tag: string, nodeDockerVersion: string}[]} */ + const artifacts = []; + + for (const nodeDockerVersion of nodeDockerVersions) { + const buildResult = await buildDockerImage({ + nodeDockerVersion, + unleashServerVersion, + isDefaultNodeVersion: nodeDockerVersion === defaultNodeDockerVersion, + }); + + for (const tag of buildResult.unleashDockerTags) { + artifacts.push({ tag, nodeDockerVersion }); + } + } + + return artifacts; +} + +/** + * Pushes a Docker image to the registry. + * @param tag the Docker image tag to push. + * @returns {Promise} + */ +async function pushDockerImage({ tag }) { + await execa('docker', ['push', tag], { stdio: 'inherit' }); +} + +module.exports = { + buildDockerImages, + pushDockerImage, +}; diff --git a/tools/release.js b/tools/release.js new file mode 100755 index 0000000..caf36df --- /dev/null +++ b/tools/release.js @@ -0,0 +1,95 @@ +#!/usr/bin/env node +'use strict'; + +const yargs = require('yargs/yargs'); +const { hideBin } = require('yargs/helpers'); +const readline = require('readline').createInterface({ + input: process.stdin, + output: process.stdout, +}); +const { buildDockerImages, pushDockerImage } = require('./docker-utils'); + +async function main() { + const argv = yargs(hideBin(process.argv)) + .option('defaultNodeDockerVersion', { + alias: 'default-node-docker-version', + describe: 'Node Docker version for latest tag', + demandOption: true, + }) + .option('nodeDockerVersions', { + alias: 'node-docker-versions', + describe: + 'Comma-separated list of Node Docker tag versions (e.g., "12-alpine,14-alpine")', + demandOption: true, + coerce: (opt) => { + return opt.split(','); + }, + }) + .check(({ nodeDockerVersions, defaultNodeDockerVersion }) => { + if (nodeDockerVersions.includes(defaultNodeDockerVersion)) { + return true; + } + + throw new Error( + `defaultNodeDockerVersion "${defaultNodeDockerVersion}" was not in list of versions "${nodeDockerVersions}"`, + ); + }) + .command({ + command: 'build', + desc: 'Build Docker image(s) based on Node version(s)', + async handler(args) { + const artifacts = await buildDockerImages(args); + + const formattedResults = artifacts.map( + (result) => + `${result.tag} (based on node:${result.nodeDockerVersion})`, + ); + + console.log(`\nBuilt tags: \n- ${formattedResults.join('\n- ')}`); + process.exit(0); + }, + }) + .command({ + command: 'publish', + desc: 'Build & push Docker image(s) to Docker Hub', + async handler(args) { + const artifacts = await buildDockerImages(args); + + const formattedResults = artifacts.map( + (result) => + `${result.tag} (based on node:${result.nodeDockerVersion})`, + ); + + console.log(`\nBuilt tags: \n- ${formattedResults.join('\n- ')}`); + + readline.setPrompt('\nDo you want to push these tags? (y/N) '); + readline.prompt(); + readline.once('line', async input => { + switch (input) { + case 'n': + case '': + console.log('Aborted'); + break; + case 'y': + for (const artifact of artifacts) { + await pushDockerImage(artifact); + } + break; + default: + console.error(`Invalid input: "${input}"`); + readline.prompt(); + } + + console.log('Bye!') + process.exit(0); + }); + }, + }) + .demandCommand(1, 'You have to specify a command.') + .strict(true) + .version(false) + .wrap(120) + .help().argv; +} + +main().catch(console.error); diff --git a/tools/unleash-server-utils.js b/tools/unleash-server-utils.js new file mode 100644 index 0000000..4d42a00 --- /dev/null +++ b/tools/unleash-server-utils.js @@ -0,0 +1,18 @@ +'use strict'; + +const execa = require('execa'); + +/** + * Gets the installed version of unleash-server. + * + * @returns {Promise} + */ +async function getUnleashServerVersion() { + const { stdout: npmListOutput } = await execa.command( + 'npm list unleash-server', + ); + const versionLine = npmListOutput.split('\n')[1]; + return versionLine.split('@')[1].trim(); +} + +module.exports = { getUnleashServerVersion }; From 2889f77ab45fd0793f27d9d997bc86355f8a9943 Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Wed, 3 Feb 2021 01:01:09 +0100 Subject: [PATCH 2/5] oops --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b81327c..39c210a 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "scripts": { "start": "NODE_ENV=production node index.js", "test:ci": "echo 'no tests for unleash-docker';", - "docker:build": "./tools/release build.js", + "docker:build": "./tools/release.js build", "docker:build-default": "./tools/release.js build --node-docker-versions 12-alpine,14-alpine --default-node-docker-version 12-alpine", - "docker:publish": "./tools/release publish.js", + "docker:publish": "./tools/release.js publish", "docker:publish-default": "./tools/release.js publish --node-docker-versions 12-alpine,14-alpine --default-node-docker-version 12-alpine" }, "engines": { From b6e864cf0e5acc9bcd422d91b063d4ef1fbc7ebc Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Wed, 3 Feb 2021 12:05:56 +0100 Subject: [PATCH 3/5] get unleash-server version in a less complicated way --- tools/docker-utils.js | 4 ++-- tools/unleash-server-utils.js | 18 ------------------ 2 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 tools/unleash-server-utils.js diff --git a/tools/docker-utils.js b/tools/docker-utils.js index 1d9b7cc..38235c3 100644 --- a/tools/docker-utils.js +++ b/tools/docker-utils.js @@ -4,7 +4,6 @@ const fs = require('fs'); const path = require('path'); const tempy = require('tempy'); const execa = require('execa'); -const { getUnleashServerVersion } = require('./unleash-server-utils'); const tempDirPath = tempy.directory(); @@ -114,7 +113,8 @@ async function buildDockerImages({ nodeDockerVersions, defaultNodeDockerVersion, }) { - const unleashServerVersion = await getUnleashServerVersion(); + /** @type string */ + const unleashServerVersion = require('unleash-server/package.json').version; /** @type {{tag: string, nodeDockerVersion: string}[]} */ const artifacts = []; diff --git a/tools/unleash-server-utils.js b/tools/unleash-server-utils.js deleted file mode 100644 index 4d42a00..0000000 --- a/tools/unleash-server-utils.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const execa = require('execa'); - -/** - * Gets the installed version of unleash-server. - * - * @returns {Promise} - */ -async function getUnleashServerVersion() { - const { stdout: npmListOutput } = await execa.command( - 'npm list unleash-server', - ); - const versionLine = npmListOutput.split('\n')[1]; - return versionLine.split('@')[1].trim(); -} - -module.exports = { getUnleashServerVersion }; From 2df24ae21c062782bb1e68dc54efcd790ad2d8a4 Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Wed, 3 Feb 2021 12:15:43 +0100 Subject: [PATCH 4/5] Update tools/docker-utils.js Co-authored-by: Simen Bekkhus --- tools/docker-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/docker-utils.js b/tools/docker-utils.js index 38235c3..1ee50fd 100644 --- a/tools/docker-utils.js +++ b/tools/docker-utils.js @@ -9,8 +9,8 @@ const tempDirPath = tempy.directory(); /** @type {string} */ const dockerfileTemplate = fs.readFileSync( - path.resolve(__dirname, '..', 'Dockerfile'), - { encoding: 'utf8' }, + path.resolve(__dirname, '../Dockerfile'), + 'utf8', ); const fromLineRegExp = /FROM node:.*?\n/g; From e678467137ca4e2a0a0dbaf1d885f3f1c6aa6a54 Mon Sep 17 00:00:00 2001 From: Martin Lehmann Date: Wed, 3 Feb 2021 12:16:23 +0100 Subject: [PATCH 5/5] formatting --- tools/docker-utils.js | 7 +++++-- tools/release.js | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/docker-utils.js b/tools/docker-utils.js index 1ee50fd..9211e3e 100644 --- a/tools/docker-utils.js +++ b/tools/docker-utils.js @@ -21,8 +21,11 @@ const fromLineRegExp = /FROM node:.*?\n/g; * @param nodeDockerVersion {string} * @returns {string} the Dockerfile content with the correct base image */ -function renderDockerfile({nodeDockerVersion}) { - return dockerfileTemplate.replace(fromLineRegExp, `FROM node:${nodeDockerVersion}`); +function renderDockerfile({ nodeDockerVersion }) { + return dockerfileTemplate.replace( + fromLineRegExp, + `FROM node:${nodeDockerVersion}`, + ); } const unleashImageName = `unleashorg/unleash-server`; diff --git a/tools/release.js b/tools/release.js index caf36df..7b33373 100755 --- a/tools/release.js +++ b/tools/release.js @@ -64,7 +64,7 @@ async function main() { readline.setPrompt('\nDo you want to push these tags? (y/N) '); readline.prompt(); - readline.once('line', async input => { + readline.once('line', async (input) => { switch (input) { case 'n': case '': @@ -80,7 +80,7 @@ async function main() { readline.prompt(); } - console.log('Bye!') + console.log('Bye!'); process.exit(0); }); },