contensis-cli 1.0.0-beta.95 → 1.0.0-beta.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,14 @@
1
1
  import inquirer from 'inquirer';
2
2
  import { JSONPath, JSONPathOptions } from 'jsonpath-plus';
3
+ import { Document } from 'yaml';
3
4
  import {
4
5
  GitHubActionPushBlockJob,
5
6
  GitHubActionPushBlockJobStep,
7
+ GitLabPushBlockJobStage,
6
8
  } from '~/models/DevService';
7
9
  import { readFile } from '~/providers/file-provider';
8
10
  import ContensisDev from '~/services/ContensisDevService';
9
11
  import { diffFileContent } from '~/util/diff';
10
- import { GitHelper } from '~/util/git';
11
12
  import { logError } from '~/util/logger';
12
13
  import { normaliseLineEndings } from '~/util/os';
13
14
  import { parseYamlDocument, validateWorkflowYaml } from '~/util/yaml';
@@ -19,252 +20,410 @@ type MappedWorkflowOutput = {
19
20
  };
20
21
 
21
22
  export const mapCIWorkflowContent = async (
22
- cli: ContensisDev,
23
- git: GitHelper
23
+ cli: ContensisDev
24
24
  ): Promise<MappedWorkflowOutput | undefined> => {
25
25
  // get existing workflow file
26
- const workflowFile = readFile(git.ciFilePath);
26
+ const workflowFile = readFile(cli.git.ciFilePath);
27
27
  if (!workflowFile) return undefined;
28
28
 
29
- const blockId = git.name;
30
- if (git.type === 'github') {
31
- const addGitHubActionJobStep: GitHubActionPushBlockJobStep = {
32
- name: 'Push block to Contensis',
33
- id: 'push-block',
34
- uses: 'contensis/block-push@v1',
35
- with: {
36
- 'block-id': blockId,
37
- // 'image-uri': '${{ steps.build.outputs.image-uri }}',
38
- alias: cli.currentEnv,
39
- 'project-id': cli.currentProject,
40
- 'client-id': '${{ secrets.CONTENSIS_CLIENT_ID }}',
41
- 'shared-secret': '${{ secrets.CONTENSIS_SHARED_SECRET }}',
42
- },
43
- };
29
+ const blockId = cli.git.name;
44
30
 
45
- // parse yaml to js
46
- const workflowDoc = parseYamlDocument(workflowFile);
47
- const workflowJS = workflowDoc.toJS();
48
- const setWorkflowElement = (path: string | any[], value: any) => {
49
- const findPath =
50
- typeof path === 'string' && path.includes('.')
51
- ? path
52
- .split('.')
53
- .map(p => (Number(p) || Number(p) !== 0 ? p : Number(p)))
54
- : path;
55
-
56
- if (workflowDoc.hasIn(findPath)) {
57
- workflowDoc.setIn(findPath, value);
58
- } else {
59
- workflowDoc.addIn(findPath, value);
60
- // }
61
- }
31
+ // parse yaml to js
32
+ const workflowDoc = parseYamlDocument(workflowFile);
33
+ const workflowJS = workflowDoc.toJS();
34
+
35
+ if (cli.git.type === 'github') {
36
+ const newWorkflow = await mapGitHubActionCIWorkflowContent(
37
+ cli,
38
+ blockId,
39
+ workflowDoc,
40
+ workflowJS
41
+ );
42
+ return {
43
+ existingWorkflow: workflowFile,
44
+ newWorkflow,
45
+ diff: diffFileContent(workflowFile, newWorkflow),
62
46
  };
63
- const findExistingJobSteps = (
64
- path: string,
65
- resultType: JSONPathOptions['resultType']
66
- ) => {
67
- const existingJobStep = JSONPath({
68
- path,
69
- json: workflowJS,
70
- resultType: resultType,
71
- });
72
-
73
- return existingJobStep;
47
+ } else if (cli.git.type === 'gitlab') {
48
+ const newWorkflow = await mapGitLabCIWorkflowContent(
49
+ cli,
50
+ blockId,
51
+ workflowDoc,
52
+ workflowJS
53
+ );
54
+ return {
55
+ existingWorkflow: workflowFile,
56
+ newWorkflow,
57
+ diff: diffFileContent(workflowFile, newWorkflow),
74
58
  };
59
+ }
60
+ };
75
61
 
76
- // look for line in job
77
- // jobs.x.steps[uses: contensis/block-push]
78
- const existingJobStep = findExistingJobSteps(
79
- git.type === 'github'
80
- ? '$.jobs..steps.*[?(@property === "uses" && @.match(/^contensis\\/block-push/i))]^'
81
- : // TODO: add jsonpath for gitlab file
82
- '',
83
- 'all'
62
+ const findExistingJobSteps = (
63
+ path: string,
64
+ json: any,
65
+ resultType: JSONPathOptions['resultType']
66
+ ) => {
67
+ const existingJobStep = JSONPath({
68
+ path,
69
+ json,
70
+ resultType: resultType,
71
+ });
72
+
73
+ return existingJobStep;
74
+ };
75
+
76
+ const setWorkflowElement = (
77
+ workflowDoc: Document,
78
+ path: string | any[],
79
+ value: any
80
+ ) => {
81
+ const findPath =
82
+ typeof path === 'string' && path.includes('.')
83
+ ? path.split('.').map(p => (Number(p) || Number(p) !== 0 ? p : Number(p)))
84
+ : path;
85
+
86
+ if (workflowDoc.hasIn(findPath)) {
87
+ workflowDoc.setIn(findPath, value);
88
+ } else {
89
+ workflowDoc.addIn(findPath, value);
90
+ }
91
+ };
92
+
93
+ const mapGitLabCIWorkflowContent = async (
94
+ cli: ContensisDev,
95
+ blockId: string,
96
+ workflowDoc: Document,
97
+ workflowJS: any
98
+ ) => {
99
+ const addGitLabJobStage: GitLabPushBlockJobStage = {
100
+ stage: 'push-block',
101
+ variables: {
102
+ block_id: blockId,
103
+ alias: cli.currentEnv,
104
+ project_id: cli.currentProject,
105
+ client_id: '$CONTENSIS_CLIENT_ID',
106
+ shared_secret: '$CONTENSIS_SHARED_SECRET',
107
+ },
108
+ };
109
+
110
+ const addAppImageUri = async () => {
111
+ // Look in document level "variables"
112
+ const appImageUri = await determineAppImageUri(
113
+ cli,
114
+ Object.entries(workflowJS.variables || {}),
115
+ '$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME/app:build-$CI_PIPELINE_IID'
84
116
  );
85
117
 
86
- const addAppImageUri = async () => {
87
- // Look in document level "env" vars
88
- const appImageUri = await determineAppImageUri(
89
- cli,
90
- Object.entries(workflowJS.env || {})
118
+ if (appImageUri.addVar)
119
+ setWorkflowElement(
120
+ workflowDoc,
121
+ `variables.${appImageUri.var}`,
122
+ appImageUri.uri
91
123
  );
92
124
 
93
- if (appImageUri.addVar)
94
- setWorkflowElement(`env.${appImageUri.var}`, appImageUri.uri);
95
- // workflowDoc.addIn(['env'], { [appImageUri.var]: appImageUri.uri });
125
+ if (appImageUri.var)
126
+ addGitLabJobStage.variables['image_uri'] = `\$${appImageUri.var}`;
127
+ };
96
128
 
97
- if (appImageUri.var)
98
- addGitHubActionJobStep.with[
99
- 'image-uri'
100
- ] = `\${{ env.${appImageUri.var} }}`;
101
- };
129
+ // look for line in job
130
+ // jobname[stage: push-block]
131
+ const existingJobStep = findExistingJobSteps(
132
+ '$..[?(@property === "stage" && @.match(/^push-block/i))]^',
133
+ workflowJS,
134
+ 'all'
135
+ );
102
136
 
103
- // update job step
104
- if (existingJobStep.length) {
105
- //cli.log.json(existingJobStep);
137
+ // update job step
138
+ if (existingJobStep.length) {
139
+ // cli.log.json(existingJobStep);
140
+
141
+ // The [0] index means we're only looking at updating the first instance in the file
142
+ const step = existingJobStep[0];
143
+
144
+ // Path looks like this "$['job_name']"
145
+ // We want it to look like this "job_name"
146
+ const stepPath = step.path
147
+ .replace('$[', '')
148
+ .replaceAll('][', '.')
149
+ .replace(']', '')
150
+ .replaceAll("'", '');
151
+
152
+ cli.log.info(
153
+ `Found existing Job step:
154
+ ${stepPath}
155
+ stage: ${step.value.stage}\n`
156
+ );
106
157
 
107
- // The [0] index means we're only looking at updating the first instance in the file
108
- const step = existingJobStep[0];
158
+ setWorkflowElement(
159
+ workflowDoc,
160
+ `${stepPath}.variables.alias`,
161
+ cli.currentEnv
162
+ );
163
+ setWorkflowElement(
164
+ workflowDoc,
165
+ `${stepPath}.variables.project_id`,
166
+ cli.currentProject
167
+ );
168
+ setWorkflowElement(workflowDoc, `${stepPath}.variables.block_id`, blockId);
109
169
 
110
- // Path looks like this "$['jobs']['build']['steps'][3]"
111
- // We want it to look like this "jobs.build.steps.3"
112
- const stepPath = step.path
113
- .replace('$[', '')
114
- .replaceAll('][', '.')
115
- .replace(']', '')
116
- .replaceAll("'", '');
170
+ // This is likely not needed when updating an existing push-block job step
171
+ // we are assuming this is a forked/copied workflow with an already working image-uri reference
172
+ // await addAppImageUri();
117
173
 
118
- cli.log.info(
119
- `Found existing Job step: ${stepPath}
120
- - name: ${step.value.name}
121
- id: ${step.value.id}\n`
122
- );
174
+ setWorkflowElement(
175
+ workflowDoc,
176
+ `${stepPath}.variables.client_id`,
177
+ '$CONTENSIS_CLIENT_ID'
178
+ );
179
+ setWorkflowElement(
180
+ workflowDoc,
181
+ `${stepPath}.variables.shared_secret`,
182
+ '$CONTENSIS_SHARED_SECRET'
183
+ );
184
+ } else {
185
+ // create job with push step
186
+
187
+ // Does a series of checks and prompts to determine the correct image-uri
188
+ // for the app container build
189
+ await addAppImageUri();
190
+
191
+ // Add the new "job" to the Yaml Document
192
+ workflowDoc.addIn(['stages'], 'push-block');
193
+ workflowDoc.addIn([], {
194
+ key: 'push-to-contensis',
195
+ value: addGitLabJobStage,
196
+ });
197
+ setWorkflowElement(
198
+ workflowDoc,
199
+ `include`,
200
+ 'https://gitlab.zengenti.com/ops/contensis-ci/-/raw/main/push-block.yml'
201
+ );
202
+ }
123
203
 
124
- setWorkflowElement(`${stepPath}.with.alias`, cli.currentEnv);
125
- setWorkflowElement(`${stepPath}.with.project-id`, cli.currentProject);
126
- setWorkflowElement(`${stepPath}.with.block-id`, blockId);
204
+ cli.log.debug(`New file content to write\n\n${workflowDoc}`);
127
205
 
128
- // This is likely not needed when updating an existing push-block job step
129
- // we are assuming this is a forked/copied workflow with an already working image-uri reference
130
- // await addAppImageUri();
206
+ const newWorkflow = normaliseLineEndings(
207
+ workflowDoc.toString({ lineWidth: 0 })
208
+ );
131
209
 
210
+ return newWorkflow;
211
+ };
212
+
213
+ const mapGitHubActionCIWorkflowContent = async (
214
+ cli: ContensisDev,
215
+ blockId: string,
216
+ workflowDoc: Document,
217
+ workflowJS: any
218
+ ) => {
219
+ const addGitHubActionJobStep: GitHubActionPushBlockJobStep = {
220
+ name: 'Push block to Contensis',
221
+ id: 'push-block',
222
+ uses: 'contensis/block-push@v1',
223
+ with: {
224
+ 'block-id': blockId,
225
+ // 'image-uri': '${{ steps.build.outputs.image-uri }}',
226
+ alias: cli.currentEnv,
227
+ 'project-id': cli.currentProject,
228
+ 'client-id': '${{ secrets.CONTENSIS_CLIENT_ID }}',
229
+ 'shared-secret': '${{ secrets.CONTENSIS_SHARED_SECRET }}',
230
+ },
231
+ };
232
+
233
+ const addAppImageUri = async () => {
234
+ // Look in document level "env" vars
235
+ const appImageUri = await determineAppImageUri(
236
+ cli,
237
+ Object.entries(workflowJS.env || {}),
238
+ 'ghcr.io/${{ github.repository }}/${{ github.ref_name }}/app:build-${{ github.run_number }}'
239
+ );
240
+
241
+ if (appImageUri.addVar)
132
242
  setWorkflowElement(
133
- `${stepPath}.with.client-id`,
134
- '${{ secrets.CONTENSIS_CLIENT_ID }}'
135
- );
136
- setWorkflowElement(
137
- `${stepPath}.with.shared-secret`,
138
- '${{ secrets.CONTENSIS_SHARED_SECRET }}'
243
+ workflowDoc,
244
+ `env.${appImageUri.var}`,
245
+ appImageUri.uri
139
246
  );
140
- } else {
141
- // create job with push step
142
-
143
- // is there already a job with a property name containing "build"?
144
- const existingBuildJobStep = findExistingJobSteps(
145
- git.type === 'github'
146
- ? '$.jobs[?(@property.match(/build/i))]'
147
- : // TODO: add jsonpath for gitlab file
148
- '',
149
- 'all'
150
- ) as JSONPathOptions[]; // This isn't the correct type for this object
151
-
152
- let needs: string | undefined;
153
- // There are multiple jobs called *build*
154
- if (existingBuildJobStep.length > 1) {
155
- // prompt which build job we should depend on before pushing the block
156
- const choices = existingBuildJobStep.map(s => s.parentProperty);
157
- choices.push(new inquirer.Separator() as any);
158
- choices.push('none');
159
-
160
- ({ needs } = await inquirer.prompt([
161
- {
162
- type: 'list',
163
- prefix: 'āŒ›',
164
- message: cli.messages.devinit.ciMultipleBuildJobChoices(),
165
- name: 'needs',
166
- choices,
167
- default: choices.find(
168
- s => typeof s === 'string' && s.includes('docker')
169
- ),
170
- },
171
- ]));
172
- cli.log.raw('');
173
- } else if (existingBuildJobStep.length === 1)
174
- // Exactly one job step found containing a property name of *build*
175
- // we'll assume that is the one the push-block job depends on
176
- needs = existingBuildJobStep[0].parentProperty;
177
-
178
- if (existingBuildJobStep.length === 0 || needs === 'none') {
179
- // No existing build step found or chosen, offer all job steps in prompt
180
- const choices = Object.keys(workflowJS.jobs);
181
- choices.push(new inquirer.Separator() as any);
182
- choices.push('none');
183
-
184
- ({ needs } = await inquirer.prompt([
185
- {
186
- type: 'list',
187
- prefix: 'āŒ›',
188
- message: cli.messages.devinit.ciMultipleJobChoices(),
189
- name: 'needs',
190
- choices,
191
- default: choices.find(
192
- j => typeof j === 'string' && j.includes('docker')
193
- ),
194
- },
195
- ]));
196
- if (needs === 'none') needs = undefined;
197
- cli.log.raw('');
198
- }
199
-
200
- // Does a series of checks and prompts to determine the correct image-uri
201
- // for the app container build
202
- await addAppImageUri();
203
-
204
- const newJob: GitHubActionPushBlockJob = {
205
- name: 'Deploy container image to Contensis',
206
- 'runs-on': 'ubuntu-latest',
207
- needs,
208
- steps: [addGitHubActionJobStep],
209
- };
210
-
211
- // Add the new "job" to the Yaml Document
212
- workflowDoc.addIn(['jobs'], {
213
- key: 'deploy',
214
- value: newJob,
215
- });
216
- }
247
+ // workflowDoc.addIn(['env'], { [appImageUri.var]: appImageUri.uri });
217
248
 
218
- // Workflow validation provided by @action-validator/core package
219
- const workflowIsValid = validateWorkflowYaml(workflowDoc.toString());
249
+ if (appImageUri.var)
250
+ addGitHubActionJobStep.with[
251
+ 'image-uri'
252
+ ] = `\${{ env.${appImageUri.var} }}`;
253
+ };
220
254
 
221
- // We could expand validation to check for having a build step to wait for
222
- // or if a valid image-uri attribute is set
223
- if (workflowIsValid === true) {
224
- cli.log.success(`GitHub workflow YAML is valid`);
225
- cli.log.debug(
226
- `New file content to write to ${git.ciFilePath}\n\n${workflowDoc}`
227
- );
228
- } else if (Array.isArray(workflowIsValid)) {
229
- // Errors
230
- logError(
231
- [
232
- ...workflowIsValid.map(
233
- res => new Error(`${res.code}: ${res.detail || res.title}`)
255
+ // look for line in job
256
+ // jobs.x.steps[uses: contensis/block-push]
257
+ const existingJobStep = findExistingJobSteps(
258
+ '$.jobs..steps.*[?(@property === "uses" && @.match(/^contensis\\/block-push/i))]^',
259
+ workflowJS,
260
+ 'all'
261
+ );
262
+
263
+ // update job step
264
+ if (existingJobStep.length) {
265
+ //cli.log.json(existingJobStep);
266
+
267
+ // The [0] index means we're only looking at updating the first instance in the file
268
+ const step = existingJobStep[0];
269
+
270
+ // Path looks like this "$['jobs']['build']['steps'][3]"
271
+ // We want it to look like this "jobs.build.steps.3"
272
+ const stepPath = step.path
273
+ .replace('$[', '')
274
+ .replaceAll('][', '.')
275
+ .replace(']', '')
276
+ .replaceAll("'", '');
277
+
278
+ cli.log.info(
279
+ `Found existing Job step: ${stepPath}
280
+ - name: ${step.value.name}
281
+ id: ${step.value.id}\n`
282
+ );
283
+
284
+ setWorkflowElement(workflowDoc, `${stepPath}.with.alias`, cli.currentEnv);
285
+ setWorkflowElement(
286
+ workflowDoc,
287
+ `${stepPath}.with.project-id`,
288
+ cli.currentProject
289
+ );
290
+ setWorkflowElement(workflowDoc, `${stepPath}.with.block-id`, blockId);
291
+
292
+ // This is likely not needed when updating an existing push-block job step
293
+ // we are assuming this is a forked/copied workflow with an already working image-uri reference
294
+ // await addAppImageUri();
295
+
296
+ setWorkflowElement(
297
+ workflowDoc,
298
+ `${stepPath}.with.client-id`,
299
+ '${{ secrets.CONTENSIS_CLIENT_ID }}'
300
+ );
301
+ setWorkflowElement(
302
+ workflowDoc,
303
+ `${stepPath}.with.shared-secret`,
304
+ '${{ secrets.CONTENSIS_SHARED_SECRET }}'
305
+ );
306
+ } else {
307
+ // create job with push step
308
+
309
+ // is there already a job with a property name containing "build"?
310
+ const existingBuildJobStep = findExistingJobSteps(
311
+ '$.jobs[?(@property.match(/build/i))]',
312
+ workflowJS,
313
+ 'all'
314
+ ) as JSONPathOptions[]; // This isn't the correct type for this object
315
+
316
+ let needs: string | undefined;
317
+ // There are multiple jobs called *build*
318
+ if (existingBuildJobStep.length > 1) {
319
+ // prompt which build job we should depend on before pushing the block
320
+ const choices = existingBuildJobStep.map(s => s.parentProperty);
321
+ choices.push(new inquirer.Separator() as any);
322
+ choices.push('none');
323
+
324
+ ({ needs } = await inquirer.prompt([
325
+ {
326
+ type: 'list',
327
+ prefix: 'āŒ›',
328
+ message: cli.messages.devinit.ciMultipleBuildJobChoices(),
329
+ name: 'needs',
330
+ choices,
331
+ default: choices.find(
332
+ s => typeof s === 'string' && s.includes('docker')
234
333
  ),
235
- workflowDoc.toString(),
236
- ],
237
- `GitHub workflow YAML did not pass validation check`
238
- );
334
+ },
335
+ ]));
336
+ cli.log.raw('');
337
+ } else if (existingBuildJobStep.length === 1)
338
+ // Exactly one job step found containing a property name of *build*
339
+ // we'll assume that is the one the push-block job depends on
340
+ needs = existingBuildJobStep[0].parentProperty;
341
+
342
+ if (existingBuildJobStep.length === 0 || needs === 'none') {
343
+ // No existing build step found or chosen, offer all job steps in prompt
344
+ const choices = Object.keys(workflowJS.jobs);
345
+ choices.push(new inquirer.Separator() as any);
346
+ choices.push('none');
347
+
348
+ ({ needs } = await inquirer.prompt([
349
+ {
350
+ type: 'list',
351
+ prefix: 'āŒ›',
352
+ message: cli.messages.devinit.ciMultipleJobChoices(),
353
+ name: 'needs',
354
+ choices,
355
+ default: choices.find(
356
+ j => typeof j === 'string' && j.includes('docker')
357
+ ),
358
+ },
359
+ ]));
360
+ if (needs === 'none') needs = undefined;
361
+ cli.log.raw('');
239
362
  }
240
- const newWorkflow = normaliseLineEndings(
241
- workflowDoc.toString({ lineWidth: 0 })
242
- );
243
363
 
244
- return {
245
- existingWorkflow: workflowFile,
246
- newWorkflow,
247
- diff: diffFileContent(workflowFile, newWorkflow),
364
+ // Does a series of checks and prompts to determine the correct image-uri
365
+ // for the app container build
366
+ await addAppImageUri();
367
+
368
+ const newJob: GitHubActionPushBlockJob = {
369
+ name: 'Deploy container image to Contensis',
370
+ 'runs-on': 'ubuntu-latest',
371
+ needs,
372
+ steps: [addGitHubActionJobStep],
248
373
  };
374
+
375
+ // Add the new "job" to the Yaml Document
376
+ workflowDoc.addIn(['jobs'], {
377
+ key: 'deploy',
378
+ value: newJob,
379
+ });
380
+ }
381
+
382
+ // Workflow validation provided by @action-validator/core package
383
+ const workflowIsValid = validateWorkflowYaml(workflowDoc.toString());
384
+
385
+ // We could expand validation to check for having a build step to wait for
386
+ // or if a valid image-uri attribute is set
387
+ if (workflowIsValid === true) {
388
+ cli.log.success(`GitHub workflow YAML is valid`);
389
+ cli.log.debug(`New file content to write\n\n${workflowDoc}`);
390
+ } else if (Array.isArray(workflowIsValid)) {
391
+ // Errors
392
+ logError(
393
+ [
394
+ ...workflowIsValid.map(
395
+ res => new Error(`${res.code}: ${res.detail || res.title}`)
396
+ ),
397
+ workflowDoc.toString(),
398
+ ],
399
+ `GitHub workflow YAML did not pass validation check`
400
+ );
249
401
  }
402
+ const newWorkflow = normaliseLineEndings(
403
+ workflowDoc.toString({ lineWidth: 0 })
404
+ );
405
+
406
+ return newWorkflow;
250
407
  };
251
408
 
252
409
  const determineAppImageUri = async (
253
410
  cli: ContensisDev,
254
- vars: [string, string][]
411
+ vars: [string, string][],
412
+ defaultUri: string
255
413
  ) => {
256
414
  // Determine container image-uri via variables and/or prompts
257
415
 
258
416
  // Find vars including the word "image"
259
- const imageVars = vars.filter(([varname, value]) =>
417
+ const imageVars = vars.filter(([varname]) =>
260
418
  varname.toLowerCase().includes('image')
261
419
  );
262
420
  // Find vars named "image" that include the word "app"
263
421
  const appImageVars = imageVars.filter(
264
422
  ([varname, value]) =>
265
- varname.toLowerCase().includes('app_') ||
266
- varname.toLowerCase().includes('build_') ||
267
- value?.toLowerCase().includes('/app')
423
+ !varname.toLowerCase().includes('builder_') &&
424
+ (varname.toLowerCase().includes('app_') ||
425
+ varname.toLowerCase().includes('build_') ||
426
+ value?.toLowerCase().includes('/app'))
268
427
  );
269
428
 
270
429
  const appImageUriGuess = appImageVars?.[0];
@@ -286,8 +445,7 @@ const determineAppImageUri = async (
286
445
  // prompt for an app image uri
287
446
  const choices = vars.map(v => v[0]);
288
447
  const enterOwnMsg = 'enter my own / use default';
289
- const defaultUri =
290
- 'ghcr.io/${{ github.repository }}/${{ github.ref_name }}/app:build-${{ github.run_number }}';
448
+
291
449
  choices.push(new inquirer.Separator() as any);
292
450
  choices.push(enterOwnMsg);
293
451
  choices.push(defaultUri);
@@ -312,7 +470,7 @@ const determineAppImageUri = async (
312
470
  return [enterOwnMsg, defaultUri].includes(answers.appImageVar);
313
471
  },
314
472
  prefix: `\n \nšŸ”—`,
315
- message: cli.messages.devinit.ciEnterOwnAppImagePrompt(),
473
+ message: cli.messages.devinit.ciEnterOwnAppImagePrompt(cli.git),
316
474
  name: 'appImageUri',
317
475
  default: defaultUri,
318
476
  },
@@ -326,7 +484,13 @@ const determineAppImageUri = async (
326
484
  appImageVar = undefined;
327
485
  }
328
486
 
329
- if (appImageVar) appImageUri = `\${{ env.${appImageVar} }}`;
487
+ if (appImageVar)
488
+ appImageUri =
489
+ cli.git.type === 'github'
490
+ ? `\${{ env.${appImageVar} }}`
491
+ : `\$${appImageVar}`;
492
+
493
+ // TODO: prompt further for image tag
330
494
 
331
495
  return {
332
496
  addVar: !appImageVar,
@@ -24,3 +24,15 @@ export type GitHubActionPushBlockJob = {
24
24
  needs?: string;
25
25
  steps: GitHubActionPushBlockJobStep[];
26
26
  };
27
+
28
+ export type GitLabPushBlockJobStage = {
29
+ stage: string;
30
+ variables: {
31
+ alias: string;
32
+ project_id: string;
33
+ block_id: string;
34
+ image_uri?: string;
35
+ client_id: string;
36
+ shared_secret: string;
37
+ };
38
+ };