UNPKG

10.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const sdk_1 = require("@cto.ai/sdk");
5const fs = tslib_1.__importStar(require("fs-extra"));
6const path = tslib_1.__importStar(require("path"));
7const base_1 = tslib_1.__importStar(require("../base"));
8const env_1 = require("../constants/env");
9const opConfig_1 = require("../constants/opConfig");
10const CustomErrors_1 = require("../errors/CustomErrors");
11const asyncPipe_1 = require("../utils/asyncPipe");
12const get_docker_1 = tslib_1.__importDefault(require("../utils/get-docker"));
13const validate_1 = require("../utils/validate");
14const utils_1 = require("../utils");
15class Publish extends base_1.default {
16 constructor() {
17 super(...arguments);
18 this.resolvePath = async (opPath) => {
19 return path.resolve(process.cwd(), opPath);
20 };
21 this.checkDocker = async (opPath) => {
22 const docker = await get_docker_1.default(this, 'publish');
23 if (!docker) {
24 throw new Error('No docker');
25 }
26 return { opPath, docker };
27 };
28 this.determineQuestions = async (inputs) => {
29 const { opsAndWorkflows } = await sdk_1.ux.prompt({
30 type: 'list',
31 name: 'opsAndWorkflows',
32 message: `\n Which would you like to publish ${sdk_1.ux.colors.reset.green('ā†’')}`,
33 choices: [
34 { name: 'Commands', value: opConfig_1.COMMAND },
35 { name: 'Workflows', value: opConfig_1.WORKFLOW },
36 'Both',
37 ],
38 afterMessage: `${sdk_1.ux.colors.reset.green('āœ“')}`,
39 });
40 return Object.assign({}, inputs, { opsAndWorkflows });
41 };
42 this.getOpsAndWorkFlows = async ({ opPath, opsAndWorkflows, docker, }) => {
43 const manifest = await fs
44 .readFile(path.join(opPath, opConfig_1.OP_FILE), 'utf8')
45 .catch((err) => {
46 this.debug('%O', err);
47 throw new CustomErrors_1.FileNotFoundError(err, opPath, opConfig_1.OP_FILE);
48 });
49 if (!manifest)
50 throw new CustomErrors_1.NoLocalOpsFound();
51 const { ops, version, workflows } = utils_1.parseYaml(manifest);
52 if (!ops && (opsAndWorkflows === opConfig_1.COMMAND || opsAndWorkflows === 'Both')) {
53 throw new CustomErrors_1.NoLocalOpsFound();
54 }
55 if (!workflows &&
56 (opsAndWorkflows === opConfig_1.WORKFLOW || opsAndWorkflows === 'Both')) {
57 throw new CustomErrors_1.NoWorkflowsFound();
58 }
59 return { ops, workflows, docker, version, opsAndWorkflows };
60 };
61 this.selectOpsAndWorkFlows = async ({ ops, workflows, version, docker, opsAndWorkflows, }) => {
62 switch (opsAndWorkflows) {
63 case opConfig_1.COMMAND:
64 ops = await this.selectOps(ops);
65 break;
66 case opConfig_1.WORKFLOW:
67 workflows = await this.selectWorkflows(workflows);
68 break;
69 default:
70 ops = await this.selectOps(ops);
71 workflows = await this.selectWorkflows(workflows);
72 }
73 return { ops, workflows, version, docker, opsAndWorkflows };
74 };
75 this.selectOps = async (ops) => {
76 if (ops.length <= 1) {
77 return ops;
78 }
79 const answers = await sdk_1.ux.prompt({
80 type: 'checkbox',
81 name: 'ops',
82 message: `\n Which ops would you like to publish ${sdk_1.ux.colors.reset.green('ā†’')}`,
83 choices: ops.map(op => {
84 return {
85 value: op,
86 name: `${op.name} - ${op.description}`,
87 };
88 }),
89 validate: input => input.length > 0,
90 });
91 return answers.ops;
92 };
93 this.selectWorkflows = async (workflows) => {
94 if (workflows.length <= 1) {
95 return workflows;
96 }
97 const answers = await sdk_1.ux.prompt({
98 type: 'checkbox',
99 name: 'workflows',
100 message: `\n Which workflows would you like to publish ${sdk_1.ux.colors.reset.green('ā†’')}`,
101 choices: workflows.map(workflow => {
102 return {
103 value: workflow,
104 name: `${workflow.name} - ${workflow.description}`,
105 };
106 }),
107 validate: input => input.length > 0,
108 });
109 return answers.workflows;
110 };
111 this.getRegistryAuth = async (name, version) => {
112 try {
113 const registryAuth = await this.services.registryAuthService.create(this.accessToken, this.team.name, name, version, false, true);
114 return registryAuth;
115 }
116 catch (err) {
117 throw new CustomErrors_1.CouldNotGetRegistryToken(err);
118 }
119 };
120 this.publishOpsAndWorkflows = async (inputs) => {
121 switch (inputs.opsAndWorkflows) {
122 case opConfig_1.COMMAND:
123 await this.opsPublishLoop(inputs);
124 break;
125 case opConfig_1.WORKFLOW:
126 await this.workflowsPublishLoop(inputs);
127 break;
128 default:
129 await this.opsPublishLoop(inputs);
130 await this.workflowsPublishLoop(inputs);
131 }
132 };
133 this.opsPublishLoop = async ({ ops, version }) => {
134 for (const op of ops) {
135 if (!validate_1.isValidOpName(op.name)) {
136 throw new CustomErrors_1.InvalidInputCharacter('Op Name');
137 }
138 // TODO: Change 'latest' to the user's intended version once it is in place
139 const opName = utils_1.getOpImageTag(this.team.name, op.name, 'latest', op.isPublic);
140 const localImage = await this.services.imageService.checkLocalImage(`${env_1.OPS_REGISTRY_HOST}/${opName}`);
141 if (!localImage) {
142 throw new CustomErrors_1.DockerPublishNoImageFound(op.name, this.team.name);
143 }
144 const { data: apiOp, } = await this.services.publishService.publishOpToAPI(op, version, this.team.id, this.accessToken, this.services.api);
145 // TODO: Setting version as 'platform version' for now
146 // but it has to be changed to op.version when versioning is added
147 const registryAuth = await this.getRegistryAuth(op.name, version);
148 await this.services.publishService.publishOpToRegistry(apiOp, registryAuth, this.team.name, this.accessToken, this.services.registryAuthService, version);
149 this.sendAnalytics('op', apiOp);
150 }
151 };
152 this.workflowsPublishLoop = async ({ workflows, version, }) => {
153 for (const workflow of workflows) {
154 if (workflow.remote) {
155 const newSteps = [];
156 for (const step of workflow.steps) {
157 let newStep = '';
158 if (await this.services.buildStepService.isGlueCode(step)) {
159 const opPath = path.resolve(__dirname, './../templates/workflowsteps/js/');
160 newStep = await this.services.buildStepService.buildAndPublishGlueCode(step, this.team.id, this.team.name, this.accessToken, opPath, this.user, this.services.publishService, this.services.opService, this.services.api, this.services.registryAuthService, this.state.config, workflow.isPublic, version);
161 newSteps.push(newStep);
162 }
163 else {
164 if (!this.services.buildStepService.isOpRun(step)) {
165 this.debug('InvalidStepsFound - Step:', step);
166 throw new CustomErrors_1.InvalidStepsFound(step);
167 }
168 newSteps.push(step);
169 }
170 }
171 workflow.steps = newSteps;
172 }
173 try {
174 const { data: apiWorkflow, } = await this.services.api.create(opConfig_1.WORKFLOW_ENDPOINT, Object.assign({}, workflow, { version, teamID: this.team.id }), {
175 headers: {
176 Authorization: this.accessToken,
177 },
178 });
179 this.log(`\nšŸ™Œ ${sdk_1.ux.colors.callOutCyan(apiWorkflow.name)} has been published! \n`);
180 // this.sendAnalytics('workflow', apiWorkflow)
181 }
182 catch (err) {
183 this.debug('%O', err);
184 throw new CustomErrors_1.CouldNotCreateWorkflow(err.message);
185 }
186 }
187 };
188 this.sendAnalytics = async (publishType, opOrWorkflow) => {
189 this.services.analytics.track({
190 userId: this.user.email,
191 event: 'Ops CLI Publish',
192 properties: {
193 email: this.user.email,
194 username: this.user.username,
195 type: publishType,
196 name: opOrWorkflow.name,
197 description: opOrWorkflow.description,
198 image: `${env_1.OPS_REGISTRY_HOST}/${opOrWorkflow.id.toLowerCase()}`,
199 tag: 'latest',
200 },
201 });
202 };
203 }
204 async run() {
205 try {
206 await this.isLoggedIn();
207 const { args } = this.parse(Publish);
208 const publishPipeline = asyncPipe_1.asyncPipe(this.resolvePath, this.checkDocker, this.determineQuestions, this.getOpsAndWorkFlows, this.selectOpsAndWorkFlows, this.publishOpsAndWorkflows);
209 await publishPipeline(args.path);
210 }
211 catch (err) {
212 this.debug('%O', err);
213 this.config.runHook('error', { err, accessToken: this.accessToken });
214 }
215 }
216}
217Publish.description = 'Publish an op to a team.';
218Publish.flags = {
219 help: base_1.flags.help({ char: 'h' }),
220};
221Publish.args = [
222 {
223 name: 'path',
224 description: 'Path to the op you want to publish.',
225 required: true,
226 },
227];
228exports.default = Publish;