UNPKG

@lenne.tech/cli

Version:

lenne.Tech CLI: lt

289 lines (288 loc) 13.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = require("path"); /** * Create a new deployment for mono repository */ const NewCommand = { alias: ['dc'], description: 'Create deployment config', hidden: false, name: 'create', run: (toolbox) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; // Retrieve the tools we need const { config, filesystem, helper, parameters, patching, print: { info, spin, success }, prompt: { confirm }, strings: { camelCase, kebabCase, pascalCase }, system, template, } = toolbox; // Load configuration const ltConfig = config.loadConfig(); const configDomain = (_b = (_a = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _a === void 0 ? void 0 : _a.deployment) === null || _b === void 0 ? void 0 : _b.domain; const configGitHub = (_d = (_c = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _c === void 0 ? void 0 : _c.deployment) === null || _d === void 0 ? void 0 : _d.gitHub; const configGitLab = (_f = (_e = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _e === void 0 ? void 0 : _e.deployment) === null || _f === void 0 ? void 0 : _f.gitLab; const configTestRunner = (_h = (_g = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _g === void 0 ? void 0 : _g.deployment) === null || _h === void 0 ? void 0 : _h.testRunner; const configProdRunner = (_k = (_j = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _j === void 0 ? void 0 : _j.deployment) === null || _k === void 0 ? void 0 : _k.prodRunner; // Load global defaults const globalDomain = config.getGlobalDefault(ltConfig, 'domain'); // Parse CLI arguments const cliDomain = parameters.options.domain; const cliGitHub = parameters.options.gitHub; const cliGitLab = parameters.options.gitLab; const cliTestRunner = parameters.options.testRunner; const cliProdRunner = parameters.options.prodRunner; const cliNoConfirm = parameters.options.noConfirm; // Determine noConfirm with priority: CLI > command > parent > global > default const noConfirm = config.getNoConfirm({ cliValue: cliNoConfirm, commandConfig: (_l = ltConfig === null || ltConfig === void 0 ? void 0 : ltConfig.commands) === null || _l === void 0 ? void 0 : _l.deployment, config: ltConfig, }); // Start timer const timer = system.startTimer(); // Info info('Create a new deployment'); // Get default project name let projectName = ''; const hasLtJson = yield filesystem.exists('lt.json'); if (hasLtJson) { yield patching.update('lt.json', (data) => { projectName = data.name; return data; }); } if (!projectName) { yield patching.update('package.json', (data) => { projectName = pascalCase(data.name); return data; }); } // Get name const name = yield helper.getInput(parameters.first, { initial: projectName, name: `project name (e.g. ${projectName ? projectName : 'My new project'})`, }); if (!name) { return; } // Determine domain with priority: CLI > config > global > interactive let domain; if (cliDomain) { domain = cliDomain; } else if (configDomain) { domain = configDomain.replace('{name}', kebabCase(name)); info(`Using domain from lt.config commands.deployment: ${domain}`); } else if (globalDomain) { domain = globalDomain.replace('{name}', kebabCase(name)); info(`Using domain from lt.config defaults: ${domain}`); } else { domain = yield helper.getInput(parameters.second, { initial: `${kebabCase(name)}.lenne.tech`, name: `main domain of the project (e.g. ${kebabCase(name)}.lenne.tech)`, }); } if (!domain) { return; } // Determine gitHub with priority: CLI > config > noConfirm > interactive let gitHub; if (cliGitHub !== undefined) { gitHub = cliGitHub === true || cliGitHub === 'true'; } else if (configGitHub !== undefined) { gitHub = configGitHub; if (gitHub) { info('Using GitHub pipeline setting from lt.config: enabled'); } } else if (noConfirm) { gitHub = false; // Default to false when noConfirm } else { gitHub = yield confirm('Add GitHub pipeline?'); } // Determine gitLab with priority: CLI > config > noConfirm > interactive let gitLab; if (cliGitLab !== undefined) { gitLab = cliGitLab === true || cliGitLab === 'true'; } else if (configGitLab !== undefined) { gitLab = configGitLab; if (gitLab) { info('Using GitLab pipeline setting from lt.config: enabled'); } } else if (noConfirm) { gitLab = false; // Default to false when noConfirm } else { gitLab = yield confirm('Add GitLab pipeline?'); } // GitLab test runner let testRunner; let prodRunner; if (gitLab) { // Determine testRunner with priority: CLI > config > interactive if (cliTestRunner) { testRunner = cliTestRunner; } else if (configTestRunner) { testRunner = configTestRunner; info(`Using test runner from lt.config: ${testRunner}`); } else { testRunner = yield helper.getInput('', { initial: 'docker-swarm', name: 'runner for test (tag in .gitlab-ci.yml, e.g. docker-swarm)', }); } if (!testRunner) { return; } // Determine prodRunner with priority: CLI > config > interactive if (cliProdRunner) { prodRunner = cliProdRunner; } else if (configProdRunner) { prodRunner = configProdRunner; info(`Using prod runner from lt.config: ${prodRunner}`); } else { prodRunner = yield helper.getInput('', { initial: 'docker-landing', name: 'runner for production (tag in .gitlab-ci.yml, e.g. docker-landing)', }); } if (!prodRunner) { return; } } // Set up initial props (to pass into templates) const nameCamel = camelCase(name); const nameKebab = kebabCase(name); const namePascal = pascalCase(name); // Check if directory const cwd = filesystem.cwd(); const generateSpinner = spin('Generate files'); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'scripts', 'build-push.sh'), template: 'deployment/scripts/build-push.sh.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'scripts', 'deploy.sh'), template: 'deployment/scripts/deploy.sh.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'Dockerfile'), template: 'deployment/Dockerfile.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'Dockerfile.app'), template: 'deployment/Dockerfile.app.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'docker-compose.dev.yml'), template: 'deployment/docker-compose.dev.yml.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'docker-compose.test.yml'), template: 'deployment/docker-compose.test.yml.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal }, target: (0, path_1.join)(cwd, 'docker-compose.prod.yml'), template: 'deployment/docker-compose.prod.yml.ejs', }); if (gitHub) { yield template.generate({ props: { nameCamel, nameKebab, namePascal, url: domain }, target: (0, path_1.join)(cwd, '.github', 'workflows', 'pre-release.yml'), template: 'deployment/.github/workflows/pre-release.yml.ejs', }); yield template.generate({ props: { nameCamel, nameKebab, namePascal, url: domain }, target: (0, path_1.join)(cwd, '.github', 'workflows', 'release.yml'), template: 'deployment/.github/workflows/release.yml.ejs', }); } if (gitLab) { yield template.generate({ props: { nameCamel, nameKebab, namePascal, prodRunner, testRunner, url: domain }, target: (0, path_1.join)(cwd, '.gitlab-ci.yml'), template: 'deployment/.gitlab-ci.yml.ejs', }); } generateSpinner.succeed('Files generated'); const environmentsSpinner = spin('Update app environment files'); const prodEnv = yield filesystem.exists('projects/app/src/environments/environment.prod.ts'); if (prodEnv) { yield patching.patch('projects/app/src/environments/environment.prod.ts', { insert: `https://api.${domain}`, replace: new RegExp('http://127.0.0.1:3000', 'g'), }); yield patching.patch('projects/app/src/environments/environment.prod.ts', { insert: `wss://api.${domain}`, replace: new RegExp('ws://127.0.0.1:3000', 'g'), }); yield patching.patch('projects/app/src/environments/environment.prod.ts', { insert: `https://${domain}`, replace: new RegExp('http://127.0.0.1:4200', 'g'), }); } else { info('Missing projects/app/src/environments/environment.prod.ts'); } const testEnv = yield filesystem.exists('projects/app/src/environments/environment.test.ts'); if (testEnv) { yield patching.patch('projects/app/src/environments/environment.test.ts', { insert: `https://api.test.${domain}`, replace: new RegExp('http://127.0.0.1:3000', 'g'), }); yield patching.patch('projects/app/src/environments/environment.test.ts', { insert: `wss://api.test.${domain}`, replace: new RegExp('ws://127.0.0.1:3000', 'g'), }); yield patching.patch('projects/app/src/environments/environment.test.ts', { insert: `https://test.${domain}`, replace: new RegExp('http://127.0.0.1:4200', 'g'), }); } else { info('Missing projects/app/src/environments/environment.test.ts'); } environmentsSpinner.succeed('App environment files updated'); // We're done, so show what to do next info(''); success(`Generated deployment for ${namePascal} in ${helper.msToMinutesAndSeconds(timer())}m.`); info(''); // Hint for CI/CD const subDomains = ['www', 'api', 'test', 'www.test', 'api.test']; let urlStr = `\n- ${domain}`; for (const sub of subDomains) { urlStr += `\n- ${sub}.${domain}`; } success(`HINT: please initialize following Domains before running the CI/CD pipeline:${urlStr}`); info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); } // For tests return `new deployment ${name}`; }), }; exports.default = NewCommand;