diff --git a/Procfile b/Procfile index 68bf28f..9b99edb 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,2 @@ -web: GQL_PORT=$PORT sqd serve:prod -worker: sqd process:prod +web: GQL_PORT=$PORT npm run serve:prod +worker: npm run process:prod diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..95cecda --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,9 @@ +# Deploy Helpers + +Folder holding scripts to support the API deployment process. + +### Run script + +Currently support deriving the database_url environment variable into expected ones for the processor and graphQL-server (e.g. DB_HOST, DB_PASS), then it starts the target applications with this new vars available. + +> Check the script [here](./run) for more details. diff --git a/deploy/run b/deploy/run new file mode 100644 index 0000000..0debb79 --- /dev/null +++ b/deploy/run @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +/** + * @file Manage to derive the DATABASE_URL env var + * into several ones, followed by starting the correct npm script. + * It will set the new vars prepending its declaration prior + * calling the npm-script defined by the caller. + * The main intent is to solve the problem when the cloud provider changes + * the DATABASE_URL due to maintenance that leads to manual derivation + * of such values. + * + * @author Bruno Menezes + */ + +/** + * @typedef {Object} Config + * @property {string} DB_HOST - Database host + * @property {string} DB_NAME - Database name + * @property {string} DB_USER - Database user + * @property {string} DB_PASS - Database password + * @property {string} DB_PORT - Database port + */ + +const url = require('node:url'); +const shell = require('shelljs'); +const yargs = require('yargs'); +const { hideBin } = require('yargs/helpers'); + +const argv = yargs(hideBin(process.argv)).argv; + +if (!argv.npmScriptName) { + console.error('Npm script name is required!\n'); + process.exitCode = 1; +} + +/** + * @type Config + */ +const config = {}; + +const scriptName = argv.npmScriptName; +const DATABASE_URL = process.env.DATABASE_URL; +const db = url.parse(DATABASE_URL); +const auth = db.auth.split(':'); +config.DB_HOST = db.hostname; +config.DB_NAME = db.pathname.substring(1); +config.DB_USER = auth[0]; +config.DB_PASS = auth[1]; +config.DB_PORT = db.port; + +/** + * + * @param {string} scriptName Existing npm-script name. + * @param {Config} config Database environment variables to be injected. + */ +function runScript(scriptName, config) { + const vars = []; + for (const key in config) { + vars.push(`${key}=${config[key]}`); + } + + shell.exec(`${vars.join(' ')} npm run ${scriptName}`); +} + +runScript(scriptName, config); diff --git a/package-lock.json b/package-lock.json index 9fbccaf..4b10a1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,10 @@ "dotenv": "^16.1.4", "ethers": "^6.5.1", "pg": "^8.11.0", + "shelljs": "^0.8.5", "type-graphql": "^1.2.0-rc.1", - "typeorm": "^0.3.16" + "typeorm": "^0.3.16", + "yargs": "^17.7.2" }, "devDependencies": { "@subsquid/cli": "latest", @@ -7051,7 +7053,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, "engines": { "node": ">= 0.10" } @@ -7168,7 +7169,6 @@ "version": "2.13.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -9915,8 +9915,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.10.1", @@ -11090,7 +11089,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, "dependencies": { "resolve": "^1.1.6" }, @@ -11179,7 +11177,6 @@ "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -11540,7 +11537,6 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -11557,7 +11553,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -11567,7 +11562,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11587,7 +11581,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -12378,7 +12371,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -21182,8 +21174,7 @@ "interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" }, "ioredis": { "version": "5.3.2", @@ -21263,7 +21254,6 @@ "version": "2.13.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -23320,8 +23310,7 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-scurry": { "version": "1.10.1", @@ -24197,7 +24186,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, "requires": { "resolve": "^1.1.6" } @@ -24265,7 +24253,6 @@ "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, "requires": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -24526,7 +24513,6 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -24537,7 +24523,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -24547,7 +24532,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -24561,7 +24545,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -25161,8 +25144,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "sync-fetch": { "version": "0.5.2", diff --git a/package.json b/package.json index d399c78..911ef00 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,16 @@ "sqd:down": "sqd down", "sqd:migration": "sqd migration", "sqd:process": "sqd process", + "sqd:process:prod": "sqd process:prod", "sqd:graphql": "sqd serve", + "sqd:graphql:prod": "sqd serve:prod", "sqd:auth": "sqd auth -k $SQD_API_KEY", "sqd:deploy": "sqd deploy -o cartesi -m", "sqd:deploy:mainnet": "run-s \"sqd:deploy -- {@} .\" -- \"squid-mainnet.yaml\"", "sqd:deploy:sepolia": "run-s \"sqd:deploy -- {@} .\" -- \"squid-sepolia.yaml\"", - "tsc": "tsc" + "tsc": "tsc", + "process:prod": "node deploy/run --npmScriptName=sqd:process:prod", + "serve:prod": "node deploy/run --npmScriptName=sqd:graphql:prod" }, "dependencies": { "@cartesi/rollups": "1.0.0", @@ -34,8 +38,10 @@ "dotenv": "^16.1.4", "ethers": "^6.5.1", "pg": "^8.11.0", + "shelljs": "^0.8.5", "type-graphql": "^1.2.0-rc.1", - "typeorm": "^0.3.16" + "typeorm": "^0.3.16", + "yargs": "^17.7.2" }, "devDependencies": { "@subsquid/cli": "latest",