UNPKG

@cto.ai/ops-rc

Version:

💻 CTO.ai Ops - The CLI built for Teams 🚀

140 lines (137 loc) • 6.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); /** * Author: Brett Campbell (brett@hackcapital.com) * Date: Saturday, 6th April 2019 10:39:58 pm * Last Modified By: Brett Campbell (brett@hackcapital.com) * Last Modified Time: Saturday, 6th April 2019 10:40:00 pm * * DESCRIPTION * */ const sdk_1 = require("@cto.ai/sdk"); const fs = tslib_1.__importStar(require("fs-extra")); const path = tslib_1.__importStar(require("path")); const base_1 = tslib_1.__importStar(require("./../base")); const opConfig_1 = require("./../constants/opConfig"); const CustomErrors_1 = require("./../errors/CustomErrors"); const utils_1 = require("./../utils"); const OpsYml_1 = require("./../types/OpsYml"); const templateUtils_1 = require("./../utils/templateUtils"); class Build extends base_1.default { constructor() { super(...arguments); this.resolvePath = (opPath) => { return opPath ? path.resolve(process.cwd(), opPath) : process.cwd(); }; this.getOpsFromFileSystem = async (opPath) => { const manifest = await fs .readFile(path.join(opPath, opConfig_1.OP_FILE), 'utf8') .catch(err => { this.debug('%O', err); throw new CustomErrors_1.FileNotFoundError(err, opPath, opConfig_1.OP_FILE); }); if (manifest.length == 0) { throw new CustomErrors_1.NoLocalOpsOrPipelinesFound(); } const { ops, pipelines, services } = utils_1.parseYaml(manifest); if (ops.length == 0 && pipelines.length == 0 && services.length == 0) { throw new CustomErrors_1.NoLocalOpsOrPipelinesFound(); } return { ops, pipelines, services }; }; this.convertPipelinesToOps = async (pipelines, config) => { const ops = []; for (const pipeline of pipelines) { for (let jobIndex = 0; jobIndex < pipeline.jobs.length; jobIndex++) { const job = pipeline.jobs[jobIndex]; const { name, description } = job; const templateDir = path.resolve(__dirname, '../templates/command/Bash'); const destDir = '/tmp/' + name; //remove temp dir if exists fs.removeSync(destDir); await templateUtils_1.copyTemplate(templateDir, destDir); await templateUtils_1.customizeManifest('command', { name, description, version: pipeline.version }, destDir); const jobContents = await this.createJobContents(config, pipeline, job, jobIndex); this.writeJobContents(jobContents, destDir + '/main.sh'); this.addJobPackages(job.packages, destDir + '/Dockerfile'); let jobOp = await this.getOpsFromFileSystem(destDir); //set op type as 'job' jobOp.ops[0].type = opConfig_1.JOB_TYPE; ops.push(jobOp.ops[0]); } } return ops; }; this.createJobContents = async (config, pipeline, job, jobIndex) => { const { team: { id: teamId }, } = config; const { name: pipelineName } = pipeline; const { name: jobName } = job; return `#!/bin/bash set -euo pipefail IFS=$'\n\t' ${job.steps.join('\n')} `; }; this.addJobPackages = (packages, targetFile) => { if (packages !== undefined && packages.length > 0) { const installStr = `\nRUN apt-get update && apt-get -y install ${packages.join(' ')} && rm -r /var/cache/apt/archives/`; fs.appendFileSync(targetFile, installStr); } }; this.writeJobContents = (contents, targetFile) => { fs.removeSync(targetFile); fs.writeFileSync(targetFile, contents); }; this.selectOpToBuild = async (ops, pipelines) => { if (ops.length === 1) { return ops; } // NOTE: this causes unexpected behaviour if there are commands and pipelines if (pipelines.length > 0) { return ops; } const { opsToBuild } = await sdk_1.ux.prompt({ type: 'checkbox', name: 'opsToBuild', message: `\n Which ops would you like to build ${sdk_1.ux.colors.reset.green('→')}`, choices: ops.map(op => { return { value: op, name: `${op.name} - ${op.description}`, }; }), validate: input => input.length > 0, }); return opsToBuild; }; this.executeOpService = async (opsToBuild, opPath, config) => { await this.services.opService.opsBuildLoop(opsToBuild, opPath, config); }; } async run() { const { args: { path }, } = this.parse(Build); try { await this.isLoggedIn(); const opPath = this.resolvePath(path); const inputManifest = await this.getOpsFromFileSystem(opPath); const pipelineOps = await this.convertPipelinesToOps(inputManifest.pipelines, this.state.config); const serviceOps = OpsYml_1.convertServicesToOps(inputManifest.services); const opsToBuild = await this.selectOpToBuild([...inputManifest.ops, ...pipelineOps, ...serviceOps], inputManifest.pipelines); await this.executeOpService(opsToBuild, opPath, this.state.config); } catch (err) { this.debug('%O', err); this.config.runHook('error', { err, accessToken: this.accessToken }); } } } exports.default = Build; Build.description = 'Build your op for sharing.'; Build.flags = { help: base_1.flags.help({ char: 'h' }), }; Build.args = [ { name: 'path', description: 'Path to the op you want to build.' }, ];