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" | |
} | |
} |