@backstage/plugin-scaffolder-backend-module-gitlab 0.4.1-next.0 → 0.4.1-next.1

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.
package/dist/index.cjs.js CHANGED
@@ -2,492 +2,161 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var errors = require('@backstage/errors');
5
6
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
7
  var node = require('@gitbeaker/node');
8
+ var yaml = require('yaml');
7
9
  var zod = require('zod');
8
- var errors = require('@backstage/errors');
9
10
  var rest = require('@gitbeaker/rest');
10
- var yaml = require('yaml');
11
- var luxon = require('luxon');
12
11
  var path = require('path');
13
12
  var backendPluginApi = require('@backstage/backend-plugin-api');
14
- var alpha = require('@backstage/plugin-scaffolder-node/alpha');
13
+ var luxon = require('luxon');
15
14
  var integration = require('@backstage/integration');
15
+ var alpha = require('@backstage/plugin-scaffolder-node/alpha');
16
16
 
17
17
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
18
18
 
19
19
  var yaml__default = /*#__PURE__*/_interopDefaultCompat(yaml);
20
20
  var path__default = /*#__PURE__*/_interopDefaultCompat(path);
21
21
 
22
- const commonGitlabConfig = zod.z.object({
23
- repoUrl: zod.z.string({ description: "Repository Location" }),
24
- token: zod.z.string({ description: "The token to use for authorization to GitLab" }).optional()
25
- });
26
- const commonGitlabConfigExample = {
27
- repoUrl: "gitlab.com?owner=namespace-or-owner&repo=project-name",
28
- token: "${{ secrets.USER_OAUTH_TOKEN }}"
29
- };
30
-
31
- const parseRepoHost = (repoUrl) => {
32
- let parsed;
33
- try {
34
- parsed = new URL(`https://${repoUrl}`);
35
- } catch (error) {
36
- throw new errors.InputError(
37
- `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
38
- );
39
- }
40
- return parsed.host;
41
- };
42
- const getToken = (config, integrations) => {
43
- const host = parseRepoHost(config.repoUrl);
44
- const integrationConfig = integrations.gitlab.byHost(host);
45
- if (!integrationConfig) {
46
- throw new errors.InputError(
47
- `No matching integration configuration for host ${host}, please check your integrations config`
48
- );
49
- }
50
- const token = config.token || integrationConfig.config.token;
51
- return { token, integrationConfig };
52
- };
53
- const parseRepoUrl = (repoUrl, integrations) => {
54
- let parsed;
55
- try {
56
- parsed = new URL(`https://${repoUrl}`);
57
- } catch (error) {
58
- throw new errors.InputError(
59
- `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
60
- );
61
- }
62
- const host = parsed.host;
63
- const owner = parsed.searchParams.get("owner") ?? void 0;
64
- const repo = parsed.searchParams.get("repo");
65
- const type = integrations.byHost(host)?.type;
66
- if (!type) {
67
- throw new errors.InputError(
68
- `No matching integration configuration for host ${host}, please check your integrations config`
69
- );
70
- }
71
- return { host, owner, repo };
72
- };
73
- function getClient(props) {
74
- const { host, token, integrations } = props;
75
- const integrationConfig = integrations.gitlab.byHost(host);
76
- if (!integrationConfig) {
77
- throw new errors.InputError(
78
- `No matching integration configuration for host ${host}, please check your integrations config`
79
- );
80
- }
81
- const { config } = integrationConfig;
82
- if (!config.token && !token) {
83
- throw new errors.InputError(`No token available for host ${host}`);
84
- }
85
- const requestToken = token || config.token;
86
- const tokenType = token ? "oauthToken" : "token";
87
- const gitlabOptions = {
88
- host: config.baseUrl
89
- };
90
- gitlabOptions[tokenType] = requestToken;
91
- return new rest.Gitlab(gitlabOptions);
92
- }
93
- function convertDate(inputDate, defaultDate) {
94
- try {
95
- return inputDate ? new Date(inputDate).toISOString() : new Date(defaultDate).toISOString();
96
- } catch (error) {
97
- throw new errors.InputError(`Error converting input date - ${error}`);
98
- }
99
- }
100
- async function getTopLevelParentGroup(client, groupId) {
101
- try {
102
- const topParentGroup = await client.Groups.show(groupId);
103
- if (topParentGroup.parent_id) {
104
- return getTopLevelParentGroup(
105
- client,
106
- topParentGroup.parent_id
107
- );
108
- }
109
- return topParentGroup;
110
- } catch (error) {
111
- throw new errors.InputError(
112
- `Error finding top-level parent group ID: ${error.message}`
113
- );
114
- }
115
- }
116
- async function checkEpicScope(client, projectId, epicId) {
117
- try {
118
- const project = await client.Projects.show(projectId);
119
- if (!project) {
120
- throw new errors.InputError(
121
- `Project with id ${projectId} not found. Check your GitLab instance.`
122
- );
123
- }
124
- const topParentGroup = await getTopLevelParentGroup(
125
- client,
126
- project.namespace.id
127
- );
128
- if (!topParentGroup) {
129
- throw new errors.InputError(`Couldn't find a suitable top-level parent group.`);
130
- }
131
- const epic = (await client.Epics.all(topParentGroup.id)).find(
132
- (x) => x.id === epicId
133
- );
134
- if (!epic) {
135
- throw new errors.InputError(
136
- `Epic with id ${epicId} not found in the top-level parent group ${topParentGroup.name}.`
137
- );
138
- }
139
- const epicGroup = await client.Groups.show(epic.group_id);
140
- const projectNamespace = project.path_with_namespace;
141
- return projectNamespace.startsWith(epicGroup.full_path);
142
- } catch (error) {
143
- throw new errors.InputError(`Could not find epic scope: ${error.message}`);
144
- }
145
- }
146
-
147
- const examples$7 = [
22
+ const examples$8 = [
148
23
  {
149
- description: "Creating a group at the top level",
24
+ description: "Initializes a git repository with the content in the workspace, and publishes it to GitLab with the default configuration.",
150
25
  example: yaml__default.default.stringify({
151
26
  steps: [
152
27
  {
153
- id: "gitlabGroup",
154
- name: "Group",
155
- action: "gitlab:group:ensureExists",
28
+ id: "publish",
29
+ action: "publish:gitlab",
30
+ name: "Publish to GitLab",
156
31
  input: {
157
- repoUrl: "gitlab.com",
158
- path: ["group1"]
32
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name"
159
33
  }
160
34
  }
161
35
  ]
162
36
  })
163
37
  },
164
38
  {
165
- description: "Create a group nested within another group",
39
+ description: "Add a description.",
166
40
  example: yaml__default.default.stringify({
167
41
  steps: [
168
42
  {
169
- id: "gitlabGroup",
170
- name: "Group",
171
- action: "gitlab:group:ensureExists",
43
+ id: "publish",
44
+ action: "publish:gitlab",
45
+ name: "Publish to GitLab",
172
46
  input: {
173
- repoUrl: "gitlab.com",
174
- path: ["group1", "group2"]
47
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
48
+ description: "Initialize a git repository"
175
49
  }
176
50
  }
177
51
  ]
178
52
  })
179
53
  },
180
54
  {
181
- description: "Create a group nested within multiple other groups",
55
+ description: "Initializes a GitLab repository with an initial commit message, if not set defaults to `initial commit`.",
182
56
  example: yaml__default.default.stringify({
183
57
  steps: [
184
58
  {
185
- id: "gitlabGroup",
186
- name: "Group",
187
- action: "gitlab:group:ensureExists",
59
+ id: "publish",
60
+ action: "publish:gitlab",
61
+ name: "Publish to GitLab",
188
62
  input: {
189
- repoUrl: "gitlab.com",
190
- path: ["group1", "group2", "group3"]
63
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
64
+ description: "Initialize a git repository",
65
+ gitCommitMessage: "Started a project."
191
66
  }
192
67
  }
193
68
  ]
194
69
  })
195
70
  },
196
71
  {
197
- description: "Create a group in dry run mode",
72
+ description: "Initializes a GitLab repository with aditional settings.",
198
73
  example: yaml__default.default.stringify({
199
74
  steps: [
200
75
  {
201
- id: "gitlabGroup",
202
- name: "Group",
203
- action: "gitlab:group:ensureExists",
204
- isDryRun: true,
76
+ id: "publish",
77
+ action: "publish:gitlab",
78
+ name: "Publish to GitLab",
205
79
  input: {
206
- repoUrl: "https://gitlab.com/my-repo",
207
- path: ["group1", "group2", "group3"]
80
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
81
+ settings: {
82
+ ci_config_path: ".gitlab-ci.yml",
83
+ visibility: "public"
84
+ }
208
85
  }
209
86
  }
210
87
  ]
211
88
  })
212
- }
213
- ];
214
-
215
- const createGitlabGroupEnsureExistsAction = (options) => {
216
- const { integrations } = options;
217
- return pluginScaffolderNode.createTemplateAction({
218
- id: "gitlab:group:ensureExists",
219
- description: "Ensures a Gitlab group exists",
220
- supportsDryRun: true,
221
- examples: examples$7,
222
- schema: {
223
- input: commonGitlabConfig.merge(
224
- zod.z.object({
225
- path: zod.z.array(zod.z.string(), {
226
- description: "A path of group names that is ensured to exist"
227
- }).min(1)
228
- })
229
- ),
230
- output: zod.z.object({
231
- groupId: zod.z.number({ description: "The id of the innermost sub-group" }).optional()
232
- })
233
- },
234
- async handler(ctx) {
235
- if (ctx.isDryRun) {
236
- ctx.output("groupId", 42);
237
- return;
238
- }
239
- const { path } = ctx.input;
240
- const { token, integrationConfig } = getToken(ctx.input, integrations);
241
- const api = new node.Gitlab({
242
- host: integrationConfig.config.baseUrl,
243
- token
244
- });
245
- let currentPath = null;
246
- let parent = null;
247
- for (const pathElement of path) {
248
- const fullPath = currentPath ? `${currentPath}/${pathElement}` : pathElement;
249
- const result = await api.Groups.search(
250
- fullPath
251
- );
252
- const subGroup = result.find(
253
- (searchPathElem) => searchPathElem.full_path === fullPath
254
- );
255
- if (!subGroup) {
256
- ctx.logger.info(`creating missing group ${fullPath}`);
257
- parent = await api.Groups.create(
258
- pathElement,
259
- pathElement,
260
- parent ? {
261
- parent_id: parent.id
262
- } : {}
263
- );
264
- } else {
265
- parent = subGroup;
266
- }
267
- currentPath = fullPath;
268
- }
269
- if (parent !== null) {
270
- ctx.output("groupId", parent?.id);
271
- }
272
- }
273
- });
274
- };
275
-
276
- const examples$6 = [
89
+ },
277
90
  {
278
- description: "Create a GitLab project deploy token with minimal options.",
91
+ description: "Initializes a GitLab repository with fast forward merge and always squash settings.",
279
92
  example: yaml__default.default.stringify({
280
93
  steps: [
281
94
  {
282
- id: "createDeployToken",
283
- action: "gitlab:projectDeployToken:create",
284
- name: "Create GitLab Project Deploy Token",
285
- input: {
286
- repoUrl: "gitlab.com?repo=repo&owner=owner",
287
- projectId: "456",
288
- name: "tokenname"
289
- }
290
- }
291
- ]
292
- })
293
- },
294
- {
295
- description: "Create a GitLab project deploy token with custom scopes.",
296
- example: yaml__default.default.stringify({
297
- steps: [
298
- {
299
- id: "createDeployToken",
300
- action: "gitlab:projectDeployToken:create",
301
- name: "Create GitLab Project Deploy Token",
302
- input: {
303
- repoUrl: "gitlab.com?repo=repo&owner=owner",
304
- projectId: "789",
305
- name: "tokenname",
306
- scopes: ["read_registry", "write_repository"]
307
- }
308
- }
309
- ]
310
- })
311
- },
312
- {
313
- description: "Create a GitLab project deploy token with a specified name.",
314
- example: yaml__default.default.stringify({
315
- steps: [
316
- {
317
- id: "createDeployToken",
318
- action: "gitlab:projectDeployToken:create",
319
- name: "Create GitLab Project Deploy Token",
320
- input: {
321
- repoUrl: "gitlab.com?repo=repo&owner=owner",
322
- projectId: "101112",
323
- name: "my-custom-token"
324
- }
325
- }
326
- ]
327
- })
328
- },
329
- {
330
- description: "Create a GitLab project deploy token with a numeric project ID.",
331
- example: yaml__default.default.stringify({
332
- steps: [
333
- {
334
- id: "createDeployToken",
335
- action: "gitlab:projectDeployToken:create",
336
- name: "Create GitLab Project Deploy Token",
337
- input: {
338
- repoUrl: "gitlab.com?repo=repo&owner=owner",
339
- projectId: 42,
340
- name: "tokenname"
341
- }
342
- }
343
- ]
344
- })
345
- },
346
- {
347
- description: "Create a GitLab project deploy token with a custom username",
348
- example: yaml__default.default.stringify({
349
- steps: [
350
- {
351
- id: "createDeployToken",
352
- action: "gitlab:projectDeployToken:create",
353
- name: "Create GitLab Project Deploy Token",
354
- input: {
355
- repoUrl: "gitlab.com?repo=repo&owner=owner",
356
- projectId: 42,
357
- name: "tokenname",
358
- username: "tokenuser"
359
- }
360
- }
361
- ]
362
- })
363
- }
364
- ];
365
-
366
- const createGitlabProjectDeployTokenAction = (options) => {
367
- const { integrations } = options;
368
- return pluginScaffolderNode.createTemplateAction({
369
- id: "gitlab:projectDeployToken:create",
370
- examples: examples$6,
371
- schema: {
372
- input: commonGitlabConfig.merge(
373
- zod.z.object({
374
- projectId: zod.z.union([zod.z.number(), zod.z.string()], {
375
- description: "Project ID"
376
- }),
377
- name: zod.z.string({ description: "Deploy Token Name" }),
378
- username: zod.z.string({ description: "Deploy Token Username" }).optional(),
379
- scopes: zod.z.array(zod.z.string(), { description: "Scopes" }).optional()
380
- })
381
- ),
382
- output: zod.z.object({
383
- deploy_token: zod.z.string({ description: "Deploy Token" }),
384
- user: zod.z.string({ description: "User" })
385
- })
386
- },
387
- async handler(ctx) {
388
- ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
389
- const { projectId, name, username, scopes } = ctx.input;
390
- const { token, integrationConfig } = getToken(ctx.input, integrations);
391
- const api = new node.Gitlab({
392
- host: integrationConfig.config.baseUrl,
393
- token
394
- });
395
- const deployToken = await api.ProjectDeployTokens.add(
396
- projectId,
397
- name,
398
- scopes,
399
- {
400
- username
401
- }
402
- );
403
- if (!deployToken.hasOwnProperty("token")) {
404
- throw new errors.InputError(`No deploy_token given from gitlab instance`);
405
- }
406
- ctx.output("deploy_token", deployToken.token);
407
- ctx.output("user", deployToken.username);
408
- }
409
- });
410
- };
411
-
412
- const examples$5 = [
413
- {
414
- description: "Create a GitLab project access token with minimal options.",
415
- example: yaml__default.default.stringify({
416
- steps: [
417
- {
418
- id: "createAccessToken",
419
- action: "gitlab:projectAccessToken:create",
420
- name: "Create GitLab Project Access Token",
421
- input: {
422
- repoUrl: "gitlab.com?repo=repo&owner=owner",
423
- projectId: "456"
424
- }
425
- }
426
- ]
427
- })
428
- },
429
- {
430
- description: "Create a GitLab project access token with custom scopes.",
431
- example: yaml__default.default.stringify({
432
- steps: [
433
- {
434
- id: "createAccessToken",
435
- action: "gitlab:projectAccessToken:create",
436
- name: "Create GitLab Project Access Token",
437
- input: {
438
- repoUrl: "gitlab.com?repo=repo&owner=owner",
439
- projectId: "789",
440
- scopes: ["read_registry", "write_repository"]
441
- }
442
- }
443
- ]
444
- })
445
- },
446
- {
447
- description: "Create a GitLab project access token with a specified name.",
448
- example: yaml__default.default.stringify({
449
- steps: [
450
- {
451
- id: "createAccessToken",
452
- action: "gitlab:projectAccessToken:create",
453
- name: "Create GitLab Project Access Token",
95
+ id: "publish",
96
+ action: "publish:gitlab",
97
+ name: "Publish to GitLab",
454
98
  input: {
455
- repoUrl: "gitlab.com?repo=repo&owner=owner",
456
- projectId: "101112",
457
- name: "my-custom-token"
99
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
100
+ settings: {
101
+ merge_method: "ff",
102
+ squash_option: "always"
103
+ }
458
104
  }
459
105
  }
460
106
  ]
461
107
  })
462
108
  },
463
109
  {
464
- description: "Create a GitLab project access token with a numeric project ID.",
110
+ description: "Initializes a GitLab repository with branch settings.",
465
111
  example: yaml__default.default.stringify({
466
112
  steps: [
467
113
  {
468
- id: "createAccessToken",
469
- action: "gitlab:projectAccessToken:create",
470
- name: "Create GitLab Project Access Token",
114
+ id: "publish",
115
+ action: "publish:gitlab",
116
+ name: "Publish to GitLab",
471
117
  input: {
472
- repoUrl: "gitlab.com?repo=repo&owner=owner",
473
- projectId: 42
118
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
119
+ branches: [
120
+ {
121
+ name: "dev",
122
+ create: true,
123
+ protected: true,
124
+ ref: "master"
125
+ },
126
+ {
127
+ name: "master",
128
+ protected: true
129
+ }
130
+ ]
474
131
  }
475
132
  }
476
133
  ]
477
134
  })
478
135
  },
479
136
  {
480
- description: "Create a GitLab project access token with a specified expired Date.",
137
+ description: "Initializes a GitLab repository with environment variables.",
481
138
  example: yaml__default.default.stringify({
482
139
  steps: [
483
140
  {
484
- id: "createAccessToken",
485
- action: "gitlab:projectAccessToken:create",
486
- name: "Create GitLab Project Access Token",
141
+ id: "publish",
142
+ action: "publish:gitlab",
143
+ name: "Publish to GitLab",
487
144
  input: {
488
- repoUrl: "gitlab.com?repo=repo&owner=owner",
489
- projectId: "123",
490
- expiresAt: "2024-06-25"
145
+ repoUrl: "gitlab.com?repo=project_name&owner=group_name",
146
+ projectVariables: [
147
+ {
148
+ key: "key1",
149
+ value: "value1",
150
+ protected: true,
151
+ masked: false
152
+ },
153
+ {
154
+ key: "key2",
155
+ value: "value2",
156
+ protected: true,
157
+ masked: false
158
+ }
159
+ ]
491
160
  }
492
161
  }
493
162
  ]
@@ -495,213 +164,964 @@ const examples$5 = [
495
164
  }
496
165
  ];
497
166
 
498
- const createGitlabProjectAccessTokenAction = (options) => {
499
- const { integrations } = options;
167
+ function createPublishGitlabAction(options) {
168
+ const { integrations, config } = options;
500
169
  return pluginScaffolderNode.createTemplateAction({
501
- id: "gitlab:projectAccessToken:create",
502
- examples: examples$5,
170
+ id: "publish:gitlab",
171
+ description: "Initializes a git repository of the content in the workspace, and publishes it to GitLab.",
172
+ examples: examples$8,
503
173
  schema: {
504
- input: zod.z.object({
505
- projectId: zod.z.union([zod.z.number(), zod.z.string()], {
506
- description: "Project ID/Name(slug) of the Gitlab Project"
507
- }),
508
- token: zod.z.string({
509
- description: "The token to use for authorization to GitLab"
510
- }).optional(),
511
- name: zod.z.string({ description: "Name of Access Key" }).optional(),
512
- repoUrl: zod.z.string({ description: "URL to gitlab instance" }),
513
- accessLevel: zod.z.number({
514
- description: "Access Level of the Token, 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), and 50 (Owner)"
515
- }).optional(),
516
- scopes: zod.z.string({
517
- description: "Scopes for a project access token"
518
- }).array().optional(),
519
- expiresAt: zod.z.string({
520
- description: "Expiration date of the access token in ISO format (YYYY-MM-DD). If Empty, it will set to the maximum of 365 days."
521
- }).optional()
522
- }),
174
+ input: {
175
+ type: "object",
176
+ required: ["repoUrl"],
177
+ properties: {
178
+ repoUrl: {
179
+ title: "Repository Location",
180
+ type: "string",
181
+ description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`
182
+ },
183
+ repoVisibility: {
184
+ title: "Repository Visibility",
185
+ description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`,
186
+ type: "string",
187
+ enum: ["private", "public", "internal"]
188
+ },
189
+ defaultBranch: {
190
+ title: "Default Branch",
191
+ type: "string",
192
+ description: `Sets the default branch on the repository. The default value is 'master'`
193
+ },
194
+ gitCommitMessage: {
195
+ title: "Git Commit Message",
196
+ type: "string",
197
+ description: `Sets the commit message on the repository. The default value is 'initial commit'`
198
+ },
199
+ gitAuthorName: {
200
+ title: "Default Author Name",
201
+ type: "string",
202
+ description: `Sets the default author name for the commit. The default value is 'Scaffolder'`
203
+ },
204
+ gitAuthorEmail: {
205
+ title: "Default Author Email",
206
+ type: "string",
207
+ description: `Sets the default author email for the commit.`
208
+ },
209
+ sourcePath: {
210
+ title: "Source Path",
211
+ description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
212
+ type: "string"
213
+ },
214
+ token: {
215
+ title: "Authentication Token",
216
+ type: "string",
217
+ description: "The token to use for authorization to GitLab"
218
+ },
219
+ setUserAsOwner: {
220
+ title: "Set User As Owner",
221
+ type: "boolean",
222
+ description: "Set the token user as owner of the newly created repository. Requires a token authorized to do the edit in the integration configuration for the matching host"
223
+ },
224
+ topics: {
225
+ title: "Topic labels",
226
+ description: "Topic labels to apply on the repository. (deprecated, use settings.topics instead)",
227
+ type: "array",
228
+ items: {
229
+ type: "string"
230
+ }
231
+ },
232
+ settings: {
233
+ title: "Project settings",
234
+ description: "Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes",
235
+ type: "object",
236
+ properties: {
237
+ path: {
238
+ title: "Project path",
239
+ description: "Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).",
240
+ type: "string"
241
+ },
242
+ auto_devops_enabled: {
243
+ title: "Auto DevOps enabled",
244
+ description: "Enable Auto DevOps for this project",
245
+ type: "boolean"
246
+ },
247
+ ci_config_path: {
248
+ title: "CI config path",
249
+ description: "Custom CI config path for this project",
250
+ type: "string"
251
+ },
252
+ description: {
253
+ title: "Project description",
254
+ description: "Short project description",
255
+ type: "string"
256
+ },
257
+ merge_method: {
258
+ title: "Merge Method to use",
259
+ description: "Merge Methods (merge, rebase_merge, ff)",
260
+ type: "string",
261
+ enum: ["merge", "rebase_merge", "ff"]
262
+ },
263
+ squash_option: {
264
+ title: "Squash option",
265
+ description: "Set squash option for the project (never, always, default_on, default_off)",
266
+ type: "string",
267
+ enum: ["default_off", "default_on", "never", "always"]
268
+ },
269
+ topics: {
270
+ title: "Topic labels",
271
+ description: "Topic labels to apply on the repository",
272
+ type: "array",
273
+ items: {
274
+ type: "string"
275
+ }
276
+ },
277
+ visibility: {
278
+ title: "Project visibility",
279
+ description: "The visibility of the project. Can be private, internal, or public. The default value is private.",
280
+ type: "string",
281
+ enum: ["private", "public", "internal"]
282
+ }
283
+ }
284
+ },
285
+ branches: {
286
+ title: "Project branches settings",
287
+ type: "array",
288
+ items: {
289
+ type: "object",
290
+ required: ["name"],
291
+ properties: {
292
+ name: {
293
+ title: "Branch name",
294
+ type: "string"
295
+ },
296
+ protect: {
297
+ title: "Should branch be protected",
298
+ description: `Will mark branch as protected. The default value is 'false'`,
299
+ type: "boolean"
300
+ },
301
+ create: {
302
+ title: "Should branch be created",
303
+ description: `If branch does not exist, it will be created from provided ref. The default value is 'false'`,
304
+ type: "boolean"
305
+ },
306
+ ref: {
307
+ title: "Branch reference",
308
+ description: `Branch reference to create branch from. The default value is 'master'`,
309
+ type: "string"
310
+ }
311
+ }
312
+ }
313
+ },
314
+ projectVariables: {
315
+ title: "Project variables",
316
+ description: "Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable",
317
+ type: "array",
318
+ items: {
319
+ type: "object",
320
+ required: ["key", "value"],
321
+ properties: {
322
+ key: {
323
+ title: "Variable key",
324
+ description: "The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed",
325
+ type: "string"
326
+ },
327
+ value: {
328
+ title: "Variable value",
329
+ description: "The value of a variable",
330
+ type: "string"
331
+ },
332
+ description: {
333
+ title: "Variable description",
334
+ description: `The description of the variable. The default value is 'null'`,
335
+ type: "string"
336
+ },
337
+ variable_type: {
338
+ title: "Variable type",
339
+ description: `The type of a variable. The default value is 'env_var'`,
340
+ type: "string",
341
+ enum: ["env_var", "file"]
342
+ },
343
+ protected: {
344
+ title: "Variable protection",
345
+ description: `Whether the variable is protected. The default value is 'false'`,
346
+ type: "boolean"
347
+ },
348
+ raw: {
349
+ title: "Variable raw",
350
+ description: `Whether the variable is in raw format. The default value is 'false'`,
351
+ type: "boolean"
352
+ },
353
+ environment_scope: {
354
+ title: "Variable environment scope",
355
+ description: `The environment_scope of the variable. The default value is '*'`,
356
+ type: "string"
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
362
+ },
363
+ output: {
364
+ type: "object",
365
+ properties: {
366
+ remoteUrl: {
367
+ title: "A URL to the repository with the provider",
368
+ type: "string"
369
+ },
370
+ repoContentsUrl: {
371
+ title: "A URL to the root of the repository",
372
+ type: "string"
373
+ },
374
+ projectId: {
375
+ title: "The ID of the project",
376
+ type: "string"
377
+ },
378
+ commitHash: {
379
+ title: "The git commit hash of the initial commit",
380
+ type: "string"
381
+ }
382
+ }
383
+ }
384
+ },
385
+ async handler(ctx) {
386
+ const {
387
+ repoUrl,
388
+ repoVisibility = "private",
389
+ defaultBranch = "master",
390
+ gitCommitMessage = "initial commit",
391
+ gitAuthorName,
392
+ gitAuthorEmail,
393
+ setUserAsOwner = false,
394
+ topics = [],
395
+ settings = {},
396
+ branches = [],
397
+ projectVariables = []
398
+ } = ctx.input;
399
+ const { owner, repo, host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
400
+ if (!owner) {
401
+ throw new errors.InputError(
402
+ `No owner provided for host: ${host}, and repo ${repo}`
403
+ );
404
+ }
405
+ const integrationConfig = integrations.gitlab.byHost(host);
406
+ if (!integrationConfig) {
407
+ throw new errors.InputError(
408
+ `No matching integration configuration for host ${host}, please check your integrations config`
409
+ );
410
+ }
411
+ if (!integrationConfig.config.token && !ctx.input.token) {
412
+ throw new errors.InputError(`No token available for host ${host}`);
413
+ }
414
+ const token = ctx.input.token || integrationConfig.config.token;
415
+ const tokenType = ctx.input.token ? "oauthToken" : "token";
416
+ const client = new node.Gitlab({
417
+ host: integrationConfig.config.baseUrl,
418
+ [tokenType]: token
419
+ });
420
+ let targetNamespaceId;
421
+ try {
422
+ const namespaceResponse = await client.Namespaces.show(owner);
423
+ targetNamespaceId = namespaceResponse.id;
424
+ } catch (e) {
425
+ if (e.response && e.response.statusCode === 404) {
426
+ throw new errors.InputError(
427
+ `The namespace ${owner} is not found or the user doesn't have permissions to access it`
428
+ );
429
+ }
430
+ throw e;
431
+ }
432
+ const { id: userId } = await client.Users.current();
433
+ if (!targetNamespaceId) {
434
+ targetNamespaceId = userId;
435
+ }
436
+ const { id: projectId, http_url_to_repo } = await client.Projects.create({
437
+ namespace_id: targetNamespaceId,
438
+ name: repo,
439
+ visibility: repoVisibility,
440
+ ...topics.length ? { topics } : {},
441
+ ...Object.keys(settings).length ? { ...settings } : {}
442
+ });
443
+ if (setUserAsOwner && integrationConfig.config.token) {
444
+ const adminClient = new node.Gitlab({
445
+ host: integrationConfig.config.baseUrl,
446
+ token: integrationConfig.config.token
447
+ });
448
+ await adminClient.ProjectMembers.add(projectId, userId, 50);
449
+ }
450
+ const remoteUrl = http_url_to_repo.replace(/\.git$/, "");
451
+ const repoContentsUrl = `${remoteUrl}/-/blob/${defaultBranch}`;
452
+ const gitAuthorInfo = {
453
+ name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
454
+ email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
455
+ };
456
+ const commitResult = await pluginScaffolderNode.initRepoAndPush({
457
+ dir: pluginScaffolderNode.getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
458
+ remoteUrl: http_url_to_repo,
459
+ defaultBranch,
460
+ auth: {
461
+ username: "oauth2",
462
+ password: token
463
+ },
464
+ logger: ctx.logger,
465
+ commitMessage: gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage"),
466
+ gitAuthorInfo
467
+ });
468
+ if (branches) {
469
+ for (const branch of branches) {
470
+ const {
471
+ name,
472
+ protect = false,
473
+ create = false,
474
+ ref = "master"
475
+ } = branch;
476
+ if (create) {
477
+ try {
478
+ await client.Branches.create(projectId, name, ref);
479
+ } catch (e) {
480
+ throw new errors.InputError(
481
+ `Branch creation failed for ${name}. ${printGitlabError(e)}`
482
+ );
483
+ }
484
+ ctx.logger.info(
485
+ `Branch ${name} created for ${projectId} with ref ${ref}`
486
+ );
487
+ }
488
+ if (protect) {
489
+ try {
490
+ await client.ProtectedBranches.protect(projectId, name);
491
+ } catch (e) {
492
+ throw new errors.InputError(
493
+ `Branch protection failed for ${name}. ${printGitlabError(e)}`
494
+ );
495
+ }
496
+ ctx.logger.info(`Branch ${name} protected for ${projectId}`);
497
+ }
498
+ }
499
+ }
500
+ if (projectVariables) {
501
+ for (const variable of projectVariables) {
502
+ const variableWithDefaults = Object.assign(variable, {
503
+ variable_type: variable.variable_type ?? "env_var",
504
+ protected: variable.protected ?? false,
505
+ masked: variable.masked ?? false,
506
+ raw: variable.raw ?? false,
507
+ environment_scope: variable.environment_scope ?? "*"
508
+ });
509
+ try {
510
+ await client.ProjectVariables.create(
511
+ projectId,
512
+ variableWithDefaults
513
+ );
514
+ } catch (e) {
515
+ throw new errors.InputError(
516
+ `Environment variable creation failed for ${variableWithDefaults.key}. ${printGitlabError(e)}`
517
+ );
518
+ }
519
+ }
520
+ }
521
+ ctx.output("commitHash", commitResult?.commitHash);
522
+ ctx.output("remoteUrl", remoteUrl);
523
+ ctx.output("repoContentsUrl", repoContentsUrl);
524
+ ctx.output("projectId", projectId);
525
+ }
526
+ });
527
+ }
528
+ function printGitlabError(error) {
529
+ return JSON.stringify({ code: error.code, message: error.description });
530
+ }
531
+
532
+ const commonGitlabConfig = zod.z.object({
533
+ repoUrl: zod.z.string({ description: "Repository Location" }),
534
+ token: zod.z.string({ description: "The token to use for authorization to GitLab" }).optional()
535
+ });
536
+ const commonGitlabConfigExample = {
537
+ repoUrl: "gitlab.com?owner=namespace-or-owner&repo=project-name",
538
+ token: "${{ secrets.USER_OAUTH_TOKEN }}"
539
+ };
540
+
541
+ const parseRepoHost = (repoUrl) => {
542
+ let parsed;
543
+ try {
544
+ parsed = new URL(`https://${repoUrl}`);
545
+ } catch (error) {
546
+ throw new errors.InputError(
547
+ `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
548
+ );
549
+ }
550
+ return parsed.host;
551
+ };
552
+ const getToken = (config, integrations) => {
553
+ const host = parseRepoHost(config.repoUrl);
554
+ const integrationConfig = integrations.gitlab.byHost(host);
555
+ if (!integrationConfig) {
556
+ throw new errors.InputError(
557
+ `No matching integration configuration for host ${host}, please check your integrations config`
558
+ );
559
+ }
560
+ const token = config.token || integrationConfig.config.token;
561
+ return { token, integrationConfig };
562
+ };
563
+ const parseRepoUrl = (repoUrl, integrations) => {
564
+ let parsed;
565
+ try {
566
+ parsed = new URL(`https://${repoUrl}`);
567
+ } catch (error) {
568
+ throw new errors.InputError(
569
+ `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
570
+ );
571
+ }
572
+ const host = parsed.host;
573
+ const owner = parsed.searchParams.get("owner") ?? void 0;
574
+ const repo = parsed.searchParams.get("repo");
575
+ const type = integrations.byHost(host)?.type;
576
+ if (!type) {
577
+ throw new errors.InputError(
578
+ `No matching integration configuration for host ${host}, please check your integrations config`
579
+ );
580
+ }
581
+ return { host, owner, repo };
582
+ };
583
+ function getClient(props) {
584
+ const { host, token, integrations } = props;
585
+ const integrationConfig = integrations.gitlab.byHost(host);
586
+ if (!integrationConfig) {
587
+ throw new errors.InputError(
588
+ `No matching integration configuration for host ${host}, please check your integrations config`
589
+ );
590
+ }
591
+ const { config } = integrationConfig;
592
+ if (!config.token && !token) {
593
+ throw new errors.InputError(`No token available for host ${host}`);
594
+ }
595
+ const requestToken = token || config.token;
596
+ const tokenType = token ? "oauthToken" : "token";
597
+ const gitlabOptions = {
598
+ host: config.baseUrl
599
+ };
600
+ gitlabOptions[tokenType] = requestToken;
601
+ return new rest.Gitlab(gitlabOptions);
602
+ }
603
+ function convertDate(inputDate, defaultDate) {
604
+ try {
605
+ return inputDate ? new Date(inputDate).toISOString() : new Date(defaultDate).toISOString();
606
+ } catch (error) {
607
+ throw new errors.InputError(`Error converting input date - ${error}`);
608
+ }
609
+ }
610
+ async function getTopLevelParentGroup(client, groupId) {
611
+ try {
612
+ const topParentGroup = await client.Groups.show(groupId);
613
+ if (topParentGroup.parent_id) {
614
+ return getTopLevelParentGroup(
615
+ client,
616
+ topParentGroup.parent_id
617
+ );
618
+ }
619
+ return topParentGroup;
620
+ } catch (error) {
621
+ throw new errors.InputError(
622
+ `Error finding top-level parent group ID: ${error.message}`
623
+ );
624
+ }
625
+ }
626
+ async function checkEpicScope(client, projectId, epicId) {
627
+ try {
628
+ const project = await client.Projects.show(projectId);
629
+ if (!project) {
630
+ throw new errors.InputError(
631
+ `Project with id ${projectId} not found. Check your GitLab instance.`
632
+ );
633
+ }
634
+ const topParentGroup = await getTopLevelParentGroup(
635
+ client,
636
+ project.namespace.id
637
+ );
638
+ if (!topParentGroup) {
639
+ throw new errors.InputError(`Couldn't find a suitable top-level parent group.`);
640
+ }
641
+ const epic = (await client.Epics.all(topParentGroup.id)).find(
642
+ (x) => x.id === epicId
643
+ );
644
+ if (!epic) {
645
+ throw new errors.InputError(
646
+ `Epic with id ${epicId} not found in the top-level parent group ${topParentGroup.name}.`
647
+ );
648
+ }
649
+ const epicGroup = await client.Groups.show(epic.group_id);
650
+ const projectNamespace = project.path_with_namespace;
651
+ return projectNamespace.startsWith(epicGroup.full_path);
652
+ } catch (error) {
653
+ throw new errors.InputError(`Could not find epic scope: ${error.message}`);
654
+ }
655
+ }
656
+
657
+ const examples$7 = [
658
+ {
659
+ description: "Creating a group at the top level",
660
+ example: yaml__default.default.stringify({
661
+ steps: [
662
+ {
663
+ id: "gitlabGroup",
664
+ name: "Group",
665
+ action: "gitlab:group:ensureExists",
666
+ input: {
667
+ repoUrl: "gitlab.com",
668
+ path: ["group1"]
669
+ }
670
+ }
671
+ ]
672
+ })
673
+ },
674
+ {
675
+ description: "Create a group nested within another group",
676
+ example: yaml__default.default.stringify({
677
+ steps: [
678
+ {
679
+ id: "gitlabGroup",
680
+ name: "Group",
681
+ action: "gitlab:group:ensureExists",
682
+ input: {
683
+ repoUrl: "gitlab.com",
684
+ path: ["group1", "group2"]
685
+ }
686
+ }
687
+ ]
688
+ })
689
+ },
690
+ {
691
+ description: "Create a group nested within multiple other groups",
692
+ example: yaml__default.default.stringify({
693
+ steps: [
694
+ {
695
+ id: "gitlabGroup",
696
+ name: "Group",
697
+ action: "gitlab:group:ensureExists",
698
+ input: {
699
+ repoUrl: "gitlab.com",
700
+ path: ["group1", "group2", "group3"]
701
+ }
702
+ }
703
+ ]
704
+ })
705
+ },
706
+ {
707
+ description: "Create a group in dry run mode",
708
+ example: yaml__default.default.stringify({
709
+ steps: [
710
+ {
711
+ id: "gitlabGroup",
712
+ name: "Group",
713
+ action: "gitlab:group:ensureExists",
714
+ isDryRun: true,
715
+ input: {
716
+ repoUrl: "https://gitlab.com/my-repo",
717
+ path: ["group1", "group2", "group3"]
718
+ }
719
+ }
720
+ ]
721
+ })
722
+ }
723
+ ];
724
+
725
+ const createGitlabGroupEnsureExistsAction = (options) => {
726
+ const { integrations } = options;
727
+ return pluginScaffolderNode.createTemplateAction({
728
+ id: "gitlab:group:ensureExists",
729
+ description: "Ensures a Gitlab group exists",
730
+ supportsDryRun: true,
731
+ examples: examples$7,
732
+ schema: {
733
+ input: commonGitlabConfig.merge(
734
+ zod.z.object({
735
+ path: zod.z.array(zod.z.string(), {
736
+ description: "A path of group names that is ensured to exist"
737
+ }).min(1)
738
+ })
739
+ ),
523
740
  output: zod.z.object({
524
- access_token: zod.z.string({ description: "Access Token" })
741
+ groupId: zod.z.number({ description: "The id of the innermost sub-group" }).optional()
525
742
  })
526
743
  },
527
744
  async handler(ctx) {
528
- ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
529
- const {
530
- projectId,
531
- name = "tokenname",
532
- accessLevel = 40,
533
- scopes = ["read_repository"],
534
- expiresAt
535
- } = ctx.input;
536
- const { token, integrationConfig } = getToken(ctx.input, integrations);
537
- if (!integrationConfig.config.token && token) {
538
- throw new errors.InputError(
539
- `No token available for host ${integrationConfig.config.baseUrl}`
540
- );
541
- }
542
- let api;
543
- if (!ctx.input.token) {
544
- api = new rest.Gitlab({
545
- host: integrationConfig.config.baseUrl,
745
+ if (ctx.isDryRun) {
746
+ ctx.output("groupId", 42);
747
+ return;
748
+ }
749
+ const { path } = ctx.input;
750
+ const { token, integrationConfig } = getToken(ctx.input, integrations);
751
+ const api = new node.Gitlab({
752
+ host: integrationConfig.config.baseUrl,
753
+ token
754
+ });
755
+ let currentPath = null;
756
+ let parent = null;
757
+ for (const pathElement of path) {
758
+ const fullPath = currentPath ? `${currentPath}/${pathElement}` : pathElement;
759
+ const result = await api.Groups.search(
760
+ fullPath
761
+ );
762
+ const subGroup = result.find(
763
+ (searchPathElem) => searchPathElem.full_path === fullPath
764
+ );
765
+ if (!subGroup) {
766
+ ctx.logger.info(`creating missing group ${fullPath}`);
767
+ parent = await api.Groups.create(
768
+ pathElement,
769
+ pathElement,
770
+ parent ? {
771
+ parent_id: parent.id
772
+ } : {}
773
+ );
774
+ } else {
775
+ parent = subGroup;
776
+ }
777
+ currentPath = fullPath;
778
+ }
779
+ if (parent !== null) {
780
+ ctx.output("groupId", parent?.id);
781
+ }
782
+ }
783
+ });
784
+ };
785
+
786
+ const examples$6 = [
787
+ {
788
+ description: "Create a GitLab issue with minimal options",
789
+ example: yaml__default.default.stringify({
790
+ steps: [
791
+ {
792
+ id: "gitlabIssue",
793
+ name: "Issues",
794
+ action: "gitlab:issues:create",
795
+ input: {
796
+ ...commonGitlabConfigExample,
797
+ projectId: 12,
798
+ title: "Test Issue",
799
+ description: "This is the description of the issue"
800
+ }
801
+ }
802
+ ]
803
+ })
804
+ },
805
+ {
806
+ description: "Create a GitLab issue with assignees and date options",
807
+ example: yaml__default.default.stringify({
808
+ steps: [
809
+ {
810
+ id: "gitlabIssue",
811
+ name: "Issues",
812
+ action: "gitlab:issues:create",
813
+ input: {
814
+ ...commonGitlabConfigExample,
815
+ projectId: 12,
816
+ title: "Test Issue",
817
+ assignees: [18],
818
+ description: "This is the description of the issue",
819
+ createdAt: "2022-09-27 18:00:00.000",
820
+ dueDate: "2022-09-28 12:00:00.000"
821
+ }
822
+ }
823
+ ]
824
+ })
825
+ },
826
+ {
827
+ description: "Create a GitLab Issue with several options",
828
+ example: yaml__default.default.stringify({
829
+ steps: [
830
+ {
831
+ id: "gitlabIssue",
832
+ name: "Issues",
833
+ action: "gitlab:issues:create",
834
+ input: {
835
+ ...commonGitlabConfigExample,
836
+ projectId: 12,
837
+ title: "Test Issue",
838
+ assignees: [18, 15],
839
+ description: "This is the description of the issue",
840
+ confidential: false,
841
+ createdAt: "2022-09-27 18:00:00.000",
842
+ dueDate: "2022-09-28 12:00:00.000",
843
+ discussionToResolve: 1,
844
+ epicId: 1,
845
+ labels: "phase1:label1,phase2:label2"
846
+ }
847
+ }
848
+ ]
849
+ })
850
+ }
851
+ ];
852
+
853
+ var IssueType = /* @__PURE__ */ ((IssueType2) => {
854
+ IssueType2["ISSUE"] = "issue";
855
+ IssueType2["INCIDENT"] = "incident";
856
+ IssueType2["TEST"] = "test_case";
857
+ return IssueType2;
858
+ })(IssueType || {});
859
+ const issueInputProperties = zod.z.object({
860
+ projectId: zod.z.number().describe("Project Id"),
861
+ title: zod.z.string({ description: "Title of the issue" }),
862
+ assignees: zod.z.array(zod.z.number(), {
863
+ description: "IDs of the users to assign the issue to."
864
+ }).optional(),
865
+ confidential: zod.z.boolean({ description: "Issue Confidentiality" }).optional(),
866
+ description: zod.z.string().describe("Issue description").max(1048576).optional(),
867
+ createdAt: zod.z.string().describe("Creation date/time").regex(
868
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
869
+ "Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
870
+ ).optional(),
871
+ dueDate: zod.z.string().describe("Due date/time").regex(
872
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
873
+ "Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
874
+ ).optional(),
875
+ discussionToResolve: zod.z.string({
876
+ description: 'Id of a discussion to resolve. Use in combination with "merge_request_to_resolve_discussions_of"'
877
+ }).optional(),
878
+ epicId: zod.z.number({ description: "Id of the linked Epic" }).min(0, "Valid values should be equal or greater than zero").optional(),
879
+ labels: zod.z.string({ description: "Labels to apply" }).optional(),
880
+ issueType: zod.z.nativeEnum(IssueType, {
881
+ description: "Type of the issue"
882
+ }).optional(),
883
+ mergeRequestToResolveDiscussionsOf: zod.z.number({
884
+ description: "IID of a merge request in which to resolve all issues"
885
+ }).optional(),
886
+ milestoneId: zod.z.number({ description: "Global ID of a milestone to assign the issue" }).optional(),
887
+ weight: zod.z.number({ description: "The issue weight" }).min(0).refine((value) => {
888
+ const isValid = value >= 0;
889
+ if (!isValid) {
890
+ return {
891
+ message: "Valid values should be equal or greater than zero"
892
+ };
893
+ }
894
+ return isValid;
895
+ }).optional()
896
+ });
897
+ const issueOutputProperties = zod.z.object({
898
+ issueUrl: zod.z.string({ description: "Issue Url" }),
899
+ issueId: zod.z.number({ description: "Issue Id" }),
900
+ issueIid: zod.z.number({ description: "Issue Iid" })
901
+ });
902
+ const createGitlabIssueAction = (options) => {
903
+ const { integrations } = options;
904
+ return pluginScaffolderNode.createTemplateAction({
905
+ id: "gitlab:issues:create",
906
+ description: "Creates a Gitlab issue.",
907
+ examples: examples$6,
908
+ schema: {
909
+ input: commonGitlabConfig.merge(issueInputProperties),
910
+ output: issueOutputProperties
911
+ },
912
+ async handler(ctx) {
913
+ try {
914
+ const {
915
+ repoUrl,
916
+ projectId,
917
+ title,
918
+ description = "",
919
+ confidential = false,
920
+ assignees = [],
921
+ createdAt = "",
922
+ dueDate,
923
+ discussionToResolve = "",
924
+ epicId,
925
+ labels = "",
926
+ issueType,
927
+ mergeRequestToResolveDiscussionsOf,
928
+ milestoneId,
929
+ weight,
546
930
  token
547
- });
548
- } else {
549
- api = new rest.Gitlab({
550
- host: integrationConfig.config.baseUrl,
551
- oauthToken: token
552
- });
553
- }
554
- const response = await api.ProjectAccessTokens.create(
555
- projectId,
556
- name,
557
- scopes,
558
- {
559
- expiresAt: expiresAt || luxon.DateTime.now().plus({ days: 365 }).toISODate(),
560
- accessLevel
931
+ } = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);
932
+ const { host } = parseRepoUrl(repoUrl, integrations);
933
+ const api = getClient({ host, integrations, token });
934
+ let isEpicScoped = false;
935
+ if (epicId) {
936
+ isEpicScoped = await checkEpicScope(
937
+ api,
938
+ projectId,
939
+ epicId
940
+ );
941
+ if (isEpicScoped) {
942
+ ctx.logger.info("Epic is within Project Scope");
943
+ } else {
944
+ ctx.logger.warn(
945
+ "Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
946
+ );
947
+ }
561
948
  }
562
- );
563
- if (!response.token) {
564
- throw new Error("Could not create project access token");
949
+ const mappedCreatedAt = convertDate(
950
+ String(createdAt),
951
+ (/* @__PURE__ */ new Date()).toISOString()
952
+ );
953
+ const mappedDueDate = dueDate ? convertDate(String(dueDate), (/* @__PURE__ */ new Date()).toISOString()) : void 0;
954
+ const issueOptions = {
955
+ description,
956
+ assigneeIds: assignees,
957
+ confidential,
958
+ epicId: isEpicScoped ? epicId : void 0,
959
+ labels,
960
+ createdAt: mappedCreatedAt,
961
+ dueDate: mappedDueDate,
962
+ discussionToResolve,
963
+ issueType,
964
+ mergeRequestToResolveDiscussionsOf,
965
+ milestoneId,
966
+ weight
967
+ };
968
+ const response = await api.Issues.create(
969
+ projectId,
970
+ title,
971
+ issueOptions
972
+ );
973
+ ctx.output("issueId", response.id);
974
+ ctx.output("issueUrl", response.web_url);
975
+ ctx.output("issueIid", response.iid);
976
+ } catch (error) {
977
+ if (error instanceof zod.z.ZodError) {
978
+ throw new errors.InputError(`Validation error: ${error.message}`, {
979
+ validationErrors: error.errors
980
+ });
981
+ }
982
+ throw new errors.InputError(`Failed to create GitLab issue: ${error.message}`);
565
983
  }
566
- ctx.output("access_token", response.token);
567
984
  }
568
985
  });
569
986
  };
570
987
 
571
- const examples$4 = [
572
- {
573
- description: "Creating a GitLab project variable of type env_var",
574
- example: yaml__default.default.stringify({
575
- steps: [
576
- {
577
- id: "createVariable",
578
- action: "gitlab:createGitlabProjectVariableAction",
579
- name: "Create GitLab Project Variable",
580
- input: {
581
- repoUrl: "gitlab.com?repo=repo&owner=owner",
582
- projectId: "123",
583
- key: "MY_VARIABLE",
584
- value: "my_value",
585
- variableType: "env_var"
586
- }
587
- }
588
- ]
589
- })
590
- },
988
+ function createGitlabApi(options) {
989
+ const { integrations, token: providedToken, repoUrl } = options;
990
+ const { host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
991
+ const integrationConfig = integrations.gitlab.byHost(host);
992
+ if (!integrationConfig) {
993
+ throw new errors.InputError(
994
+ `No matching integration configuration for host ${host}, please check your integrations config`
995
+ );
996
+ }
997
+ if (!integrationConfig.config.token && !providedToken) {
998
+ throw new errors.InputError(`No token available for host ${host}`);
999
+ }
1000
+ const token = providedToken ?? integrationConfig.config.token;
1001
+ const tokenType = providedToken ? "oauthToken" : "token";
1002
+ return new node.Gitlab({
1003
+ host: integrationConfig.config.baseUrl,
1004
+ [tokenType]: token
1005
+ });
1006
+ }
1007
+
1008
+ const examples$5 = [
591
1009
  {
592
- description: "Creating a GitLab project variable of type file",
1010
+ description: "Create a merge request with a specific assignee",
593
1011
  example: yaml__default.default.stringify({
594
1012
  steps: [
595
1013
  {
596
- id: "createVariable",
597
- action: "gitlab:createGitlabProjectVariableAction",
598
- name: "Create GitLab Project Variable",
1014
+ id: "createMergeRequest",
1015
+ action: "publish:gitlab:merge-request",
1016
+ name: "Create a Merge Request",
599
1017
  input: {
600
1018
  repoUrl: "gitlab.com?repo=repo&owner=owner",
601
- projectId: "123",
602
- key: "MY_VARIABLE",
603
- value: "my-file-content",
604
- variableType: "file"
1019
+ title: "Create my new MR",
1020
+ description: "This MR is really good",
1021
+ sourcePath: "./path/to/my/changes",
1022
+ branchName: "new-mr",
1023
+ assignee: "my-assignee"
605
1024
  }
606
1025
  }
607
1026
  ]
608
1027
  })
609
1028
  },
610
1029
  {
611
- description: "Create a GitLab project variable that is protected.",
1030
+ description: "Create a merge request with removal of source branch after merge",
612
1031
  example: yaml__default.default.stringify({
613
1032
  steps: [
614
1033
  {
615
- id: "createVariable",
616
- action: "gitlab:createGitlabProjectVariableAction",
617
- name: "Create GitLab Project Variable",
1034
+ id: "createMergeRequest",
1035
+ action: "publish:gitlab:merge-request",
1036
+ name: "Create a Merge Request",
618
1037
  input: {
619
1038
  repoUrl: "gitlab.com?repo=repo&owner=owner",
620
- projectId: "456",
621
- key: "MY_VARIABLE",
622
- value: "my_value",
623
- variableType: "env_var",
624
- variableProtected: true
1039
+ title: "Create my new MR",
1040
+ description: "This MR is really good",
1041
+ sourcePath: "./path/to/my/changes",
1042
+ branchName: "new-mr",
1043
+ removeSourceBranch: true
625
1044
  }
626
1045
  }
627
1046
  ]
628
1047
  })
629
1048
  },
630
1049
  {
631
- description: "Create a GitLab project variable with masked flag as true",
1050
+ description: "Create a merge request with a target branch",
632
1051
  example: yaml__default.default.stringify({
633
1052
  steps: [
634
1053
  {
635
- id: "createVariable",
636
- action: "gitlab:createGitlabProjectVariableAction",
637
- name: "Create GitLab Project Variable",
1054
+ id: "createMergeRequest",
1055
+ action: "publish:gitlab:merge-request",
1056
+ name: "Create a Merge Request",
638
1057
  input: {
639
1058
  repoUrl: "gitlab.com?repo=repo&owner=owner",
640
- projectId: "789",
641
- key: "DB_PASSWORD",
642
- value: "password123",
643
- variableType: "env_var",
644
- masked: true
1059
+ title: "Create my new MR",
1060
+ description: "This MR is really good",
1061
+ sourcePath: "./path/to/my/changes",
1062
+ branchName: "new-mr",
1063
+ targetBranchName: "test",
1064
+ targetPath: "Subdirectory"
645
1065
  }
646
1066
  }
647
1067
  ]
648
1068
  })
649
1069
  },
650
1070
  {
651
- description: "Create a GitLab project variable that is expandable.",
1071
+ description: "Create a merge request with a commit action as create",
652
1072
  example: yaml__default.default.stringify({
653
1073
  steps: [
654
1074
  {
655
- id: "createVariable",
656
- action: "gitlab:projectVariable:create",
657
- name: "Create GitLab Project Variable",
1075
+ id: "createMergeRequest",
1076
+ action: "publish:gitlab:merge-request",
1077
+ name: "Create a Merge Request",
658
1078
  input: {
659
1079
  repoUrl: "gitlab.com?repo=repo&owner=owner",
660
- projectId: "123",
661
- key: "MY_VARIABLE",
662
- value: "my_value",
663
- variableType: "env_var",
664
- raw: true
1080
+ title: "Create my new MR",
1081
+ branchName: "new-mr",
1082
+ description: "MR description",
1083
+ commitAction: "create",
1084
+ targetPath: "source"
665
1085
  }
666
1086
  }
667
1087
  ]
668
1088
  })
669
1089
  },
670
1090
  {
671
- description: "Create a GitLab project variable with a specific environment scope.",
1091
+ description: "Create a merge request with a commit action as delete",
672
1092
  example: yaml__default.default.stringify({
673
1093
  steps: [
674
1094
  {
675
- id: "createVariable",
676
- action: "gitlab:projectVariable:create",
677
- name: "Create GitLab Project Variable",
678
- input: {
679
- repoUrl: "gitlab.com?repo=repo&owner=owner",
680
- projectId: "123",
681
- key: "MY_VARIABLE",
682
- value: "my_value",
683
- variableType: "env_var",
684
- environmentScope: "production"
1095
+ id: "createMergeRequest",
1096
+ action: "publish:gitlab:merge-request",
1097
+ name: "Create a Merge Request",
1098
+ input: {
1099
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1100
+ title: "Create my new MR",
1101
+ branchName: "new-mr",
1102
+ description: "MR description",
1103
+ commitAction: "delete",
1104
+ targetPath: "source"
685
1105
  }
686
1106
  }
687
1107
  ]
688
1108
  })
689
1109
  },
690
1110
  {
691
- description: "Create a GitLab project variable with a wildcard environment scope.",
1111
+ description: "Create a merge request with a commit action as update",
692
1112
  example: yaml__default.default.stringify({
693
1113
  steps: [
694
1114
  {
695
- id: "createVariable",
696
- action: "gitlab:projectVariable:create",
697
- name: "Create GitLab Project Variable",
1115
+ id: "createMergeRequest",
1116
+ action: "publish:gitlab:merge-request",
1117
+ name: "Create a Merge Request",
698
1118
  input: {
699
1119
  repoUrl: "gitlab.com?repo=repo&owner=owner",
700
- projectId: "123",
701
- key: "MY_VARIABLE",
702
- value: "my_value",
703
- variableType: "env_var",
704
- environmentScope: "*"
1120
+ title: "Create my new MR",
1121
+ branchName: "new-mr",
1122
+ description: "MR description",
1123
+ commitAction: "update",
1124
+ targetPath: "source"
705
1125
  }
706
1126
  }
707
1127
  ]
@@ -709,120 +1129,212 @@ const examples$4 = [
709
1129
  }
710
1130
  ];
711
1131
 
712
- const createGitlabProjectVariableAction = (options) => {
1132
+ const createPublishGitlabMergeRequestAction = (options) => {
713
1133
  const { integrations } = options;
714
1134
  return pluginScaffolderNode.createTemplateAction({
715
- id: "gitlab:projectVariable:create",
716
- examples: examples$4,
1135
+ id: "publish:gitlab:merge-request",
1136
+ examples: examples$5,
717
1137
  schema: {
718
- input: commonGitlabConfig.merge(
719
- zod.z.object({
720
- projectId: zod.z.union([zod.z.number(), zod.z.string()], {
721
- description: "Project ID"
722
- }),
723
- key: zod.z.string({
724
- description: "The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed"
725
- }).regex(/^[A-Za-z0-9_]{1,255}$/),
726
- value: zod.z.string({ description: "The value of a variable" }),
727
- variableType: zod.z.string({
728
- description: "Variable Type (env_var or file)"
729
- }),
730
- variableProtected: zod.z.boolean({ description: "Whether the variable is protected" }).default(false).optional(),
731
- masked: zod.z.boolean({ description: "Whether the variable is masked" }).default(false).optional(),
732
- raw: zod.z.boolean({ description: "Whether the variable is expandable" }).default(false).optional(),
733
- environmentScope: zod.z.string({ description: "The environment_scope of the variable" }).default("*").optional()
734
- })
735
- )
1138
+ input: {
1139
+ required: ["repoUrl", "branchName"],
1140
+ type: "object",
1141
+ properties: {
1142
+ repoUrl: {
1143
+ type: "string",
1144
+ title: "Repository Location",
1145
+ description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`
1146
+ },
1147
+ /** @deprecated projectID is passed as query parameters in the repoUrl */
1148
+ projectid: {
1149
+ type: "string",
1150
+ title: "projectid",
1151
+ description: "Project ID/Name(slug) of the Gitlab Project"
1152
+ },
1153
+ title: {
1154
+ type: "string",
1155
+ title: "Merge Request Name",
1156
+ description: "The name for the merge request"
1157
+ },
1158
+ description: {
1159
+ type: "string",
1160
+ title: "Merge Request Description",
1161
+ description: "The description of the merge request"
1162
+ },
1163
+ branchName: {
1164
+ type: "string",
1165
+ title: "Source Branch Name",
1166
+ description: "The source branch name of the merge request"
1167
+ },
1168
+ targetBranchName: {
1169
+ type: "string",
1170
+ title: "Target Branch Name",
1171
+ description: "The target branch name of the merge request"
1172
+ },
1173
+ sourcePath: {
1174
+ type: "string",
1175
+ title: "Working Subdirectory",
1176
+ description: "Subdirectory of working directory to copy changes from"
1177
+ },
1178
+ targetPath: {
1179
+ type: "string",
1180
+ title: "Repository Subdirectory",
1181
+ description: "Subdirectory of repository to apply changes to"
1182
+ },
1183
+ token: {
1184
+ title: "Authentication Token",
1185
+ type: "string",
1186
+ description: "The token to use for authorization to GitLab"
1187
+ },
1188
+ commitAction: {
1189
+ title: "Commit action",
1190
+ type: "string",
1191
+ enum: ["create", "update", "delete"],
1192
+ description: "The action to be used for git commit. Defaults to create."
1193
+ },
1194
+ removeSourceBranch: {
1195
+ title: "Delete source branch",
1196
+ type: "boolean",
1197
+ description: "Option to delete source branch once the MR has been merged. Default: false"
1198
+ },
1199
+ assignee: {
1200
+ title: "Merge Request Assignee",
1201
+ type: "string",
1202
+ description: "User this merge request will be assigned to"
1203
+ }
1204
+ }
1205
+ },
1206
+ output: {
1207
+ type: "object",
1208
+ properties: {
1209
+ targetBranchName: {
1210
+ title: "Target branch name of the merge request",
1211
+ type: "string"
1212
+ },
1213
+ projectid: {
1214
+ title: "Gitlab Project id/Name(slug)",
1215
+ type: "string"
1216
+ },
1217
+ projectPath: {
1218
+ title: "Gitlab Project path",
1219
+ type: "string"
1220
+ },
1221
+ mergeRequestUrl: {
1222
+ title: "MergeRequest(MR) URL",
1223
+ type: "string",
1224
+ description: "Link to the merge request in GitLab"
1225
+ }
1226
+ }
1227
+ }
736
1228
  },
737
1229
  async handler(ctx) {
738
1230
  const {
739
- projectId,
740
- key,
741
- value,
742
- variableType,
743
- variableProtected = false,
744
- masked = false,
745
- raw = false,
746
- environmentScope = "*"
747
- } = ctx.input;
748
- const { token, integrationConfig } = getToken(ctx.input, integrations);
749
- const api = new node.Gitlab({
750
- host: integrationConfig.config.baseUrl,
1231
+ assignee,
1232
+ branchName,
1233
+ targetBranchName,
1234
+ description,
1235
+ repoUrl,
1236
+ removeSourceBranch,
1237
+ targetPath,
1238
+ sourcePath,
1239
+ title,
751
1240
  token
1241
+ } = ctx.input;
1242
+ const { owner, repo, project } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
1243
+ const repoID = project ? project : `${owner}/${repo}`;
1244
+ const api = createGitlabApi({
1245
+ integrations,
1246
+ token,
1247
+ repoUrl
752
1248
  });
753
- await api.ProjectVariables.create(projectId, {
754
- key,
755
- value,
756
- variable_type: variableType,
757
- protected: variableProtected,
758
- masked,
759
- raw,
760
- environment_scope: environmentScope
761
- });
762
- }
763
- });
764
- };
765
-
766
- const examples$3 = [
767
- {
768
- description: "Create a GitLab issue with minimal options",
769
- example: yaml__default.default.stringify({
770
- steps: [
771
- {
772
- id: "gitlabIssue",
773
- name: "Issues",
774
- action: "gitlab:issues:create",
775
- input: {
776
- ...commonGitlabConfigExample,
777
- projectId: 12,
778
- title: "Test Issue",
779
- description: "This is the description of the issue"
780
- }
1249
+ let assigneeId = void 0;
1250
+ if (assignee !== void 0) {
1251
+ try {
1252
+ const assigneeUser = await api.Users.username(assignee);
1253
+ assigneeId = assigneeUser[0].id;
1254
+ } catch (e) {
1255
+ ctx.logger.warn(
1256
+ `Failed to find gitlab user id for ${assignee}: ${e}. Proceeding with MR creation without an assignee.`
1257
+ );
781
1258
  }
782
- ]
783
- })
784
- },
785
- {
786
- description: "Create a GitLab issue with assignees and date options",
787
- example: yaml__default.default.stringify({
788
- steps: [
789
- {
790
- id: "gitlabIssue",
791
- name: "Issues",
792
- action: "gitlab:issues:create",
793
- input: {
794
- ...commonGitlabConfigExample,
795
- projectId: 12,
796
- title: "Test Issue",
797
- assignees: [18],
798
- description: "This is the description of the issue",
799
- createdAt: "2022-09-27 18:00:00.000",
800
- dueDate: "2022-09-28 12:00:00.000"
1259
+ }
1260
+ let fileRoot;
1261
+ if (sourcePath) {
1262
+ fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, sourcePath);
1263
+ } else if (targetPath) {
1264
+ fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
1265
+ } else {
1266
+ fileRoot = ctx.workspacePath;
1267
+ }
1268
+ const fileContents = await pluginScaffolderNode.serializeDirectoryContents(fileRoot, {
1269
+ gitignore: true
1270
+ });
1271
+ const actions = fileContents.map((file) => ({
1272
+ action: ctx.input.commitAction ?? "create",
1273
+ filePath: targetPath ? path__default.default.posix.join(targetPath, file.path) : file.path,
1274
+ encoding: "base64",
1275
+ content: file.content.toString("base64"),
1276
+ execute_filemode: file.executable
1277
+ }));
1278
+ let targetBranch = targetBranchName;
1279
+ if (!targetBranch) {
1280
+ const projects = await api.Projects.show(repoID);
1281
+ const { default_branch: defaultBranch } = projects;
1282
+ targetBranch = defaultBranch;
1283
+ }
1284
+ try {
1285
+ await api.Branches.create(repoID, branchName, String(targetBranch));
1286
+ } catch (e) {
1287
+ throw new errors.InputError(
1288
+ `The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${e}`
1289
+ );
1290
+ }
1291
+ try {
1292
+ await api.Commits.create(repoID, branchName, ctx.input.title, actions);
1293
+ } catch (e) {
1294
+ throw new errors.InputError(
1295
+ `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${e}`
1296
+ );
1297
+ }
1298
+ try {
1299
+ const mergeRequestUrl = await api.MergeRequests.create(
1300
+ repoID,
1301
+ branchName,
1302
+ String(targetBranch),
1303
+ title,
1304
+ {
1305
+ description,
1306
+ removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
1307
+ assigneeId
801
1308
  }
802
- }
803
- ]
804
- })
805
- },
1309
+ ).then((mergeRequest) => {
1310
+ return mergeRequest.web_url;
1311
+ });
1312
+ ctx.output("projectid", repoID);
1313
+ ctx.output("targetBranchName", targetBranch);
1314
+ ctx.output("projectPath", repoID);
1315
+ ctx.output("mergeRequestUrl", mergeRequestUrl);
1316
+ } catch (e) {
1317
+ throw new errors.InputError(`Merge request creation failed${e}`);
1318
+ }
1319
+ }
1320
+ });
1321
+ };
1322
+
1323
+ const examples$4 = [
806
1324
  {
807
- description: "Create a GitLab Issue with several options",
1325
+ description: "Trigger a GitLab Project Pipeline",
808
1326
  example: yaml__default.default.stringify({
809
1327
  steps: [
810
1328
  {
811
- id: "gitlabIssue",
812
- name: "Issues",
813
- action: "gitlab:issues:create",
1329
+ id: "triggerPipeline",
1330
+ name: "Trigger Project Pipeline",
1331
+ action: "gitlab:pipeline:trigger",
814
1332
  input: {
815
1333
  ...commonGitlabConfigExample,
816
1334
  projectId: 12,
817
- title: "Test Issue",
818
- assignees: [18, 15],
819
- description: "This is the description of the issue",
820
- confidential: false,
821
- createdAt: "2022-09-27 18:00:00.000",
822
- dueDate: "2022-09-28 12:00:00.000",
823
- discussionToResolve: 1,
824
- epicId: 1,
825
- labels: "phase1:label1,phase2:label2"
1335
+ tokenDescription: "This is the text that will appear in the pipeline token",
1336
+ token: "glpt-xxxxxxxxxxxx",
1337
+ branch: "main"
826
1338
  }
827
1339
  }
828
1340
  ]
@@ -830,788 +1342,509 @@ const examples$3 = [
830
1342
  }
831
1343
  ];
832
1344
 
833
- var IssueType = /* @__PURE__ */ ((IssueType2) => {
834
- IssueType2["ISSUE"] = "issue";
835
- IssueType2["INCIDENT"] = "incident";
836
- IssueType2["TEST"] = "test_case";
837
- return IssueType2;
838
- })(IssueType || {});
839
- const issueInputProperties = zod.z.object({
1345
+ const pipelineInputProperties = zod.z.object({
840
1346
  projectId: zod.z.number().describe("Project Id"),
841
- title: zod.z.string({ description: "Title of the issue" }),
842
- assignees: zod.z.array(zod.z.number(), {
843
- description: "IDs of the users to assign the issue to."
844
- }).optional(),
845
- confidential: zod.z.boolean({ description: "Issue Confidentiality" }).optional(),
846
- description: zod.z.string().describe("Issue description").max(1048576).optional(),
847
- createdAt: zod.z.string().describe("Creation date/time").regex(
848
- /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
849
- "Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
850
- ).optional(),
851
- dueDate: zod.z.string().describe("Due date/time").regex(
852
- /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
853
- "Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
854
- ).optional(),
855
- discussionToResolve: zod.z.string({
856
- description: 'Id of a discussion to resolve. Use in combination with "merge_request_to_resolve_discussions_of"'
857
- }).optional(),
858
- epicId: zod.z.number({ description: "Id of the linked Epic" }).min(0, "Valid values should be equal or greater than zero").optional(),
859
- labels: zod.z.string({ description: "Labels to apply" }).optional(),
860
- issueType: zod.z.nativeEnum(IssueType, {
861
- description: "Type of the issue"
862
- }).optional(),
863
- mergeRequestToResolveDiscussionsOf: zod.z.number({
864
- description: "IID of a merge request in which to resolve all issues"
865
- }).optional(),
866
- milestoneId: zod.z.number({ description: "Global ID of a milestone to assign the issue" }).optional(),
867
- weight: zod.z.number({ description: "The issue weight" }).min(0).refine((value) => {
868
- const isValid = value >= 0;
869
- if (!isValid) {
870
- return {
871
- message: "Valid values should be equal or greater than zero"
872
- };
873
- }
874
- return isValid;
875
- }).optional()
1347
+ tokenDescription: zod.z.string().describe("Pipeline token description"),
1348
+ branch: zod.z.string().describe("Project branch")
876
1349
  });
877
- const issueOutputProperties = zod.z.object({
878
- issueUrl: zod.z.string({ description: "Issue Url" }),
879
- issueId: zod.z.number({ description: "Issue Id" }),
880
- issueIid: zod.z.number({ description: "Issue Iid" })
1350
+ const pipelineOutputProperties = zod.z.object({
1351
+ pipelineUrl: zod.z.string({ description: "Pipeline Url" })
881
1352
  });
882
- const createGitlabIssueAction = (options) => {
1353
+ const createTriggerGitlabPipelineAction = (options) => {
883
1354
  const { integrations } = options;
884
1355
  return pluginScaffolderNode.createTemplateAction({
885
- id: "gitlab:issues:create",
886
- description: "Creates a Gitlab issue.",
887
- examples: examples$3,
1356
+ id: "gitlab:pipeline:trigger",
1357
+ description: "Triggers a GitLab Pipeline.",
1358
+ examples: examples$4,
888
1359
  schema: {
889
- input: commonGitlabConfig.merge(issueInputProperties),
890
- output: issueOutputProperties
1360
+ input: commonGitlabConfig.merge(pipelineInputProperties),
1361
+ output: pipelineOutputProperties
891
1362
  },
892
1363
  async handler(ctx) {
1364
+ let pipelineTokenResponse = null;
1365
+ const { repoUrl, projectId, tokenDescription, token, branch } = commonGitlabConfig.merge(pipelineInputProperties).parse(ctx.input);
1366
+ const { host } = parseRepoUrl(repoUrl, integrations);
1367
+ const api = getClient({ host, integrations, token });
893
1368
  try {
894
- const {
895
- repoUrl,
1369
+ pipelineTokenResponse = await api.PipelineTriggerTokens.create(
896
1370
  projectId,
897
- title,
898
- description = "",
899
- confidential = false,
900
- assignees = [],
901
- createdAt = "",
902
- dueDate,
903
- discussionToResolve = "",
904
- epicId,
905
- labels = "",
906
- issueType,
907
- mergeRequestToResolveDiscussionsOf,
908
- milestoneId,
909
- weight,
910
- token
911
- } = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);
912
- const { host } = parseRepoUrl(repoUrl, integrations);
913
- const api = getClient({ host, integrations, token });
914
- let isEpicScoped = false;
915
- if (epicId) {
916
- isEpicScoped = await checkEpicScope(
917
- api,
918
- projectId,
919
- epicId
920
- );
921
- if (isEpicScoped) {
922
- ctx.logger.info("Epic is within Project Scope");
923
- } else {
924
- ctx.logger.warn(
925
- "Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
926
- );
927
- }
1371
+ tokenDescription
1372
+ );
1373
+ if (!pipelineTokenResponse.token) {
1374
+ ctx.logger.error("Failed to create pipeline token.");
1375
+ return;
928
1376
  }
929
- const mappedCreatedAt = convertDate(
930
- String(createdAt),
931
- (/* @__PURE__ */ new Date()).toISOString()
1377
+ ctx.logger.info(
1378
+ `Pipeline token id ${pipelineTokenResponse.id} created.`
932
1379
  );
933
- const mappedDueDate = dueDate ? convertDate(String(dueDate), (/* @__PURE__ */ new Date()).toISOString()) : void 0;
934
- const issueOptions = {
935
- description,
936
- assigneeIds: assignees,
937
- confidential,
938
- epicId: isEpicScoped ? epicId : void 0,
939
- labels,
940
- createdAt: mappedCreatedAt,
941
- dueDate: mappedDueDate,
942
- discussionToResolve,
943
- issueType,
944
- mergeRequestToResolveDiscussionsOf,
945
- milestoneId,
946
- weight
947
- };
948
- const response = await api.Issues.create(
1380
+ const pipelineTriggerResponse = await api.PipelineTriggerTokens.trigger(
949
1381
  projectId,
950
- title,
951
- issueOptions
1382
+ branch,
1383
+ pipelineTokenResponse.token
952
1384
  );
953
- ctx.output("issueId", response.id);
954
- ctx.output("issueUrl", response.web_url);
955
- ctx.output("issueIid", response.iid);
1385
+ if (!pipelineTriggerResponse.id) {
1386
+ ctx.logger.error("Failed to trigger pipeline.");
1387
+ return;
1388
+ }
1389
+ ctx.logger.info(`Pipeline id ${pipelineTriggerResponse.id} triggered.`);
1390
+ ctx.output("pipelineUrl", pipelineTriggerResponse.web_url);
956
1391
  } catch (error) {
957
1392
  if (error instanceof zod.z.ZodError) {
958
1393
  throw new errors.InputError(`Validation error: ${error.message}`, {
959
1394
  validationErrors: error.errors
960
1395
  });
961
1396
  }
962
- throw new errors.InputError(`Failed to create GitLab issue: ${error.message}`);
963
- }
964
- }
965
- });
966
- };
967
-
968
- const examples$2 = [
969
- {
970
- description: "Initializes a git repository with the content in the workspace, and publishes it to GitLab with the default configuration.",
971
- example: yaml__default.default.stringify({
972
- steps: [
973
- {
974
- id: "publish",
975
- action: "publish:gitlab",
976
- name: "Publish to GitLab",
977
- input: {
978
- repoUrl: "gitlab.com?repo=project_name&owner=group_name"
979
- }
980
- }
981
- ]
982
- })
983
- },
984
- {
985
- description: "Add a description.",
986
- example: yaml__default.default.stringify({
987
- steps: [
988
- {
989
- id: "publish",
990
- action: "publish:gitlab",
991
- name: "Publish to GitLab",
992
- input: {
993
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
994
- description: "Initialize a git repository"
995
- }
996
- }
997
- ]
998
- })
999
- },
1000
- {
1001
- description: "Initializes a GitLab repository with an initial commit message, if not set defaults to `initial commit`.",
1002
- example: yaml__default.default.stringify({
1003
- steps: [
1004
- {
1005
- id: "publish",
1006
- action: "publish:gitlab",
1007
- name: "Publish to GitLab",
1008
- input: {
1009
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
1010
- description: "Initialize a git repository",
1011
- gitCommitMessage: "Started a project."
1012
- }
1013
- }
1014
- ]
1015
- })
1016
- },
1017
- {
1018
- description: "Initializes a GitLab repository with aditional settings.",
1019
- example: yaml__default.default.stringify({
1020
- steps: [
1021
- {
1022
- id: "publish",
1023
- action: "publish:gitlab",
1024
- name: "Publish to GitLab",
1025
- input: {
1026
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
1027
- settings: {
1028
- ci_config_path: ".gitlab-ci.yml",
1029
- visibility: "public"
1030
- }
1031
- }
1032
- }
1033
- ]
1034
- })
1035
- },
1036
- {
1037
- description: "Initializes a GitLab repository with fast forward merge and always squash settings.",
1038
- example: yaml__default.default.stringify({
1039
- steps: [
1040
- {
1041
- id: "publish",
1042
- action: "publish:gitlab",
1043
- name: "Publish to GitLab",
1044
- input: {
1045
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
1046
- settings: {
1047
- merge_method: "ff",
1048
- squash_option: "always"
1049
- }
1397
+ throw new errors.InputError(`Failed to trigger Pipeline: ${error.message}`);
1398
+ } finally {
1399
+ if (pipelineTokenResponse && pipelineTokenResponse.id) {
1400
+ try {
1401
+ await api.PipelineTriggerTokens.remove(
1402
+ projectId,
1403
+ pipelineTokenResponse.id
1404
+ );
1405
+ ctx.logger.info(
1406
+ `Deleted pipeline token ${pipelineTokenResponse.id}.`
1407
+ );
1408
+ } catch (error) {
1409
+ ctx.logger.error(
1410
+ `Failed to delete pipeline token id ${pipelineTokenResponse.id}.`
1411
+ );
1050
1412
  }
1051
1413
  }
1052
- ]
1053
- })
1054
- },
1414
+ }
1415
+ }
1416
+ });
1417
+ };
1418
+
1419
+ const examples$3 = [
1055
1420
  {
1056
- description: "Initializes a GitLab repository with branch settings.",
1421
+ description: "Create a GitLab project access token with minimal options.",
1057
1422
  example: yaml__default.default.stringify({
1058
1423
  steps: [
1059
1424
  {
1060
- id: "publish",
1061
- action: "publish:gitlab",
1062
- name: "Publish to GitLab",
1425
+ id: "createAccessToken",
1426
+ action: "gitlab:projectAccessToken:create",
1427
+ name: "Create GitLab Project Access Token",
1063
1428
  input: {
1064
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
1065
- branches: [
1066
- {
1067
- name: "dev",
1068
- create: true,
1069
- protected: true,
1070
- ref: "master"
1071
- },
1072
- {
1073
- name: "master",
1074
- protected: true
1075
- }
1076
- ]
1429
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1430
+ projectId: "456"
1077
1431
  }
1078
1432
  }
1079
1433
  ]
1080
1434
  })
1081
1435
  },
1082
- {
1083
- description: "Initializes a GitLab repository with environment variables.",
1084
- example: yaml__default.default.stringify({
1085
- steps: [
1086
- {
1087
- id: "publish",
1088
- action: "publish:gitlab",
1089
- name: "Publish to GitLab",
1090
- input: {
1091
- repoUrl: "gitlab.com?repo=project_name&owner=group_name",
1092
- projectVariables: [
1093
- {
1094
- key: "key1",
1095
- value: "value1",
1096
- protected: true,
1097
- masked: false
1098
- },
1099
- {
1100
- key: "key2",
1101
- value: "value2",
1102
- protected: true,
1103
- masked: false
1104
- }
1105
- ]
1106
- }
1107
- }
1108
- ]
1109
- })
1110
- }
1111
- ];
1112
-
1113
- function createPublishGitlabAction(options) {
1114
- const { integrations, config } = options;
1115
- return pluginScaffolderNode.createTemplateAction({
1116
- id: "publish:gitlab",
1117
- description: "Initializes a git repository of the content in the workspace, and publishes it to GitLab.",
1118
- examples: examples$2,
1119
- schema: {
1120
- input: {
1121
- type: "object",
1122
- required: ["repoUrl"],
1123
- properties: {
1124
- repoUrl: {
1125
- title: "Repository Location",
1126
- type: "string",
1127
- description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`
1128
- },
1129
- repoVisibility: {
1130
- title: "Repository Visibility",
1131
- description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`,
1132
- type: "string",
1133
- enum: ["private", "public", "internal"]
1134
- },
1135
- defaultBranch: {
1136
- title: "Default Branch",
1137
- type: "string",
1138
- description: `Sets the default branch on the repository. The default value is 'master'`
1139
- },
1140
- gitCommitMessage: {
1141
- title: "Git Commit Message",
1142
- type: "string",
1143
- description: `Sets the commit message on the repository. The default value is 'initial commit'`
1144
- },
1145
- gitAuthorName: {
1146
- title: "Default Author Name",
1147
- type: "string",
1148
- description: `Sets the default author name for the commit. The default value is 'Scaffolder'`
1149
- },
1150
- gitAuthorEmail: {
1151
- title: "Default Author Email",
1152
- type: "string",
1153
- description: `Sets the default author email for the commit.`
1154
- },
1155
- sourcePath: {
1156
- title: "Source Path",
1157
- description: "Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.",
1158
- type: "string"
1159
- },
1160
- token: {
1161
- title: "Authentication Token",
1162
- type: "string",
1163
- description: "The token to use for authorization to GitLab"
1164
- },
1165
- setUserAsOwner: {
1166
- title: "Set User As Owner",
1167
- type: "boolean",
1168
- description: "Set the token user as owner of the newly created repository. Requires a token authorized to do the edit in the integration configuration for the matching host"
1169
- },
1170
- topics: {
1171
- title: "Topic labels",
1172
- description: "Topic labels to apply on the repository. (deprecated, use settings.topics instead)",
1173
- type: "array",
1174
- items: {
1175
- type: "string"
1176
- }
1177
- },
1178
- settings: {
1179
- title: "Project settings",
1180
- description: "Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes",
1181
- type: "object",
1182
- properties: {
1183
- path: {
1184
- title: "Project path",
1185
- description: "Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).",
1186
- type: "string"
1187
- },
1188
- auto_devops_enabled: {
1189
- title: "Auto DevOps enabled",
1190
- description: "Enable Auto DevOps for this project",
1191
- type: "boolean"
1192
- },
1193
- ci_config_path: {
1194
- title: "CI config path",
1195
- description: "Custom CI config path for this project",
1196
- type: "string"
1197
- },
1198
- description: {
1199
- title: "Project description",
1200
- description: "Short project description",
1201
- type: "string"
1202
- },
1203
- merge_method: {
1204
- title: "Merge Method to use",
1205
- description: "Merge Methods (merge, rebase_merge, ff)",
1206
- type: "string",
1207
- enum: ["merge", "rebase_merge", "ff"]
1208
- },
1209
- squash_option: {
1210
- title: "Squash option",
1211
- description: "Set squash option for the project (never, always, default_on, default_off)",
1212
- type: "string",
1213
- enum: ["default_off", "default_on", "never", "always"]
1214
- },
1215
- topics: {
1216
- title: "Topic labels",
1217
- description: "Topic labels to apply on the repository",
1218
- type: "array",
1219
- items: {
1220
- type: "string"
1221
- }
1222
- },
1223
- visibility: {
1224
- title: "Project visibility",
1225
- description: "The visibility of the project. Can be private, internal, or public. The default value is private.",
1226
- type: "string",
1227
- enum: ["private", "public", "internal"]
1228
- }
1229
- }
1230
- },
1231
- branches: {
1232
- title: "Project branches settings",
1233
- type: "array",
1234
- items: {
1235
- type: "object",
1236
- required: ["name"],
1237
- properties: {
1238
- name: {
1239
- title: "Branch name",
1240
- type: "string"
1241
- },
1242
- protect: {
1243
- title: "Should branch be protected",
1244
- description: `Will mark branch as protected. The default value is 'false'`,
1245
- type: "boolean"
1246
- },
1247
- create: {
1248
- title: "Should branch be created",
1249
- description: `If branch does not exist, it will be created from provided ref. The default value is 'false'`,
1250
- type: "boolean"
1251
- },
1252
- ref: {
1253
- title: "Branch reference",
1254
- description: `Branch reference to create branch from. The default value is 'master'`,
1255
- type: "string"
1256
- }
1257
- }
1258
- }
1259
- },
1260
- projectVariables: {
1261
- title: "Project variables",
1262
- description: "Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable",
1263
- type: "array",
1264
- items: {
1265
- type: "object",
1266
- required: ["key", "value"],
1267
- properties: {
1268
- key: {
1269
- title: "Variable key",
1270
- description: "The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed",
1271
- type: "string"
1272
- },
1273
- value: {
1274
- title: "Variable value",
1275
- description: "The value of a variable",
1276
- type: "string"
1277
- },
1278
- description: {
1279
- title: "Variable description",
1280
- description: `The description of the variable. The default value is 'null'`,
1281
- type: "string"
1282
- },
1283
- variable_type: {
1284
- title: "Variable type",
1285
- description: `The type of a variable. The default value is 'env_var'`,
1286
- type: "string",
1287
- enum: ["env_var", "file"]
1288
- },
1289
- protected: {
1290
- title: "Variable protection",
1291
- description: `Whether the variable is protected. The default value is 'false'`,
1292
- type: "boolean"
1293
- },
1294
- raw: {
1295
- title: "Variable raw",
1296
- description: `Whether the variable is in raw format. The default value is 'false'`,
1297
- type: "boolean"
1298
- },
1299
- environment_scope: {
1300
- title: "Variable environment scope",
1301
- description: `The environment_scope of the variable. The default value is '*'`,
1302
- type: "string"
1303
- }
1304
- }
1305
- }
1436
+ {
1437
+ description: "Create a GitLab project access token with custom scopes.",
1438
+ example: yaml__default.default.stringify({
1439
+ steps: [
1440
+ {
1441
+ id: "createAccessToken",
1442
+ action: "gitlab:projectAccessToken:create",
1443
+ name: "Create GitLab Project Access Token",
1444
+ input: {
1445
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1446
+ projectId: "789",
1447
+ scopes: ["read_registry", "write_repository"]
1306
1448
  }
1307
1449
  }
1308
- },
1309
- output: {
1310
- type: "object",
1311
- properties: {
1312
- remoteUrl: {
1313
- title: "A URL to the repository with the provider",
1314
- type: "string"
1315
- },
1316
- repoContentsUrl: {
1317
- title: "A URL to the root of the repository",
1318
- type: "string"
1319
- },
1320
- projectId: {
1321
- title: "The ID of the project",
1322
- type: "string"
1323
- },
1324
- commitHash: {
1325
- title: "The git commit hash of the initial commit",
1326
- type: "string"
1450
+ ]
1451
+ })
1452
+ },
1453
+ {
1454
+ description: "Create a GitLab project access token with a specified name.",
1455
+ example: yaml__default.default.stringify({
1456
+ steps: [
1457
+ {
1458
+ id: "createAccessToken",
1459
+ action: "gitlab:projectAccessToken:create",
1460
+ name: "Create GitLab Project Access Token",
1461
+ input: {
1462
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1463
+ projectId: "101112",
1464
+ name: "my-custom-token"
1327
1465
  }
1328
1466
  }
1329
- }
1467
+ ]
1468
+ })
1469
+ },
1470
+ {
1471
+ description: "Create a GitLab project access token with a numeric project ID.",
1472
+ example: yaml__default.default.stringify({
1473
+ steps: [
1474
+ {
1475
+ id: "createAccessToken",
1476
+ action: "gitlab:projectAccessToken:create",
1477
+ name: "Create GitLab Project Access Token",
1478
+ input: {
1479
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1480
+ projectId: 42
1481
+ }
1482
+ }
1483
+ ]
1484
+ })
1485
+ },
1486
+ {
1487
+ description: "Create a GitLab project access token with a specified expired Date.",
1488
+ example: yaml__default.default.stringify({
1489
+ steps: [
1490
+ {
1491
+ id: "createAccessToken",
1492
+ action: "gitlab:projectAccessToken:create",
1493
+ name: "Create GitLab Project Access Token",
1494
+ input: {
1495
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1496
+ projectId: "123",
1497
+ expiresAt: "2024-06-25"
1498
+ }
1499
+ }
1500
+ ]
1501
+ })
1502
+ }
1503
+ ];
1504
+
1505
+ const createGitlabProjectAccessTokenAction = (options) => {
1506
+ const { integrations } = options;
1507
+ return pluginScaffolderNode.createTemplateAction({
1508
+ id: "gitlab:projectAccessToken:create",
1509
+ examples: examples$3,
1510
+ schema: {
1511
+ input: zod.z.object({
1512
+ projectId: zod.z.union([zod.z.number(), zod.z.string()], {
1513
+ description: "Project ID/Name(slug) of the Gitlab Project"
1514
+ }),
1515
+ token: zod.z.string({
1516
+ description: "The token to use for authorization to GitLab"
1517
+ }).optional(),
1518
+ name: zod.z.string({ description: "Name of Access Key" }).optional(),
1519
+ repoUrl: zod.z.string({ description: "URL to gitlab instance" }),
1520
+ accessLevel: zod.z.number({
1521
+ description: "Access Level of the Token, 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), and 50 (Owner)"
1522
+ }).optional(),
1523
+ scopes: zod.z.string({
1524
+ description: "Scopes for a project access token"
1525
+ }).array().optional(),
1526
+ expiresAt: zod.z.string({
1527
+ description: "Expiration date of the access token in ISO format (YYYY-MM-DD). If Empty, it will set to the maximum of 365 days."
1528
+ }).optional()
1529
+ }),
1530
+ output: zod.z.object({
1531
+ access_token: zod.z.string({ description: "Access Token" })
1532
+ })
1330
1533
  },
1331
1534
  async handler(ctx) {
1535
+ ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
1332
1536
  const {
1333
- repoUrl,
1334
- repoVisibility = "private",
1335
- defaultBranch = "master",
1336
- gitCommitMessage = "initial commit",
1337
- gitAuthorName,
1338
- gitAuthorEmail,
1339
- setUserAsOwner = false,
1340
- topics = [],
1341
- settings = {},
1342
- branches = [],
1343
- projectVariables = []
1537
+ projectId,
1538
+ name = "tokenname",
1539
+ accessLevel = 40,
1540
+ scopes = ["read_repository"],
1541
+ expiresAt
1344
1542
  } = ctx.input;
1345
- const { owner, repo, host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
1346
- if (!owner) {
1347
- throw new errors.InputError(
1348
- `No owner provided for host: ${host}, and repo ${repo}`
1349
- );
1350
- }
1351
- const integrationConfig = integrations.gitlab.byHost(host);
1352
- if (!integrationConfig) {
1543
+ const { token, integrationConfig } = getToken(ctx.input, integrations);
1544
+ if (!integrationConfig.config.token && token) {
1353
1545
  throw new errors.InputError(
1354
- `No matching integration configuration for host ${host}, please check your integrations config`
1546
+ `No token available for host ${integrationConfig.config.baseUrl}`
1355
1547
  );
1356
1548
  }
1357
- if (!integrationConfig.config.token && !ctx.input.token) {
1358
- throw new errors.InputError(`No token available for host ${host}`);
1359
- }
1360
- const token = ctx.input.token || integrationConfig.config.token;
1361
- const tokenType = ctx.input.token ? "oauthToken" : "token";
1362
- const client = new node.Gitlab({
1363
- host: integrationConfig.config.baseUrl,
1364
- [tokenType]: token
1365
- });
1366
- let targetNamespaceId;
1367
- try {
1368
- const namespaceResponse = await client.Namespaces.show(owner);
1369
- targetNamespaceId = namespaceResponse.id;
1370
- } catch (e) {
1371
- if (e.response && e.response.statusCode === 404) {
1372
- throw new errors.InputError(
1373
- `The namespace ${owner} is not found or the user doesn't have permissions to access it`
1374
- );
1375
- }
1376
- throw e;
1377
- }
1378
- const { id: userId } = await client.Users.current();
1379
- if (!targetNamespaceId) {
1380
- targetNamespaceId = userId;
1381
- }
1382
- const { id: projectId, http_url_to_repo } = await client.Projects.create({
1383
- namespace_id: targetNamespaceId,
1384
- name: repo,
1385
- visibility: repoVisibility,
1386
- ...topics.length ? { topics } : {},
1387
- ...Object.keys(settings).length ? { ...settings } : {}
1388
- });
1389
- if (setUserAsOwner && integrationConfig.config.token) {
1390
- const adminClient = new node.Gitlab({
1549
+ let api;
1550
+ if (!ctx.input.token) {
1551
+ api = new rest.Gitlab({
1391
1552
  host: integrationConfig.config.baseUrl,
1392
- token: integrationConfig.config.token
1553
+ token
1554
+ });
1555
+ } else {
1556
+ api = new rest.Gitlab({
1557
+ host: integrationConfig.config.baseUrl,
1558
+ oauthToken: token
1393
1559
  });
1394
- await adminClient.ProjectMembers.add(projectId, userId, 50);
1395
1560
  }
1396
- const remoteUrl = http_url_to_repo.replace(/\.git$/, "");
1397
- const repoContentsUrl = `${remoteUrl}/-/blob/${defaultBranch}`;
1398
- const gitAuthorInfo = {
1399
- name: gitAuthorName ? gitAuthorName : config.getOptionalString("scaffolder.defaultAuthor.name"),
1400
- email: gitAuthorEmail ? gitAuthorEmail : config.getOptionalString("scaffolder.defaultAuthor.email")
1401
- };
1402
- const commitResult = await pluginScaffolderNode.initRepoAndPush({
1403
- dir: pluginScaffolderNode.getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
1404
- remoteUrl: http_url_to_repo,
1405
- defaultBranch,
1406
- auth: {
1407
- username: "oauth2",
1408
- password: token
1409
- },
1410
- logger: ctx.logger,
1411
- commitMessage: gitCommitMessage ? gitCommitMessage : config.getOptionalString("scaffolder.defaultCommitMessage"),
1412
- gitAuthorInfo
1413
- });
1414
- if (branches) {
1415
- for (const branch of branches) {
1416
- const {
1417
- name,
1418
- protect = false,
1419
- create = false,
1420
- ref = "master"
1421
- } = branch;
1422
- if (create) {
1423
- try {
1424
- await client.Branches.create(projectId, name, ref);
1425
- } catch (e) {
1426
- throw new errors.InputError(
1427
- `Branch creation failed for ${name}. ${printGitlabError(e)}`
1428
- );
1429
- }
1430
- ctx.logger.info(
1431
- `Branch ${name} created for ${projectId} with ref ${ref}`
1432
- );
1561
+ const response = await api.ProjectAccessTokens.create(
1562
+ projectId,
1563
+ name,
1564
+ scopes,
1565
+ {
1566
+ expiresAt: expiresAt || luxon.DateTime.now().plus({ days: 365 }).toISODate(),
1567
+ accessLevel
1568
+ }
1569
+ );
1570
+ if (!response.token) {
1571
+ throw new Error("Could not create project access token");
1572
+ }
1573
+ ctx.output("access_token", response.token);
1574
+ }
1575
+ });
1576
+ };
1577
+
1578
+ const examples$2 = [
1579
+ {
1580
+ description: "Create a GitLab project deploy token with minimal options.",
1581
+ example: yaml__default.default.stringify({
1582
+ steps: [
1583
+ {
1584
+ id: "createDeployToken",
1585
+ action: "gitlab:projectDeployToken:create",
1586
+ name: "Create GitLab Project Deploy Token",
1587
+ input: {
1588
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1589
+ projectId: "456",
1590
+ name: "tokenname"
1591
+ }
1592
+ }
1593
+ ]
1594
+ })
1595
+ },
1596
+ {
1597
+ description: "Create a GitLab project deploy token with custom scopes.",
1598
+ example: yaml__default.default.stringify({
1599
+ steps: [
1600
+ {
1601
+ id: "createDeployToken",
1602
+ action: "gitlab:projectDeployToken:create",
1603
+ name: "Create GitLab Project Deploy Token",
1604
+ input: {
1605
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1606
+ projectId: "789",
1607
+ name: "tokenname",
1608
+ scopes: ["read_registry", "write_repository"]
1433
1609
  }
1434
- if (protect) {
1435
- try {
1436
- await client.ProtectedBranches.protect(projectId, name);
1437
- } catch (e) {
1438
- throw new errors.InputError(
1439
- `Branch protection failed for ${name}. ${printGitlabError(e)}`
1440
- );
1441
- }
1442
- ctx.logger.info(`Branch ${name} protected for ${projectId}`);
1610
+ }
1611
+ ]
1612
+ })
1613
+ },
1614
+ {
1615
+ description: "Create a GitLab project deploy token with a specified name.",
1616
+ example: yaml__default.default.stringify({
1617
+ steps: [
1618
+ {
1619
+ id: "createDeployToken",
1620
+ action: "gitlab:projectDeployToken:create",
1621
+ name: "Create GitLab Project Deploy Token",
1622
+ input: {
1623
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1624
+ projectId: "101112",
1625
+ name: "my-custom-token"
1443
1626
  }
1444
1627
  }
1445
- }
1446
- if (projectVariables) {
1447
- for (const variable of projectVariables) {
1448
- const variableWithDefaults = Object.assign(variable, {
1449
- variable_type: variable.variable_type ?? "env_var",
1450
- protected: variable.protected ?? false,
1451
- masked: variable.masked ?? false,
1452
- raw: variable.raw ?? false,
1453
- environment_scope: variable.environment_scope ?? "*"
1454
- });
1455
- try {
1456
- await client.ProjectVariables.create(
1457
- projectId,
1458
- variableWithDefaults
1459
- );
1460
- } catch (e) {
1461
- throw new errors.InputError(
1462
- `Environment variable creation failed for ${variableWithDefaults.key}. ${printGitlabError(e)}`
1463
- );
1628
+ ]
1629
+ })
1630
+ },
1631
+ {
1632
+ description: "Create a GitLab project deploy token with a numeric project ID.",
1633
+ example: yaml__default.default.stringify({
1634
+ steps: [
1635
+ {
1636
+ id: "createDeployToken",
1637
+ action: "gitlab:projectDeployToken:create",
1638
+ name: "Create GitLab Project Deploy Token",
1639
+ input: {
1640
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1641
+ projectId: 42,
1642
+ name: "tokenname"
1643
+ }
1644
+ }
1645
+ ]
1646
+ })
1647
+ },
1648
+ {
1649
+ description: "Create a GitLab project deploy token with a custom username",
1650
+ example: yaml__default.default.stringify({
1651
+ steps: [
1652
+ {
1653
+ id: "createDeployToken",
1654
+ action: "gitlab:projectDeployToken:create",
1655
+ name: "Create GitLab Project Deploy Token",
1656
+ input: {
1657
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1658
+ projectId: 42,
1659
+ name: "tokenname",
1660
+ username: "tokenuser"
1464
1661
  }
1465
1662
  }
1663
+ ]
1664
+ })
1665
+ }
1666
+ ];
1667
+
1668
+ const createGitlabProjectDeployTokenAction = (options) => {
1669
+ const { integrations } = options;
1670
+ return pluginScaffolderNode.createTemplateAction({
1671
+ id: "gitlab:projectDeployToken:create",
1672
+ examples: examples$2,
1673
+ schema: {
1674
+ input: commonGitlabConfig.merge(
1675
+ zod.z.object({
1676
+ projectId: zod.z.union([zod.z.number(), zod.z.string()], {
1677
+ description: "Project ID"
1678
+ }),
1679
+ name: zod.z.string({ description: "Deploy Token Name" }),
1680
+ username: zod.z.string({ description: "Deploy Token Username" }).optional(),
1681
+ scopes: zod.z.array(zod.z.string(), { description: "Scopes" }).optional()
1682
+ })
1683
+ ),
1684
+ output: zod.z.object({
1685
+ deploy_token: zod.z.string({ description: "Deploy Token" }),
1686
+ user: zod.z.string({ description: "User" })
1687
+ })
1688
+ },
1689
+ async handler(ctx) {
1690
+ ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
1691
+ const { projectId, name, username, scopes } = ctx.input;
1692
+ const { token, integrationConfig } = getToken(ctx.input, integrations);
1693
+ const api = new node.Gitlab({
1694
+ host: integrationConfig.config.baseUrl,
1695
+ token
1696
+ });
1697
+ const deployToken = await api.ProjectDeployTokens.add(
1698
+ projectId,
1699
+ name,
1700
+ scopes,
1701
+ {
1702
+ username
1703
+ }
1704
+ );
1705
+ if (!deployToken.hasOwnProperty("token")) {
1706
+ throw new errors.InputError(`No deploy_token given from gitlab instance`);
1466
1707
  }
1467
- ctx.output("commitHash", commitResult?.commitHash);
1468
- ctx.output("remoteUrl", remoteUrl);
1469
- ctx.output("repoContentsUrl", repoContentsUrl);
1470
- ctx.output("projectId", projectId);
1708
+ ctx.output("deploy_token", deployToken.token);
1709
+ ctx.output("user", deployToken.username);
1471
1710
  }
1472
1711
  });
1473
- }
1474
- function printGitlabError(error) {
1475
- return JSON.stringify({ code: error.code, message: error.description });
1476
- }
1477
-
1478
- function createGitlabApi(options) {
1479
- const { integrations, token: providedToken, repoUrl } = options;
1480
- const { host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
1481
- const integrationConfig = integrations.gitlab.byHost(host);
1482
- if (!integrationConfig) {
1483
- throw new errors.InputError(
1484
- `No matching integration configuration for host ${host}, please check your integrations config`
1485
- );
1486
- }
1487
- if (!integrationConfig.config.token && !providedToken) {
1488
- throw new errors.InputError(`No token available for host ${host}`);
1489
- }
1490
- const token = providedToken ?? integrationConfig.config.token;
1491
- const tokenType = providedToken ? "oauthToken" : "token";
1492
- return new node.Gitlab({
1493
- host: integrationConfig.config.baseUrl,
1494
- [tokenType]: token
1495
- });
1496
- }
1712
+ };
1497
1713
 
1498
1714
  const examples$1 = [
1499
1715
  {
1500
- description: "Create a merge request with a specific assignee",
1716
+ description: "Creating a GitLab project variable of type env_var",
1501
1717
  example: yaml__default.default.stringify({
1502
1718
  steps: [
1503
1719
  {
1504
- id: "createMergeRequest",
1505
- action: "publish:gitlab:merge-request",
1506
- name: "Create a Merge Request",
1720
+ id: "createVariable",
1721
+ action: "gitlab:createGitlabProjectVariableAction",
1722
+ name: "Create GitLab Project Variable",
1507
1723
  input: {
1508
1724
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1509
- title: "Create my new MR",
1510
- description: "This MR is really good",
1511
- sourcePath: "./path/to/my/changes",
1512
- branchName: "new-mr",
1513
- assignee: "my-assignee"
1725
+ projectId: "123",
1726
+ key: "MY_VARIABLE",
1727
+ value: "my_value",
1728
+ variableType: "env_var"
1514
1729
  }
1515
1730
  }
1516
1731
  ]
1517
1732
  })
1518
1733
  },
1519
1734
  {
1520
- description: "Create a merge request with removal of source branch after merge",
1735
+ description: "Creating a GitLab project variable of type file",
1521
1736
  example: yaml__default.default.stringify({
1522
1737
  steps: [
1523
1738
  {
1524
- id: "createMergeRequest",
1525
- action: "publish:gitlab:merge-request",
1526
- name: "Create a Merge Request",
1739
+ id: "createVariable",
1740
+ action: "gitlab:createGitlabProjectVariableAction",
1741
+ name: "Create GitLab Project Variable",
1527
1742
  input: {
1528
1743
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1529
- title: "Create my new MR",
1530
- description: "This MR is really good",
1531
- sourcePath: "./path/to/my/changes",
1532
- branchName: "new-mr",
1533
- removeSourceBranch: true
1744
+ projectId: "123",
1745
+ key: "MY_VARIABLE",
1746
+ value: "my-file-content",
1747
+ variableType: "file"
1534
1748
  }
1535
1749
  }
1536
1750
  ]
1537
1751
  })
1538
1752
  },
1539
1753
  {
1540
- description: "Create a merge request with a target branch",
1754
+ description: "Create a GitLab project variable that is protected.",
1541
1755
  example: yaml__default.default.stringify({
1542
1756
  steps: [
1543
1757
  {
1544
- id: "createMergeRequest",
1545
- action: "publish:gitlab:merge-request",
1546
- name: "Create a Merge Request",
1758
+ id: "createVariable",
1759
+ action: "gitlab:createGitlabProjectVariableAction",
1760
+ name: "Create GitLab Project Variable",
1547
1761
  input: {
1548
1762
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1549
- title: "Create my new MR",
1550
- description: "This MR is really good",
1551
- sourcePath: "./path/to/my/changes",
1552
- branchName: "new-mr",
1553
- targetBranchName: "test",
1554
- targetPath: "Subdirectory"
1763
+ projectId: "456",
1764
+ key: "MY_VARIABLE",
1765
+ value: "my_value",
1766
+ variableType: "env_var",
1767
+ variableProtected: true
1555
1768
  }
1556
1769
  }
1557
1770
  ]
1558
1771
  })
1559
1772
  },
1560
1773
  {
1561
- description: "Create a merge request with a commit action as create",
1774
+ description: "Create a GitLab project variable with masked flag as true",
1562
1775
  example: yaml__default.default.stringify({
1563
1776
  steps: [
1564
1777
  {
1565
- id: "createMergeRequest",
1566
- action: "publish:gitlab:merge-request",
1567
- name: "Create a Merge Request",
1778
+ id: "createVariable",
1779
+ action: "gitlab:createGitlabProjectVariableAction",
1780
+ name: "Create GitLab Project Variable",
1568
1781
  input: {
1569
1782
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1570
- title: "Create my new MR",
1571
- branchName: "new-mr",
1572
- description: "MR description",
1573
- commitAction: "create",
1574
- targetPath: "source"
1783
+ projectId: "789",
1784
+ key: "DB_PASSWORD",
1785
+ value: "password123",
1786
+ variableType: "env_var",
1787
+ masked: true
1788
+ }
1789
+ }
1790
+ ]
1791
+ })
1792
+ },
1793
+ {
1794
+ description: "Create a GitLab project variable that is expandable.",
1795
+ example: yaml__default.default.stringify({
1796
+ steps: [
1797
+ {
1798
+ id: "createVariable",
1799
+ action: "gitlab:projectVariable:create",
1800
+ name: "Create GitLab Project Variable",
1801
+ input: {
1802
+ repoUrl: "gitlab.com?repo=repo&owner=owner",
1803
+ projectId: "123",
1804
+ key: "MY_VARIABLE",
1805
+ value: "my_value",
1806
+ variableType: "env_var",
1807
+ raw: true
1575
1808
  }
1576
1809
  }
1577
1810
  ]
1578
1811
  })
1579
1812
  },
1580
1813
  {
1581
- description: "Create a merge request with a commit action as delete",
1814
+ description: "Create a GitLab project variable with a specific environment scope.",
1582
1815
  example: yaml__default.default.stringify({
1583
1816
  steps: [
1584
1817
  {
1585
- id: "createMergeRequest",
1586
- action: "publish:gitlab:merge-request",
1587
- name: "Create a Merge Request",
1818
+ id: "createVariable",
1819
+ action: "gitlab:projectVariable:create",
1820
+ name: "Create GitLab Project Variable",
1588
1821
  input: {
1589
1822
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1590
- title: "Create my new MR",
1591
- branchName: "new-mr",
1592
- description: "MR description",
1593
- commitAction: "delete",
1594
- targetPath: "source"
1823
+ projectId: "123",
1824
+ key: "MY_VARIABLE",
1825
+ value: "my_value",
1826
+ variableType: "env_var",
1827
+ environmentScope: "production"
1595
1828
  }
1596
1829
  }
1597
1830
  ]
1598
1831
  })
1599
1832
  },
1600
1833
  {
1601
- description: "Create a merge request with a commit action as update",
1834
+ description: "Create a GitLab project variable with a wildcard environment scope.",
1602
1835
  example: yaml__default.default.stringify({
1603
1836
  steps: [
1604
1837
  {
1605
- id: "createMergeRequest",
1606
- action: "publish:gitlab:merge-request",
1607
- name: "Create a Merge Request",
1838
+ id: "createVariable",
1839
+ action: "gitlab:projectVariable:create",
1840
+ name: "Create GitLab Project Variable",
1608
1841
  input: {
1609
1842
  repoUrl: "gitlab.com?repo=repo&owner=owner",
1610
- title: "Create my new MR",
1611
- branchName: "new-mr",
1612
- description: "MR description",
1613
- commitAction: "update",
1614
- targetPath: "source"
1843
+ projectId: "123",
1844
+ key: "MY_VARIABLE",
1845
+ value: "my_value",
1846
+ variableType: "env_var",
1847
+ environmentScope: "*"
1615
1848
  }
1616
1849
  }
1617
1850
  ]
@@ -1619,193 +1852,56 @@ const examples$1 = [
1619
1852
  }
1620
1853
  ];
1621
1854
 
1622
- const createPublishGitlabMergeRequestAction = (options) => {
1855
+ const createGitlabProjectVariableAction = (options) => {
1623
1856
  const { integrations } = options;
1624
1857
  return pluginScaffolderNode.createTemplateAction({
1625
- id: "publish:gitlab:merge-request",
1858
+ id: "gitlab:projectVariable:create",
1626
1859
  examples: examples$1,
1627
1860
  schema: {
1628
- input: {
1629
- required: ["repoUrl", "branchName"],
1630
- type: "object",
1631
- properties: {
1632
- repoUrl: {
1633
- type: "string",
1634
- title: "Repository Location",
1635
- description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`
1636
- },
1637
- /** @deprecated projectID is passed as query parameters in the repoUrl */
1638
- projectid: {
1639
- type: "string",
1640
- title: "projectid",
1641
- description: "Project ID/Name(slug) of the Gitlab Project"
1642
- },
1643
- title: {
1644
- type: "string",
1645
- title: "Merge Request Name",
1646
- description: "The name for the merge request"
1647
- },
1648
- description: {
1649
- type: "string",
1650
- title: "Merge Request Description",
1651
- description: "The description of the merge request"
1652
- },
1653
- branchName: {
1654
- type: "string",
1655
- title: "Source Branch Name",
1656
- description: "The source branch name of the merge request"
1657
- },
1658
- targetBranchName: {
1659
- type: "string",
1660
- title: "Target Branch Name",
1661
- description: "The target branch name of the merge request"
1662
- },
1663
- sourcePath: {
1664
- type: "string",
1665
- title: "Working Subdirectory",
1666
- description: "Subdirectory of working directory to copy changes from"
1667
- },
1668
- targetPath: {
1669
- type: "string",
1670
- title: "Repository Subdirectory",
1671
- description: "Subdirectory of repository to apply changes to"
1672
- },
1673
- token: {
1674
- title: "Authentication Token",
1675
- type: "string",
1676
- description: "The token to use for authorization to GitLab"
1677
- },
1678
- commitAction: {
1679
- title: "Commit action",
1680
- type: "string",
1681
- enum: ["create", "update", "delete"],
1682
- description: "The action to be used for git commit. Defaults to create."
1683
- },
1684
- removeSourceBranch: {
1685
- title: "Delete source branch",
1686
- type: "boolean",
1687
- description: "Option to delete source branch once the MR has been merged. Default: false"
1688
- },
1689
- assignee: {
1690
- title: "Merge Request Assignee",
1691
- type: "string",
1692
- description: "User this merge request will be assigned to"
1693
- }
1694
- }
1695
- },
1696
- output: {
1697
- type: "object",
1698
- properties: {
1699
- targetBranchName: {
1700
- title: "Target branch name of the merge request",
1701
- type: "string"
1702
- },
1703
- projectid: {
1704
- title: "Gitlab Project id/Name(slug)",
1705
- type: "string"
1706
- },
1707
- projectPath: {
1708
- title: "Gitlab Project path",
1709
- type: "string"
1710
- },
1711
- mergeRequestUrl: {
1712
- title: "MergeRequest(MR) URL",
1713
- type: "string",
1714
- description: "Link to the merge request in GitLab"
1715
- }
1716
- }
1717
- }
1861
+ input: commonGitlabConfig.merge(
1862
+ zod.z.object({
1863
+ projectId: zod.z.union([zod.z.number(), zod.z.string()], {
1864
+ description: "Project ID"
1865
+ }),
1866
+ key: zod.z.string({
1867
+ description: "The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed"
1868
+ }).regex(/^[A-Za-z0-9_]{1,255}$/),
1869
+ value: zod.z.string({ description: "The value of a variable" }),
1870
+ variableType: zod.z.string({
1871
+ description: "Variable Type (env_var or file)"
1872
+ }),
1873
+ variableProtected: zod.z.boolean({ description: "Whether the variable is protected" }).default(false).optional(),
1874
+ masked: zod.z.boolean({ description: "Whether the variable is masked" }).default(false).optional(),
1875
+ raw: zod.z.boolean({ description: "Whether the variable is expandable" }).default(false).optional(),
1876
+ environmentScope: zod.z.string({ description: "The environment_scope of the variable" }).default("*").optional()
1877
+ })
1878
+ )
1718
1879
  },
1719
1880
  async handler(ctx) {
1720
1881
  const {
1721
- assignee,
1722
- branchName,
1723
- targetBranchName,
1724
- description,
1725
- repoUrl,
1726
- removeSourceBranch,
1727
- targetPath,
1728
- sourcePath,
1729
- title,
1730
- token
1882
+ projectId,
1883
+ key,
1884
+ value,
1885
+ variableType,
1886
+ variableProtected = false,
1887
+ masked = false,
1888
+ raw = false,
1889
+ environmentScope = "*"
1731
1890
  } = ctx.input;
1732
- const { owner, repo, project } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
1733
- const repoID = project ? project : `${owner}/${repo}`;
1734
- const api = createGitlabApi({
1735
- integrations,
1736
- token,
1737
- repoUrl
1891
+ const { token, integrationConfig } = getToken(ctx.input, integrations);
1892
+ const api = new node.Gitlab({
1893
+ host: integrationConfig.config.baseUrl,
1894
+ token
1738
1895
  });
1739
- let assigneeId = void 0;
1740
- if (assignee !== void 0) {
1741
- try {
1742
- const assigneeUser = await api.Users.username(assignee);
1743
- assigneeId = assigneeUser[0].id;
1744
- } catch (e) {
1745
- ctx.logger.warn(
1746
- `Failed to find gitlab user id for ${assignee}: ${e}. Proceeding with MR creation without an assignee.`
1747
- );
1748
- }
1749
- }
1750
- let fileRoot;
1751
- if (sourcePath) {
1752
- fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, sourcePath);
1753
- } else if (targetPath) {
1754
- fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
1755
- } else {
1756
- fileRoot = ctx.workspacePath;
1757
- }
1758
- const fileContents = await pluginScaffolderNode.serializeDirectoryContents(fileRoot, {
1759
- gitignore: true
1896
+ await api.ProjectVariables.create(projectId, {
1897
+ key,
1898
+ value,
1899
+ variable_type: variableType,
1900
+ protected: variableProtected,
1901
+ masked,
1902
+ raw,
1903
+ environment_scope: environmentScope
1760
1904
  });
1761
- const actions = fileContents.map((file) => ({
1762
- action: ctx.input.commitAction ?? "create",
1763
- filePath: targetPath ? path__default.default.posix.join(targetPath, file.path) : file.path,
1764
- encoding: "base64",
1765
- content: file.content.toString("base64"),
1766
- execute_filemode: file.executable
1767
- }));
1768
- let targetBranch = targetBranchName;
1769
- if (!targetBranch) {
1770
- const projects = await api.Projects.show(repoID);
1771
- const { default_branch: defaultBranch } = projects;
1772
- targetBranch = defaultBranch;
1773
- }
1774
- try {
1775
- await api.Branches.create(repoID, branchName, String(targetBranch));
1776
- } catch (e) {
1777
- throw new errors.InputError(
1778
- `The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${e}`
1779
- );
1780
- }
1781
- try {
1782
- await api.Commits.create(repoID, branchName, ctx.input.title, actions);
1783
- } catch (e) {
1784
- throw new errors.InputError(
1785
- `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${e}`
1786
- );
1787
- }
1788
- try {
1789
- const mergeRequestUrl = await api.MergeRequests.create(
1790
- repoID,
1791
- branchName,
1792
- String(targetBranch),
1793
- title,
1794
- {
1795
- description,
1796
- removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
1797
- assigneeId
1798
- }
1799
- ).then((mergeRequest) => {
1800
- return mergeRequest.web_url;
1801
- });
1802
- ctx.output("projectid", repoID);
1803
- ctx.output("targetBranchName", targetBranch);
1804
- ctx.output("projectPath", repoID);
1805
- ctx.output("mergeRequestUrl", mergeRequestUrl);
1806
- } catch (e) {
1807
- throw new errors.InputError(`Merge request creation failed${e}`);
1808
- }
1809
1905
  }
1810
1906
  });
1811
1907
  };
@@ -2025,7 +2121,8 @@ const gitlabModule = backendPluginApi.createBackendModule({
2025
2121
  createGitlabProjectVariableAction({ integrations }),
2026
2122
  createGitlabRepoPushAction({ integrations }),
2027
2123
  createPublishGitlabAction({ config, integrations }),
2028
- createPublishGitlabMergeRequestAction({ integrations })
2124
+ createPublishGitlabMergeRequestAction({ integrations }),
2125
+ createTriggerGitlabPipelineAction({ integrations })
2029
2126
  );
2030
2127
  }
2031
2128
  });
@@ -2041,5 +2138,6 @@ exports.createGitlabProjectVariableAction = createGitlabProjectVariableAction;
2041
2138
  exports.createGitlabRepoPushAction = createGitlabRepoPushAction;
2042
2139
  exports.createPublishGitlabAction = createPublishGitlabAction;
2043
2140
  exports.createPublishGitlabMergeRequestAction = createPublishGitlabMergeRequestAction;
2141
+ exports.createTriggerGitlabPipelineAction = createTriggerGitlabPipelineAction;
2044
2142
  exports.default = gitlabModule;
2045
2143
  //# sourceMappingURL=index.cjs.js.map