UNPKG

@cto.ai/ops-rc

Version:

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

135 lines (134 loc) 5.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseYaml = void 0; const tslib_1 = require("tslib"); const sdk_1 = require("@cto.ai/sdk"); const yaml = tslib_1.__importStar(require("yaml")); const CustomErrors_1 = require("./../errors/CustomErrors"); const opConfig_1 = require("../constants/opConfig"); const { white, callOutCyan } = sdk_1.ux.colors; const checkCommandNecessryFields = (commandContents) => { if (!commandContents.run || typeof commandContents.run !== 'string') { throw new CustomErrors_1.IncompleteOpsYml('The run command must be included as a string'); } }; const checkWorkflowNecessryFields = (workflowContents) => { if (!workflowContents.steps || !workflowContents.steps.length) { throw new CustomErrors_1.IncompleteOpsYml('The run command must be included as a string'); } workflowContents.steps.forEach(step => { if (!step || typeof step !== 'string') { throw new CustomErrors_1.IncompleteOpsYml('Each step should be a non-empty string'); } }); }; const checkJobProperites = job => { if (!job.name) { throw new CustomErrors_1.IncompleteOpsYml('Each pipeline job name should be a non-empty string'); } if (!job.description) { throw new CustomErrors_1.IncompleteOpsYml('Each pipeline job description should be a non-empty string'); } }; const formatPipeline = (pipelines) => { pipelines.forEach(pipeline => { const nameAndVersion = _splitOpNameAndVersion(pipeline); pipeline.name = nameAndVersion[0]; if (!nameAndVersion[1] || nameAndVersion[1] === '') { pipeline.version = '0.1.0'; //default version } else { pipeline.version = nameAndVersion[1]; } }); }; const checkRequiredJobFields = (pipelines) => { pipelines.forEach(pipeline => { if (!pipeline.version) { throw new CustomErrors_1.IncompleteOpsYml('Each pipeline a valid version string'); } if (!pipeline.jobs || pipeline.jobs.length < 1) { throw new CustomErrors_1.IncompleteOpsYml('Each pipeline requires at least one valid job'); } pipeline.jobs.some(checkJobProperites); }); }; const checkOpNecessaryFields = (opContents) => { if (!opContents.name || typeof opContents.name !== 'string') { throw new CustomErrors_1.IncompleteOpsYml('Op name must be a non-empty string'); } if (!opContents.description || typeof opContents.description !== 'string') { throw new CustomErrors_1.IncompleteOpsYml('Op description must be a non-empty string'); } if (!opContents.isPublic === undefined || typeof opContents.isPublic !== 'boolean') { throw new CustomErrors_1.IncompleteOpsYml('Your ops.yml file is missing the public field, please add `public:false` to publish your op as private'); } return true; }; const _splitOpNameAndVersion = (op) => { // Pass through to the (later) validation code if (!op.name || typeof op.name != 'string') { return ['', '']; } const splits = op.name.split(':'); return [splits[0], splits[1]]; }; const formatAndCheckService = (service) => { let [opName, opVersion] = _splitOpNameAndVersion(service); if (!opVersion) { throw new CustomErrors_1.IncompleteOpsYml(`Service ${opName} must have a version`); } if (!service.run || typeof service.run !== 'string') { throw new CustomErrors_1.IncompleteOpsYml(`The run command must be included as a string for service ${opName}`); } return Object.assign(Object.assign({}, service), { name: opName, version: opVersion, type: opConfig_1.SERVICE_TYPE }); }; exports.parseYaml = (manifest) => { // This will always return the default values of these variables, even if manifest is empty const { version, ops = [], workflows = [], pipelines = [], commands = [], services = [], } = manifest && yaml.parse(manifest); if (ops.length > 0) { console.log(white(`It looks like your ops.yml is a little out of date.\nYou should replace the ${callOutCyan('ops')} field with ${callOutCyan('commands')}.\nLearn more here ${sdk_1.ux.url('https://cto.ai/docs/developing-ops/configuring-ops', 'https://cto.ai/docs/developing-ops/configuring-ops')}`)); } let yamlContents = { version, ops: [], pipelines: [], workflows: [], services: services.map(formatAndCheckService), }; yamlContents.ops = [...ops, ...commands].map(op => { const newCommand = formatRequiredFields(op, opConfig_1.COMMAND_TYPE); checkOpNecessaryFields(newCommand); checkCommandNecessryFields(newCommand); return newCommand; }); yamlContents.workflows = workflows.map(wf => { const newWf = formatRequiredFields(wf, opConfig_1.WORKFLOW_TYPE); checkOpNecessaryFields(newWf); checkWorkflowNecessryFields(newWf); return newWf; }); if (pipelines.length > 0) { formatPipeline(pipelines); checkRequiredJobFields(pipelines); yamlContents.pipelines = pipelines; } return yamlContents; }; const defaultVersion = `0.1.0`; const defaultVersionLog = `\nℹ️ It looks like your ops.yml is a little out of date. It does not have a version, we are setting the default version to ${sdk_1.ux.colors.callOutCyan(defaultVersion)}. Learn more ${sdk_1.ux.url('here', 'https://cto.ai/docs/developing-ops/configuring-ops')}.\n`; const formatRequiredFields = (opOrWorkflow, type) => { const newOp = Object.assign({}, opOrWorkflow); newOp.isPublic = newOp.public; delete newOp.public; let [opName, opVersion] = _splitOpNameAndVersion(opOrWorkflow); if (!opVersion) { opVersion = defaultVersion; console.log(defaultVersionLog); } newOp.name = opName; newOp.version = opVersion; newOp.type = type; return newOp; };