@lenne.tech/cli
Version:
lenne.Tech CLI: lt
289 lines (288 loc) • 13.3 kB
JavaScript
"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;