UNPKG

bitbucket-env-manager

Version:

Deploys Bitbucket Environment

193 lines (169 loc) 5.66 kB
#!/usr/bin/env node const dotenv = require('dotenv'); const fs = require('fs-extra'); const path = require('path'); const inquirer = require('inquirer'); const { capitalizeFirstLetter } = require('./helpers'); const { names } = require('./config'); const getEnvFileNameParams = (filename) => { const splits = filename.split('.'); const splitsLength = splits.length; const verify_start = splits[0] === '' && splits[1] === 'env'; const env_name = splits[splitsLength - 1]; const rankRaw = splits[splitsLength - 2]; const rank = Number(rankRaw); if (splitsLength !== 4 || !verify_start || !env_name || ![0, 1, 2].includes(rank)) { throw new Error('Specify env filename in the format .env.{rank}.{env_name}. 0|1|2 for rank'); } return { env_name: capitalizeFirstLetter(env_name), rank, }; }; const getInfoJsonParams = (envfilePath) => { const parent = path.dirname(envfilePath); const infoJsonPath = path.join(parent, names.infoJsonFile); if (!fs.existsSync(infoJsonPath)) { throw new Error( `Please specify {workspace:, repo:, secured:[]} under "${names.infoJsonFile}" file` ); } const infoRaw = fs.readFileSync(infoJsonPath, { encoding: 'utf-8' }); const infoJson = JSON.parse(infoRaw); if ( !infoJson.workspace || !infoJson.repo || !infoJson.secured || !Array.isArray(infoJson.secured) ) { throw new Error( `Please specify {workspace:, repo:, secured:[]} under "${names.infoJsonFile}" file` ); } return { workspace: infoJson.workspace, repo: infoJson.repo, secured: infoJson.secured, envs_config: infoJson.envs_config || {}, }; }; const runConvert = async ({ multiple = false } = {}) => { try { inquirer.registerPrompt('file-tree-selection', require('inquirer-file-tree-selection-prompt')); const basePath = path.join(process.cwd()); const answers = await inquirer.prompt([ /* Pass your questions in here */ { type: 'file-tree-selection', name: 'filePaths', message: `\n\n\x1b[45m\x1b[33mSelect .env file(s) to deploy to bitbucket\n\x1b[0m(format ".env.{0|1|2}.{env_name}")\n\n\x1b[36m"Arrow keys" -> Navigate\n"Space" -> toggle file selection\n"Enter" -> Submit selected envs\n\x1b[0m`, root: basePath, loop: false, pageSize: 20, validate: (item) => { const name = item.split(path.sep).pop(); if (name[0] != '.') { return 'please select another file in the format ".env.{0|1|2}.{env_name}"'; } try { getEnvFileNameParams(name); } catch (e) { return 'please select another file in the format ".env.{0|1|2}.{env_name}"'; } // try { // getInfoJsonParams(item); // } catch (e) { // return e.message || 'Error info.json'; // } return true; }, onlyShowValid: false, multiple: multiple, }, ]); const filePaths = multiple ? answers.filePaths : [answers.filePaths]; if (!filePaths.length) { throw new Error('No Files Selected!'); } const jsonCfgs = []; for (const fPath of filePaths) { const jsonCfg = await getCfgForEnvFile(fPath); jsonCfgs.push(jsonCfg); } return jsonCfgs; } catch (e) { console.error(e.message); } finally { } }; const getCfgForEnvFile = async (filePath) => { const filename = path.basename(filePath); const { env_name, rank } = getEnvFileNameParams(filename); const { workspace, repo, secured, envs_config = {} } = getInfoJsonParams(filePath); const cfg = dotenv.config({ path: filePath }); const vars = Object.keys(cfg.parsed) .map((key) => { return { secured: secured.includes(key), key, rawValue: cfg.parsed[key], /* NOTE To escape \n, as other escape sequence charactes seem to be already escaped. */ value: cfg.parsed[key].replace(/\n/g, '\\n'), }; }) .filter((v) => v.value); const found = Object.keys(envs_config).find((a) => a.toLowerCase() === env_name.toLowerCase()); const env_config = { admin_only: found && envs_config[found] ? !!envs_config[found].admin_only : false, }; //TODO: add allowed branches const jsonCfg = { workspace, repo, env_name, rank, vars, env_config, }; console.log('\n'); console.log('%s\x1b[34m%s\x1b[0m', 'workspace = ', `${workspace}`); console.log('%s\x1b[34m%s\x1b[0m', 'repo = ', `${repo}`); console.log('%s\x1b[34m%s\x1b[0m', 'env_name = ', `${env_name}`); console.log('%s\x1b[34m%s\x1b[0m', 'rank = ', `${rank}`); console.log('%s\x1b[34m%s\x1b[0m', 'env_config = ', `${JSON.stringify(env_config)}`); const { destConfirm } = await inquirer.prompt([ { type: 'confirm', name: 'destConfirm', message: 'Do the destination details above look correct?', }, ]); if (!destConfirm) { throw new Error('Operation Cancelled!'); } console.log('\n'); vars.forEach((v) => { v.secured ? console.log('\x1b[36m%s\x1b[0m', `${v.key}="🔒🔒🔒"`) : console.log(`${v.key}="${v.value}"`); }); console.log('\n'); const { varsConfirm } = await inquirer.prompt([ { type: 'confirm', name: 'varsConfirm', message: 'Do the variables above look correct?', }, ]); if (!varsConfirm) { throw new Error('Operation Cancelled!'); } console.log( '\n----------------------------------------------------------------------------------------' ); return jsonCfg; }; module.exports = { runConvert, };