Run using
npx GIST_URL ./deploy/PROJECT_NAME| node_modules/ |
| #!/usr/bin/env node | |
| // @ts-check | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const yaml = require('yaml'); | |
| const dotenv = require('dotenv'); | |
| const { execSync } = require('child_process'); | |
| const dotEnvStringify = require('dotenv-stringify'); | |
| const deploymentPath = process.argv[process.argv.length - 1]; | |
| try { | |
| copySandboxEnv(); | |
| console.log('Copied sandbox env 💿'); | |
| } catch (error) { | |
| console.error('🚨', error.message); | |
| process.exit(1); | |
| } | |
| function copySandboxEnv() { | |
| const existing = readDotEnv('.env'); | |
| const values = readYaml('values.yaml').app.env; | |
| const sandbox = readYaml('values.sandbox.yaml').app.env; | |
| const secrets = readSops('secrets.sandbox.yaml'); | |
| const merged = { ...values, ...sandbox, ...secrets, ...existing }; | |
| const env = replaceClusterURLs(merged); | |
| writeEnv('.env', env); | |
| } | |
| function readDotEnv(path) { | |
| return fs.existsSync(path) | |
| ? dotenv.parse(fs.readFileSync(path).toString()) | |
| : {}; | |
| } | |
| /** | |
| * @param {string} path | |
| * @param {Record<string, any>} env | |
| */ | |
| function writeEnv(path, env) { | |
| const envString = dotEnvStringify(env); | |
| fs.writeFileSync(path, envString); | |
| } | |
| /** | |
| * @param {string} file | |
| * @returns {Record<string, any>} parsed content | |
| */ | |
| function readYaml(file) { | |
| return yaml.parse(fs.readFileSync(inDeploymentFolder(file)).toString()); | |
| } | |
| function inDeploymentFolder(file) { | |
| return path.resolve(deploymentPath, file); | |
| } | |
| function readSops(file) { | |
| try { | |
| execSync('saml2aws login', { stdio: 'pipe' }); | |
| } catch (error) { | |
| throw new Error('Login using "saml2aws login" first'); | |
| } | |
| try { | |
| const decrypted = execSync(`sops -d ${inDeploymentFolder(file)}`, { | |
| env: { AWS_PROFILE: 'sandbox-Developer', ...process.env }, | |
| }); | |
| return yaml.parse(decrypted.toString()).app.env; | |
| } catch (err) { | |
| return {}; | |
| } | |
| } | |
| /** | |
| * @param {Record<string, any>} params | |
| * @returns {Record<string, string>} | |
| */ | |
| function replaceClusterURLs(params) { | |
| return Object.fromEntries( | |
| Object.entries(params).map(([key, value]) => [ | |
| key, | |
| replaceClusterURL(value.toString()), | |
| ]) | |
| ); | |
| } | |
| /** | |
| * @param {string} value | |
| * @returns string | |
| */ | |
| function replaceClusterURL(value) { | |
| if (value.endsWith('.api.svc.cluster.local.')) { | |
| return value | |
| .toString() | |
| .replace('http://', 'https://') | |
| .replace('.api.svc.cluster.local.', '.forto.io'); | |
| } | |
| return value; | |
| } |
| { | |
| "name": "copy-sandbox-env", | |
| "version": "0.1.0", | |
| "lockfileVersion": 2, | |
| "requires": true, | |
| "packages": { | |
| "": { | |
| "name": "copy-sandbox-env", | |
| "version": "0.1.0", | |
| "license": "MIT", | |
| "dependencies": { | |
| "dotenv": "^10.0.0", | |
| "dotenv-stringify": "^2.0.6", | |
| "yaml": "^1.10.2" | |
| }, | |
| "bin": { | |
| "copy-sandbox-env": "index.js" | |
| }, | |
| "devDependencies": {}, | |
| "engines": { | |
| "node": ">=10" | |
| } | |
| }, | |
| "node_modules/dotenv": { | |
| "version": "10.0.0", | |
| "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", | |
| "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", | |
| "engines": { | |
| "node": ">=10" | |
| } | |
| }, | |
| "node_modules/dotenv-stringify": { | |
| "version": "2.0.7", | |
| "resolved": "https://registry.npmjs.org/dotenv-stringify/-/dotenv-stringify-2.0.7.tgz", | |
| "integrity": "sha512-uCLaePd3S/kSYJkbUeWYluYEeiiPcOZdHB0za0xoojixYC6G0nTYBrdPhvcdP/bhmduFd1cOcWjXVA+XFZOLog==" | |
| }, | |
| "node_modules/yaml": { | |
| "version": "1.10.2", | |
| "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", | |
| "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", | |
| "engines": { | |
| "node": ">= 6" | |
| } | |
| } | |
| }, | |
| "dependencies": { | |
| "dotenv": { | |
| "version": "10.0.0", | |
| "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", | |
| "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" | |
| }, | |
| "dotenv-stringify": { | |
| "version": "2.0.7", | |
| "resolved": "https://registry.npmjs.org/dotenv-stringify/-/dotenv-stringify-2.0.7.tgz", | |
| "integrity": "sha512-uCLaePd3S/kSYJkbUeWYluYEeiiPcOZdHB0za0xoojixYC6G0nTYBrdPhvcdP/bhmduFd1cOcWjXVA+XFZOLog==" | |
| }, | |
| "yaml": { | |
| "version": "1.10.2", | |
| "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", | |
| "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" | |
| } | |
| } | |
| } |
| { | |
| "version": "0.1.0", | |
| "license": "MIT", | |
| "main": "./index.js", | |
| "bin": "./index.js", | |
| "files": [ | |
| "./index.js" | |
| ], | |
| "engines": { | |
| "node": ">=10" | |
| }, | |
| "scripts": { | |
| "start": "node index.js" | |
| }, | |
| "peerDependencies": {}, | |
| "prettier": { | |
| "printWidth": 80, | |
| "semi": true, | |
| "singleQuote": true, | |
| "trailingComma": "es5" | |
| }, | |
| "name": "copy-sandbox-env", | |
| "author": "Maximilian Taeschner", | |
| "devDependencies": {}, | |
| "dependencies": { | |
| "dotenv": "^10.0.0", | |
| "dotenv-stringify": "^2.0.6", | |
| "yaml": "^1.10.2" | |
| } | |
| } |