@backstage/plugin-scaffolder-backend-module-gitlab 0.4.1-next.0 → 0.4.1-next.2
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/CHANGELOG.md +23 -0
- package/dist/index.cjs.js +1790 -1468
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +169 -102
- package/package.json +9 -9
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
|
|
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
|
|
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$9 = [
|
|
148
23
|
{
|
|
149
|
-
description: "
|
|
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: "
|
|
154
|
-
|
|
155
|
-
|
|
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: "
|
|
39
|
+
description: "Add a description.",
|
|
166
40
|
example: yaml__default.default.stringify({
|
|
167
41
|
steps: [
|
|
168
42
|
{
|
|
169
|
-
id: "
|
|
170
|
-
|
|
171
|
-
|
|
43
|
+
id: "publish",
|
|
44
|
+
action: "publish:gitlab",
|
|
45
|
+
name: "Publish to GitLab",
|
|
172
46
|
input: {
|
|
173
|
-
repoUrl: "gitlab.com",
|
|
174
|
-
|
|
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: "
|
|
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: "
|
|
186
|
-
|
|
187
|
-
|
|
59
|
+
id: "publish",
|
|
60
|
+
action: "publish:gitlab",
|
|
61
|
+
name: "Publish to GitLab",
|
|
188
62
|
input: {
|
|
189
|
-
repoUrl: "gitlab.com",
|
|
190
|
-
|
|
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: "
|
|
72
|
+
description: "Initializes a GitLab repository with aditional settings.",
|
|
198
73
|
example: yaml__default.default.stringify({
|
|
199
74
|
steps: [
|
|
200
75
|
{
|
|
201
|
-
id: "
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
isDryRun: true,
|
|
76
|
+
id: "publish",
|
|
77
|
+
action: "publish:gitlab",
|
|
78
|
+
name: "Publish to GitLab",
|
|
205
79
|
input: {
|
|
206
|
-
repoUrl: "
|
|
207
|
-
|
|
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: "
|
|
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: "
|
|
283
|
-
action: "gitlab
|
|
284
|
-
name: "
|
|
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=
|
|
456
|
-
|
|
457
|
-
|
|
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: "
|
|
110
|
+
description: "Initializes a GitLab repository with branch settings.",
|
|
465
111
|
example: yaml__default.default.stringify({
|
|
466
112
|
steps: [
|
|
467
113
|
{
|
|
468
|
-
id: "
|
|
469
|
-
action: "gitlab
|
|
470
|
-
name: "
|
|
114
|
+
id: "publish",
|
|
115
|
+
action: "publish:gitlab",
|
|
116
|
+
name: "Publish to GitLab",
|
|
471
117
|
input: {
|
|
472
|
-
repoUrl: "gitlab.com?repo=
|
|
473
|
-
|
|
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: "
|
|
137
|
+
description: "Initializes a GitLab repository with environment variables.",
|
|
481
138
|
example: yaml__default.default.stringify({
|
|
482
139
|
steps: [
|
|
483
140
|
{
|
|
484
|
-
id: "
|
|
485
|
-
action: "gitlab
|
|
486
|
-
name: "
|
|
141
|
+
id: "publish",
|
|
142
|
+
action: "publish:gitlab",
|
|
143
|
+
name: "Publish to GitLab",
|
|
487
144
|
input: {
|
|
488
|
-
repoUrl: "gitlab.com?repo=
|
|
489
|
-
|
|
490
|
-
|
|
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,1185 @@ const examples$5 = [
|
|
|
495
164
|
}
|
|
496
165
|
];
|
|
497
166
|
|
|
498
|
-
|
|
499
|
-
const { integrations } = options;
|
|
167
|
+
function createPublishGitlabAction(options) {
|
|
168
|
+
const { integrations, config } = options;
|
|
500
169
|
return pluginScaffolderNode.createTemplateAction({
|
|
501
|
-
id: "gitlab
|
|
502
|
-
|
|
170
|
+
id: "publish:gitlab",
|
|
171
|
+
description: "Initializes a git repository of the content in the workspace, and publishes it to GitLab.",
|
|
172
|
+
examples: examples$9,
|
|
503
173
|
schema: {
|
|
504
|
-
input:
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
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
|
+
var IssueType = /* @__PURE__ */ ((IssueType2) => {
|
|
541
|
+
IssueType2["ISSUE"] = "issue";
|
|
542
|
+
IssueType2["INCIDENT"] = "incident";
|
|
543
|
+
IssueType2["TEST"] = "test_case";
|
|
544
|
+
IssueType2["TASK"] = "task";
|
|
545
|
+
return IssueType2;
|
|
546
|
+
})(IssueType || {});
|
|
547
|
+
var IssueStateEvent = /* @__PURE__ */ ((IssueStateEvent2) => {
|
|
548
|
+
IssueStateEvent2["CLOSE"] = "close";
|
|
549
|
+
IssueStateEvent2["REOPEN"] = "reopen";
|
|
550
|
+
return IssueStateEvent2;
|
|
551
|
+
})(IssueStateEvent || {});
|
|
552
|
+
|
|
553
|
+
const parseRepoHost = (repoUrl) => {
|
|
554
|
+
let parsed;
|
|
555
|
+
try {
|
|
556
|
+
parsed = new URL(`https://${repoUrl}`);
|
|
557
|
+
} catch (error) {
|
|
558
|
+
throw new errors.InputError(
|
|
559
|
+
`Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
return parsed.host;
|
|
563
|
+
};
|
|
564
|
+
const getToken = (config, integrations) => {
|
|
565
|
+
const host = parseRepoHost(config.repoUrl);
|
|
566
|
+
const integrationConfig = integrations.gitlab.byHost(host);
|
|
567
|
+
if (!integrationConfig) {
|
|
568
|
+
throw new errors.InputError(
|
|
569
|
+
`No matching integration configuration for host ${host}, please check your integrations config`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
const token = config.token || integrationConfig.config.token;
|
|
573
|
+
return { token, integrationConfig };
|
|
574
|
+
};
|
|
575
|
+
const parseRepoUrl = (repoUrl, integrations) => {
|
|
576
|
+
let parsed;
|
|
577
|
+
try {
|
|
578
|
+
parsed = new URL(`https://${repoUrl}`);
|
|
579
|
+
} catch (error) {
|
|
580
|
+
throw new errors.InputError(
|
|
581
|
+
`Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
const host = parsed.host;
|
|
585
|
+
const owner = parsed.searchParams.get("owner") ?? void 0;
|
|
586
|
+
const repo = parsed.searchParams.get("repo");
|
|
587
|
+
const type = integrations.byHost(host)?.type;
|
|
588
|
+
if (!type) {
|
|
589
|
+
throw new errors.InputError(
|
|
590
|
+
`No matching integration configuration for host ${host}, please check your integrations config`
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
return { host, owner, repo };
|
|
594
|
+
};
|
|
595
|
+
function getClient(props) {
|
|
596
|
+
const { host, token, integrations } = props;
|
|
597
|
+
const integrationConfig = integrations.gitlab.byHost(host);
|
|
598
|
+
if (!integrationConfig) {
|
|
599
|
+
throw new errors.InputError(
|
|
600
|
+
`No matching integration configuration for host ${host}, please check your integrations config`
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
const { config } = integrationConfig;
|
|
604
|
+
if (!config.token && !token) {
|
|
605
|
+
throw new errors.InputError(`No token available for host ${host}`);
|
|
606
|
+
}
|
|
607
|
+
const requestToken = token || config.token;
|
|
608
|
+
const tokenType = token ? "oauthToken" : "token";
|
|
609
|
+
const gitlabOptions = {
|
|
610
|
+
host: config.baseUrl
|
|
611
|
+
};
|
|
612
|
+
gitlabOptions[tokenType] = requestToken;
|
|
613
|
+
return new rest.Gitlab(gitlabOptions);
|
|
614
|
+
}
|
|
615
|
+
function convertDate(inputDate, defaultDate) {
|
|
616
|
+
try {
|
|
617
|
+
return inputDate ? new Date(inputDate).toISOString() : new Date(defaultDate).toISOString();
|
|
618
|
+
} catch (error) {
|
|
619
|
+
throw new errors.InputError(`Error converting input date - ${error}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
async function getTopLevelParentGroup(client, groupId) {
|
|
623
|
+
try {
|
|
624
|
+
const topParentGroup = await client.Groups.show(groupId);
|
|
625
|
+
if (topParentGroup.parent_id) {
|
|
626
|
+
return getTopLevelParentGroup(
|
|
627
|
+
client,
|
|
628
|
+
topParentGroup.parent_id
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
return topParentGroup;
|
|
632
|
+
} catch (error) {
|
|
633
|
+
throw new errors.InputError(
|
|
634
|
+
`Error finding top-level parent group ID: ${error.message}`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
async function checkEpicScope(client, projectId, epicId) {
|
|
639
|
+
try {
|
|
640
|
+
const project = await client.Projects.show(projectId);
|
|
641
|
+
if (!project) {
|
|
642
|
+
throw new errors.InputError(
|
|
643
|
+
`Project with id ${projectId} not found. Check your GitLab instance.`
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
const topParentGroup = await getTopLevelParentGroup(
|
|
647
|
+
client,
|
|
648
|
+
project.namespace.id
|
|
649
|
+
);
|
|
650
|
+
if (!topParentGroup) {
|
|
651
|
+
throw new errors.InputError(`Couldn't find a suitable top-level parent group.`);
|
|
652
|
+
}
|
|
653
|
+
const epic = (await client.Epics.all(topParentGroup.id)).find(
|
|
654
|
+
(x) => x.id === epicId
|
|
655
|
+
);
|
|
656
|
+
if (!epic) {
|
|
657
|
+
throw new errors.InputError(
|
|
658
|
+
`Epic with id ${epicId} not found in the top-level parent group ${topParentGroup.name}.`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
const epicGroup = await client.Groups.show(epic.group_id);
|
|
662
|
+
const projectNamespace = project.path_with_namespace;
|
|
663
|
+
return projectNamespace.startsWith(epicGroup.full_path);
|
|
664
|
+
} catch (error) {
|
|
665
|
+
throw new errors.InputError(`Could not find epic scope: ${error.message}`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const examples$8 = [
|
|
670
|
+
{
|
|
671
|
+
description: "Creating a group at the top level",
|
|
672
|
+
example: yaml__default.default.stringify({
|
|
673
|
+
steps: [
|
|
674
|
+
{
|
|
675
|
+
id: "gitlabGroup",
|
|
676
|
+
name: "Group",
|
|
677
|
+
action: "gitlab:group:ensureExists",
|
|
678
|
+
input: {
|
|
679
|
+
repoUrl: "gitlab.com",
|
|
680
|
+
path: ["group1"]
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
]
|
|
684
|
+
})
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
description: "Create a group nested within another group",
|
|
688
|
+
example: yaml__default.default.stringify({
|
|
689
|
+
steps: [
|
|
690
|
+
{
|
|
691
|
+
id: "gitlabGroup",
|
|
692
|
+
name: "Group",
|
|
693
|
+
action: "gitlab:group:ensureExists",
|
|
694
|
+
input: {
|
|
695
|
+
repoUrl: "gitlab.com",
|
|
696
|
+
path: ["group1", "group2"]
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
]
|
|
700
|
+
})
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
description: "Create a group nested within multiple other groups",
|
|
704
|
+
example: yaml__default.default.stringify({
|
|
705
|
+
steps: [
|
|
706
|
+
{
|
|
707
|
+
id: "gitlabGroup",
|
|
708
|
+
name: "Group",
|
|
709
|
+
action: "gitlab:group:ensureExists",
|
|
710
|
+
input: {
|
|
711
|
+
repoUrl: "gitlab.com",
|
|
712
|
+
path: ["group1", "group2", "group3"]
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
]
|
|
716
|
+
})
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
description: "Create a group in dry run mode",
|
|
720
|
+
example: yaml__default.default.stringify({
|
|
721
|
+
steps: [
|
|
722
|
+
{
|
|
723
|
+
id: "gitlabGroup",
|
|
724
|
+
name: "Group",
|
|
725
|
+
action: "gitlab:group:ensureExists",
|
|
726
|
+
isDryRun: true,
|
|
727
|
+
input: {
|
|
728
|
+
repoUrl: "https://gitlab.com/my-repo",
|
|
729
|
+
path: ["group1", "group2", "group3"]
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
]
|
|
733
|
+
})
|
|
734
|
+
}
|
|
735
|
+
];
|
|
736
|
+
|
|
737
|
+
const createGitlabGroupEnsureExistsAction = (options) => {
|
|
738
|
+
const { integrations } = options;
|
|
739
|
+
return pluginScaffolderNode.createTemplateAction({
|
|
740
|
+
id: "gitlab:group:ensureExists",
|
|
741
|
+
description: "Ensures a Gitlab group exists",
|
|
742
|
+
supportsDryRun: true,
|
|
743
|
+
examples: examples$8,
|
|
744
|
+
schema: {
|
|
745
|
+
input: commonGitlabConfig.merge(
|
|
746
|
+
zod.z.object({
|
|
747
|
+
path: zod.z.array(zod.z.string(), {
|
|
748
|
+
description: "A path of group names that is ensured to exist"
|
|
749
|
+
}).min(1)
|
|
750
|
+
})
|
|
751
|
+
),
|
|
523
752
|
output: zod.z.object({
|
|
524
|
-
|
|
753
|
+
groupId: zod.z.number({ description: "The id of the innermost sub-group" }).optional()
|
|
525
754
|
})
|
|
526
755
|
},
|
|
527
756
|
async handler(ctx) {
|
|
528
|
-
ctx.
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
scopes = ["read_repository"],
|
|
534
|
-
expiresAt
|
|
535
|
-
} = ctx.input;
|
|
757
|
+
if (ctx.isDryRun) {
|
|
758
|
+
ctx.output("groupId", 42);
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const { path } = ctx.input;
|
|
536
762
|
const { token, integrationConfig } = getToken(ctx.input, integrations);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
763
|
+
const api = new node.Gitlab({
|
|
764
|
+
host: integrationConfig.config.baseUrl,
|
|
765
|
+
token
|
|
766
|
+
});
|
|
767
|
+
let currentPath = null;
|
|
768
|
+
let parent = null;
|
|
769
|
+
for (const pathElement of path) {
|
|
770
|
+
const fullPath = currentPath ? `${currentPath}/${pathElement}` : pathElement;
|
|
771
|
+
const result = await api.Groups.search(
|
|
772
|
+
fullPath
|
|
773
|
+
);
|
|
774
|
+
const subGroup = result.find(
|
|
775
|
+
(searchPathElem) => searchPathElem.full_path === fullPath
|
|
776
|
+
);
|
|
777
|
+
if (!subGroup) {
|
|
778
|
+
ctx.logger.info(`creating missing group ${fullPath}`);
|
|
779
|
+
parent = await api.Groups.create(
|
|
780
|
+
pathElement,
|
|
781
|
+
pathElement,
|
|
782
|
+
parent ? {
|
|
783
|
+
parent_id: parent.id
|
|
784
|
+
} : {}
|
|
785
|
+
);
|
|
786
|
+
} else {
|
|
787
|
+
parent = subGroup;
|
|
788
|
+
}
|
|
789
|
+
currentPath = fullPath;
|
|
790
|
+
}
|
|
791
|
+
if (parent !== null) {
|
|
792
|
+
ctx.output("groupId", parent?.id);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
const examples$7 = [
|
|
799
|
+
{
|
|
800
|
+
description: "Create a GitLab issue with minimal options",
|
|
801
|
+
example: yaml__default.default.stringify({
|
|
802
|
+
steps: [
|
|
803
|
+
{
|
|
804
|
+
id: "gitlabIssue",
|
|
805
|
+
name: "Issues",
|
|
806
|
+
action: "gitlab:issues:create",
|
|
807
|
+
input: {
|
|
808
|
+
...commonGitlabConfigExample,
|
|
809
|
+
projectId: 12,
|
|
810
|
+
title: "Test Issue",
|
|
811
|
+
description: "This is the description of the issue"
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
]
|
|
815
|
+
})
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
description: "Create a GitLab issue with assignees and date options",
|
|
819
|
+
example: yaml__default.default.stringify({
|
|
820
|
+
steps: [
|
|
821
|
+
{
|
|
822
|
+
id: "gitlabIssue",
|
|
823
|
+
name: "Issues",
|
|
824
|
+
action: "gitlab:issues:create",
|
|
825
|
+
input: {
|
|
826
|
+
...commonGitlabConfigExample,
|
|
827
|
+
projectId: 12,
|
|
828
|
+
title: "Test Issue",
|
|
829
|
+
assignees: [18],
|
|
830
|
+
description: "This is the description of the issue",
|
|
831
|
+
createdAt: "2022-09-27 18:00:00.000",
|
|
832
|
+
dueDate: "2022-09-28 12:00:00.000"
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
]
|
|
836
|
+
})
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
description: "Create a GitLab Issue with several options",
|
|
840
|
+
example: yaml__default.default.stringify({
|
|
841
|
+
steps: [
|
|
842
|
+
{
|
|
843
|
+
id: "gitlabIssue",
|
|
844
|
+
name: "Issues",
|
|
845
|
+
action: "gitlab:issues:create",
|
|
846
|
+
input: {
|
|
847
|
+
...commonGitlabConfigExample,
|
|
848
|
+
projectId: 12,
|
|
849
|
+
title: "Test Issue",
|
|
850
|
+
assignees: [18, 15],
|
|
851
|
+
description: "This is the description of the issue",
|
|
852
|
+
confidential: false,
|
|
853
|
+
createdAt: "2022-09-27 18:00:00.000",
|
|
854
|
+
dueDate: "2022-09-28 12:00:00.000",
|
|
855
|
+
discussionToResolve: 1,
|
|
856
|
+
epicId: 1,
|
|
857
|
+
labels: "phase1:label1,phase2:label2"
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
]
|
|
861
|
+
})
|
|
862
|
+
}
|
|
863
|
+
];
|
|
864
|
+
|
|
865
|
+
const issueInputProperties = zod.z.object({
|
|
866
|
+
projectId: zod.z.number().describe("Project Id"),
|
|
867
|
+
title: zod.z.string({ description: "Title of the issue" }),
|
|
868
|
+
assignees: zod.z.array(zod.z.number(), {
|
|
869
|
+
description: "IDs of the users to assign the issue to."
|
|
870
|
+
}).optional(),
|
|
871
|
+
confidential: zod.z.boolean({ description: "Issue Confidentiality" }).optional(),
|
|
872
|
+
description: zod.z.string().describe("Issue description").max(1048576).optional(),
|
|
873
|
+
createdAt: zod.z.string().describe("Creation date/time").regex(
|
|
874
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
|
875
|
+
"Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
|
|
876
|
+
).optional(),
|
|
877
|
+
dueDate: zod.z.string().describe("Due date/time").regex(
|
|
878
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
|
879
|
+
"Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
|
|
880
|
+
).optional(),
|
|
881
|
+
discussionToResolve: zod.z.string({
|
|
882
|
+
description: 'Id of a discussion to resolve. Use in combination with "merge_request_to_resolve_discussions_of"'
|
|
883
|
+
}).optional(),
|
|
884
|
+
epicId: zod.z.number({ description: "Id of the linked Epic" }).min(0, "Valid values should be equal or greater than zero").optional(),
|
|
885
|
+
labels: zod.z.string({ description: "Labels to apply" }).optional(),
|
|
886
|
+
issueType: zod.z.nativeEnum(IssueType, {
|
|
887
|
+
description: "Type of the issue"
|
|
888
|
+
}).optional(),
|
|
889
|
+
mergeRequestToResolveDiscussionsOf: zod.z.number({
|
|
890
|
+
description: "IID of a merge request in which to resolve all issues"
|
|
891
|
+
}).optional(),
|
|
892
|
+
milestoneId: zod.z.number({ description: "Global ID of a milestone to assign the issue" }).optional(),
|
|
893
|
+
weight: zod.z.number({ description: "The issue weight" }).min(0).refine((value) => {
|
|
894
|
+
const isValid = value >= 0;
|
|
895
|
+
if (!isValid) {
|
|
896
|
+
return {
|
|
897
|
+
message: "Valid values should be equal or greater than zero"
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
return isValid;
|
|
901
|
+
}).optional()
|
|
902
|
+
});
|
|
903
|
+
const issueOutputProperties = zod.z.object({
|
|
904
|
+
issueUrl: zod.z.string({ description: "Issue Url" }),
|
|
905
|
+
issueId: zod.z.number({ description: "Issue Id" }),
|
|
906
|
+
issueIid: zod.z.number({ description: "Issue Iid" })
|
|
907
|
+
});
|
|
908
|
+
const createGitlabIssueAction = (options) => {
|
|
909
|
+
const { integrations } = options;
|
|
910
|
+
return pluginScaffolderNode.createTemplateAction({
|
|
911
|
+
id: "gitlab:issues:create",
|
|
912
|
+
description: "Creates a Gitlab issue.",
|
|
913
|
+
examples: examples$7,
|
|
914
|
+
schema: {
|
|
915
|
+
input: commonGitlabConfig.merge(issueInputProperties),
|
|
916
|
+
output: issueOutputProperties
|
|
917
|
+
},
|
|
918
|
+
async handler(ctx) {
|
|
919
|
+
try {
|
|
920
|
+
const {
|
|
921
|
+
repoUrl,
|
|
922
|
+
projectId,
|
|
923
|
+
title,
|
|
924
|
+
description = "",
|
|
925
|
+
confidential = false,
|
|
926
|
+
assignees = [],
|
|
927
|
+
createdAt = "",
|
|
928
|
+
dueDate,
|
|
929
|
+
discussionToResolve = "",
|
|
930
|
+
epicId,
|
|
931
|
+
labels = "",
|
|
932
|
+
issueType,
|
|
933
|
+
mergeRequestToResolveDiscussionsOf,
|
|
934
|
+
milestoneId,
|
|
935
|
+
weight,
|
|
936
|
+
token
|
|
937
|
+
} = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);
|
|
938
|
+
const { host } = parseRepoUrl(repoUrl, integrations);
|
|
939
|
+
const api = getClient({ host, integrations, token });
|
|
940
|
+
let isEpicScoped = false;
|
|
941
|
+
if (epicId) {
|
|
942
|
+
isEpicScoped = await checkEpicScope(api, projectId, epicId);
|
|
943
|
+
if (isEpicScoped) {
|
|
944
|
+
ctx.logger.info("Epic is within Project Scope");
|
|
945
|
+
} else {
|
|
946
|
+
ctx.logger.warn(
|
|
947
|
+
"Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
const mappedCreatedAt = convertDate(
|
|
952
|
+
String(createdAt),
|
|
953
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
954
|
+
);
|
|
955
|
+
const mappedDueDate = dueDate ? convertDate(String(dueDate), (/* @__PURE__ */ new Date()).toISOString()) : void 0;
|
|
956
|
+
const issueOptions = {
|
|
957
|
+
description,
|
|
958
|
+
assigneeIds: assignees,
|
|
959
|
+
confidential,
|
|
960
|
+
epicId: isEpicScoped ? epicId : void 0,
|
|
961
|
+
labels,
|
|
962
|
+
createdAt: mappedCreatedAt,
|
|
963
|
+
dueDate: mappedDueDate,
|
|
964
|
+
discussionToResolve,
|
|
965
|
+
issueType,
|
|
966
|
+
mergeRequestToResolveDiscussionsOf,
|
|
967
|
+
milestoneId,
|
|
968
|
+
weight
|
|
969
|
+
};
|
|
970
|
+
const response = await api.Issues.create(
|
|
971
|
+
projectId,
|
|
972
|
+
title,
|
|
973
|
+
issueOptions
|
|
540
974
|
);
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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
|
|
975
|
+
ctx.output("issueId", response.id);
|
|
976
|
+
ctx.output("issueUrl", response.web_url);
|
|
977
|
+
ctx.output("issueIid", response.iid);
|
|
978
|
+
} catch (error) {
|
|
979
|
+
if (error instanceof zod.z.ZodError) {
|
|
980
|
+
throw new errors.InputError(`Validation error: ${error.message}`, {
|
|
981
|
+
validationErrors: error.errors
|
|
982
|
+
});
|
|
561
983
|
}
|
|
562
|
-
|
|
563
|
-
if (!response.token) {
|
|
564
|
-
throw new Error("Could not create project access token");
|
|
984
|
+
throw new errors.InputError(`Failed to create GitLab issue: ${error.message}`);
|
|
565
985
|
}
|
|
566
|
-
ctx.output("access_token", response.token);
|
|
567
986
|
}
|
|
568
987
|
});
|
|
569
988
|
};
|
|
570
989
|
|
|
571
|
-
const examples$
|
|
990
|
+
const examples$6 = [
|
|
572
991
|
{
|
|
573
|
-
description: "
|
|
992
|
+
description: "Edit a GitLab issue with minimal options",
|
|
574
993
|
example: yaml__default.default.stringify({
|
|
575
994
|
steps: [
|
|
576
995
|
{
|
|
577
|
-
id: "
|
|
578
|
-
|
|
579
|
-
|
|
996
|
+
id: "gitlabIssue",
|
|
997
|
+
name: "EditIssues",
|
|
998
|
+
action: "gitlab:issue:edit",
|
|
580
999
|
input: {
|
|
581
|
-
|
|
582
|
-
projectId:
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
variableType: "env_var"
|
|
1000
|
+
...commonGitlabConfigExample,
|
|
1001
|
+
projectId: 12,
|
|
1002
|
+
title: "Modified Test Issue",
|
|
1003
|
+
description: "This is a modified description of the issue"
|
|
586
1004
|
}
|
|
587
1005
|
}
|
|
588
1006
|
]
|
|
589
1007
|
})
|
|
590
1008
|
},
|
|
591
1009
|
{
|
|
592
|
-
description: "
|
|
1010
|
+
description: "Edit a GitLab issue with assignees and date options",
|
|
593
1011
|
example: yaml__default.default.stringify({
|
|
594
1012
|
steps: [
|
|
595
1013
|
{
|
|
596
|
-
id: "
|
|
597
|
-
|
|
598
|
-
|
|
1014
|
+
id: "gitlabIssue",
|
|
1015
|
+
name: "EditIssues",
|
|
1016
|
+
action: "gitlab:issue:edit",
|
|
1017
|
+
input: {
|
|
1018
|
+
...commonGitlabConfigExample,
|
|
1019
|
+
projectId: 12,
|
|
1020
|
+
title: "Test Issue",
|
|
1021
|
+
assignees: [18],
|
|
1022
|
+
description: "This is the edited description of the issue",
|
|
1023
|
+
updatedAt: "2024-05-10 18:00:00.000",
|
|
1024
|
+
dueDate: "2024-09-28"
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
]
|
|
1028
|
+
})
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
description: "Create a GitLab Issue with several options",
|
|
1032
|
+
example: yaml__default.default.stringify({
|
|
1033
|
+
steps: [
|
|
1034
|
+
{
|
|
1035
|
+
id: "gitlabIssue",
|
|
1036
|
+
name: "EditIssues",
|
|
1037
|
+
action: "gitlab:issue:edit",
|
|
1038
|
+
input: {
|
|
1039
|
+
...commonGitlabConfigExample,
|
|
1040
|
+
projectId: 12,
|
|
1041
|
+
title: "Test Edit Issue",
|
|
1042
|
+
assignees: [18, 15],
|
|
1043
|
+
description: "This is the description of the issue",
|
|
1044
|
+
confidential: false,
|
|
1045
|
+
updatedAt: "2024-05-10 18:00:00.000",
|
|
1046
|
+
dueDate: "2024-09-28",
|
|
1047
|
+
discussionLocked: true,
|
|
1048
|
+
epicId: 1,
|
|
1049
|
+
labels: "phase1:label1,phase2:label2"
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
]
|
|
1053
|
+
})
|
|
1054
|
+
}
|
|
1055
|
+
];
|
|
1056
|
+
|
|
1057
|
+
const editIssueInputProperties = zod.z.object({
|
|
1058
|
+
projectId: zod.z.number().describe(
|
|
1059
|
+
"The global ID or URL-encoded path of the project owned by the authenticated user."
|
|
1060
|
+
),
|
|
1061
|
+
issueIid: zod.z.number().describe("The internal ID of a project's issue"),
|
|
1062
|
+
addLabels: zod.z.string({
|
|
1063
|
+
description: "Comma-separated label names to add to an issue. If a label does not already exist, this creates a new project label and assigns it to the issue."
|
|
1064
|
+
}).optional(),
|
|
1065
|
+
assignees: zod.z.array(zod.z.number(), {
|
|
1066
|
+
description: "IDs of the users to assign the issue to."
|
|
1067
|
+
}).optional(),
|
|
1068
|
+
confidential: zod.z.boolean({ description: "Updates an issue to be confidential." }).optional(),
|
|
1069
|
+
description: zod.z.string().describe("The description of an issue. Limited to 1,048,576 characters.").max(1048576).optional(),
|
|
1070
|
+
discussionLocked: zod.z.boolean({
|
|
1071
|
+
description: "Flag indicating if the issue\u2019s discussion is locked. If the discussion is locked only project members can add or edit comments."
|
|
1072
|
+
}).optional(),
|
|
1073
|
+
dueDate: zod.z.string().describe(
|
|
1074
|
+
"The due date. Date time string in the format YYYY-MM-DD, for example 2016-03-11."
|
|
1075
|
+
).regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid date format. Use YYYY-MM-DD").optional(),
|
|
1076
|
+
epicId: zod.z.number({
|
|
1077
|
+
description: "ID of the epic to add the issue to. Valid values are greater than or equal to 0."
|
|
1078
|
+
}).min(0, "Valid values should be equal or greater than zero").optional(),
|
|
1079
|
+
issueType: zod.z.nativeEnum(IssueType, {
|
|
1080
|
+
description: "Updates the type of issue. One of issue, incident, test_case or task."
|
|
1081
|
+
}).optional(),
|
|
1082
|
+
labels: zod.z.string({
|
|
1083
|
+
description: "Comma-separated label names for an issue. Set to an empty string to unassign all labels. If a label does not already exist, this creates a new project label and assigns it to the issue."
|
|
1084
|
+
}).optional(),
|
|
1085
|
+
milestoneId: zod.z.number({
|
|
1086
|
+
description: "The global ID of a milestone to assign the issue to. Set to 0 or provide an empty value to unassign a milestone"
|
|
1087
|
+
}).optional(),
|
|
1088
|
+
removeLabels: zod.z.string({
|
|
1089
|
+
description: "Comma-separated label names to remove from an issue."
|
|
1090
|
+
}).optional(),
|
|
1091
|
+
stateEvent: zod.z.nativeEnum(IssueStateEvent, {
|
|
1092
|
+
description: "The state event of an issue. To close the issue, use close, and to reopen it, use reopen."
|
|
1093
|
+
}).optional(),
|
|
1094
|
+
title: zod.z.string().describe("The title of an issue.").optional(),
|
|
1095
|
+
updatedAt: zod.z.string().describe(
|
|
1096
|
+
"When the issue was updated. Date time string, ISO 8601 formatted"
|
|
1097
|
+
).regex(
|
|
1098
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
|
1099
|
+
"Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ"
|
|
1100
|
+
).optional(),
|
|
1101
|
+
weight: zod.z.number({ description: "The issue weight" }).min(0, "Valid values should be equal or greater than zero").max(10, "Valid values should be equal or less than 10").optional()
|
|
1102
|
+
});
|
|
1103
|
+
const editIssueOutputProperties = zod.z.object({
|
|
1104
|
+
issueUrl: zod.z.string({ description: "Issue WebUrl" }),
|
|
1105
|
+
projectId: zod.z.number({
|
|
1106
|
+
description: "The project id the issue belongs to WebUrl"
|
|
1107
|
+
}),
|
|
1108
|
+
issueId: zod.z.number({ description: "The issues Id" }),
|
|
1109
|
+
issueIid: zod.z.number({
|
|
1110
|
+
description: "The issues internal ID of a project's issue"
|
|
1111
|
+
}),
|
|
1112
|
+
state: zod.z.string({ description: "The state event of an issue" }),
|
|
1113
|
+
title: zod.z.string({ description: "The title of an issue." }),
|
|
1114
|
+
updatedAt: zod.z.string({ description: "The last updated time of the issue." })
|
|
1115
|
+
});
|
|
1116
|
+
const editGitlabIssueAction = (options) => {
|
|
1117
|
+
const { integrations } = options;
|
|
1118
|
+
return pluginScaffolderNode.createTemplateAction({
|
|
1119
|
+
id: "gitlab:issue:edit",
|
|
1120
|
+
description: "Edit a Gitlab issue.",
|
|
1121
|
+
examples: examples$6,
|
|
1122
|
+
schema: {
|
|
1123
|
+
input: commonGitlabConfig.merge(editIssueInputProperties),
|
|
1124
|
+
output: editIssueOutputProperties
|
|
1125
|
+
},
|
|
1126
|
+
async handler(ctx) {
|
|
1127
|
+
try {
|
|
1128
|
+
const {
|
|
1129
|
+
repoUrl,
|
|
1130
|
+
projectId,
|
|
1131
|
+
title,
|
|
1132
|
+
addLabels,
|
|
1133
|
+
removeLabels,
|
|
1134
|
+
issueIid,
|
|
1135
|
+
description,
|
|
1136
|
+
confidential = false,
|
|
1137
|
+
assignees = [],
|
|
1138
|
+
updatedAt = "",
|
|
1139
|
+
dueDate,
|
|
1140
|
+
discussionLocked = false,
|
|
1141
|
+
epicId,
|
|
1142
|
+
labels,
|
|
1143
|
+
issueType,
|
|
1144
|
+
milestoneId,
|
|
1145
|
+
stateEvent,
|
|
1146
|
+
weight,
|
|
1147
|
+
token
|
|
1148
|
+
} = commonGitlabConfig.merge(editIssueInputProperties).parse(ctx.input);
|
|
1149
|
+
const { host } = parseRepoUrl(repoUrl, integrations);
|
|
1150
|
+
const api = getClient({ host, integrations, token });
|
|
1151
|
+
let isEpicScoped = false;
|
|
1152
|
+
if (epicId) {
|
|
1153
|
+
isEpicScoped = await checkEpicScope(api, projectId, epicId);
|
|
1154
|
+
if (isEpicScoped) {
|
|
1155
|
+
ctx.logger.info("Epic is within Project Scope");
|
|
1156
|
+
} else {
|
|
1157
|
+
ctx.logger.warn(
|
|
1158
|
+
"Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
const mappedUpdatedAt = convertDate(
|
|
1163
|
+
String(updatedAt),
|
|
1164
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
1165
|
+
);
|
|
1166
|
+
const editIssueOptions = {
|
|
1167
|
+
addLabels,
|
|
1168
|
+
assigneeIds: assignees,
|
|
1169
|
+
confidential,
|
|
1170
|
+
description,
|
|
1171
|
+
discussionLocked,
|
|
1172
|
+
dueDate,
|
|
1173
|
+
epicId: isEpicScoped ? epicId : void 0,
|
|
1174
|
+
issueType,
|
|
1175
|
+
labels,
|
|
1176
|
+
milestoneId,
|
|
1177
|
+
removeLabels,
|
|
1178
|
+
stateEvent,
|
|
1179
|
+
title,
|
|
1180
|
+
updatedAt: mappedUpdatedAt,
|
|
1181
|
+
weight
|
|
1182
|
+
};
|
|
1183
|
+
const response = await api.Issues.edit(
|
|
1184
|
+
projectId,
|
|
1185
|
+
issueIid,
|
|
1186
|
+
editIssueOptions
|
|
1187
|
+
);
|
|
1188
|
+
ctx.output("issueId", response.id);
|
|
1189
|
+
ctx.output("projectId", response.project_id);
|
|
1190
|
+
ctx.output("issueUrl", response.web_url);
|
|
1191
|
+
ctx.output("issueIid", response.iid);
|
|
1192
|
+
ctx.output("title", response.title);
|
|
1193
|
+
ctx.output("state", response.state);
|
|
1194
|
+
ctx.output("updatedAt", response.updated_at);
|
|
1195
|
+
} catch (error) {
|
|
1196
|
+
if (error instanceof zod.z.ZodError) {
|
|
1197
|
+
throw new errors.InputError(`Validation error: ${error.message}`, {
|
|
1198
|
+
validationErrors: error.errors
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
throw new errors.InputError(
|
|
1202
|
+
`Failed to edit/modify GitLab issue: ${error.message}`
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
function createGitlabApi(options) {
|
|
1210
|
+
const { integrations, token: providedToken, repoUrl } = options;
|
|
1211
|
+
const { host } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
|
|
1212
|
+
const integrationConfig = integrations.gitlab.byHost(host);
|
|
1213
|
+
if (!integrationConfig) {
|
|
1214
|
+
throw new errors.InputError(
|
|
1215
|
+
`No matching integration configuration for host ${host}, please check your integrations config`
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
if (!integrationConfig.config.token && !providedToken) {
|
|
1219
|
+
throw new errors.InputError(`No token available for host ${host}`);
|
|
1220
|
+
}
|
|
1221
|
+
const token = providedToken ?? integrationConfig.config.token;
|
|
1222
|
+
const tokenType = providedToken ? "oauthToken" : "token";
|
|
1223
|
+
return new node.Gitlab({
|
|
1224
|
+
host: integrationConfig.config.baseUrl,
|
|
1225
|
+
[tokenType]: token
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
const examples$5 = [
|
|
1230
|
+
{
|
|
1231
|
+
description: "Create a merge request with a specific assignee",
|
|
1232
|
+
example: yaml__default.default.stringify({
|
|
1233
|
+
steps: [
|
|
1234
|
+
{
|
|
1235
|
+
id: "createMergeRequest",
|
|
1236
|
+
action: "publish:gitlab:merge-request",
|
|
1237
|
+
name: "Create a Merge Request",
|
|
599
1238
|
input: {
|
|
600
1239
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
1240
|
+
title: "Create my new MR",
|
|
1241
|
+
description: "This MR is really good",
|
|
1242
|
+
sourcePath: "./path/to/my/changes",
|
|
1243
|
+
branchName: "new-mr",
|
|
1244
|
+
assignee: "my-assignee"
|
|
605
1245
|
}
|
|
606
1246
|
}
|
|
607
1247
|
]
|
|
608
1248
|
})
|
|
609
1249
|
},
|
|
610
1250
|
{
|
|
611
|
-
description: "Create a
|
|
1251
|
+
description: "Create a merge request with removal of source branch after merge",
|
|
612
1252
|
example: yaml__default.default.stringify({
|
|
613
1253
|
steps: [
|
|
614
1254
|
{
|
|
615
|
-
id: "
|
|
616
|
-
action: "gitlab:
|
|
617
|
-
name: "Create
|
|
1255
|
+
id: "createMergeRequest",
|
|
1256
|
+
action: "publish:gitlab:merge-request",
|
|
1257
|
+
name: "Create a Merge Request",
|
|
618
1258
|
input: {
|
|
619
1259
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
1260
|
+
title: "Create my new MR",
|
|
1261
|
+
description: "This MR is really good",
|
|
1262
|
+
sourcePath: "./path/to/my/changes",
|
|
1263
|
+
branchName: "new-mr",
|
|
1264
|
+
removeSourceBranch: true
|
|
625
1265
|
}
|
|
626
1266
|
}
|
|
627
1267
|
]
|
|
628
1268
|
})
|
|
629
1269
|
},
|
|
630
1270
|
{
|
|
631
|
-
description: "Create a
|
|
1271
|
+
description: "Create a merge request with a target branch",
|
|
632
1272
|
example: yaml__default.default.stringify({
|
|
633
1273
|
steps: [
|
|
634
1274
|
{
|
|
635
|
-
id: "
|
|
636
|
-
action: "gitlab:
|
|
637
|
-
name: "Create
|
|
1275
|
+
id: "createMergeRequest",
|
|
1276
|
+
action: "publish:gitlab:merge-request",
|
|
1277
|
+
name: "Create a Merge Request",
|
|
638
1278
|
input: {
|
|
639
1279
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
1280
|
+
title: "Create my new MR",
|
|
1281
|
+
description: "This MR is really good",
|
|
1282
|
+
sourcePath: "./path/to/my/changes",
|
|
1283
|
+
branchName: "new-mr",
|
|
1284
|
+
targetBranchName: "test",
|
|
1285
|
+
targetPath: "Subdirectory"
|
|
645
1286
|
}
|
|
646
1287
|
}
|
|
647
1288
|
]
|
|
648
1289
|
})
|
|
649
1290
|
},
|
|
650
1291
|
{
|
|
651
|
-
description: "Create a
|
|
1292
|
+
description: "Create a merge request with a commit action as create",
|
|
652
1293
|
example: yaml__default.default.stringify({
|
|
653
1294
|
steps: [
|
|
654
1295
|
{
|
|
655
|
-
id: "
|
|
656
|
-
action: "gitlab:
|
|
657
|
-
name: "Create
|
|
1296
|
+
id: "createMergeRequest",
|
|
1297
|
+
action: "publish:gitlab:merge-request",
|
|
1298
|
+
name: "Create a Merge Request",
|
|
658
1299
|
input: {
|
|
659
1300
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1301
|
+
title: "Create my new MR",
|
|
1302
|
+
branchName: "new-mr",
|
|
1303
|
+
description: "MR description",
|
|
1304
|
+
commitAction: "create",
|
|
1305
|
+
targetPath: "source"
|
|
665
1306
|
}
|
|
666
1307
|
}
|
|
667
1308
|
]
|
|
668
1309
|
})
|
|
669
1310
|
},
|
|
670
1311
|
{
|
|
671
|
-
description: "Create a
|
|
1312
|
+
description: "Create a merge request with a commit action as delete",
|
|
672
1313
|
example: yaml__default.default.stringify({
|
|
673
1314
|
steps: [
|
|
674
1315
|
{
|
|
675
|
-
id: "
|
|
676
|
-
action: "gitlab:
|
|
677
|
-
name: "Create
|
|
1316
|
+
id: "createMergeRequest",
|
|
1317
|
+
action: "publish:gitlab:merge-request",
|
|
1318
|
+
name: "Create a Merge Request",
|
|
678
1319
|
input: {
|
|
679
1320
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
1321
|
+
title: "Create my new MR",
|
|
1322
|
+
branchName: "new-mr",
|
|
1323
|
+
description: "MR description",
|
|
1324
|
+
commitAction: "delete",
|
|
1325
|
+
targetPath: "source"
|
|
685
1326
|
}
|
|
686
1327
|
}
|
|
687
1328
|
]
|
|
688
1329
|
})
|
|
689
1330
|
},
|
|
690
1331
|
{
|
|
691
|
-
description: "Create a
|
|
1332
|
+
description: "Create a merge request with a commit action as update",
|
|
692
1333
|
example: yaml__default.default.stringify({
|
|
693
1334
|
steps: [
|
|
694
1335
|
{
|
|
695
|
-
id: "
|
|
696
|
-
action: "gitlab:
|
|
697
|
-
name: "Create
|
|
1336
|
+
id: "createMergeRequest",
|
|
1337
|
+
action: "publish:gitlab:merge-request",
|
|
1338
|
+
name: "Create a Merge Request",
|
|
698
1339
|
input: {
|
|
699
1340
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
1341
|
+
title: "Create my new MR",
|
|
1342
|
+
branchName: "new-mr",
|
|
1343
|
+
description: "MR description",
|
|
1344
|
+
commitAction: "update",
|
|
1345
|
+
targetPath: "source"
|
|
705
1346
|
}
|
|
706
1347
|
}
|
|
707
1348
|
]
|
|
@@ -709,120 +1350,212 @@ const examples$4 = [
|
|
|
709
1350
|
}
|
|
710
1351
|
];
|
|
711
1352
|
|
|
712
|
-
const
|
|
1353
|
+
const createPublishGitlabMergeRequestAction = (options) => {
|
|
713
1354
|
const { integrations } = options;
|
|
714
1355
|
return pluginScaffolderNode.createTemplateAction({
|
|
715
|
-
id: "gitlab:
|
|
716
|
-
examples: examples$
|
|
1356
|
+
id: "publish:gitlab:merge-request",
|
|
1357
|
+
examples: examples$5,
|
|
717
1358
|
schema: {
|
|
718
|
-
input:
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
1359
|
+
input: {
|
|
1360
|
+
required: ["repoUrl", "branchName"],
|
|
1361
|
+
type: "object",
|
|
1362
|
+
properties: {
|
|
1363
|
+
repoUrl: {
|
|
1364
|
+
type: "string",
|
|
1365
|
+
title: "Repository Location",
|
|
1366
|
+
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`
|
|
1367
|
+
},
|
|
1368
|
+
/** @deprecated projectID is passed as query parameters in the repoUrl */
|
|
1369
|
+
projectid: {
|
|
1370
|
+
type: "string",
|
|
1371
|
+
title: "projectid",
|
|
1372
|
+
description: "Project ID/Name(slug) of the Gitlab Project"
|
|
1373
|
+
},
|
|
1374
|
+
title: {
|
|
1375
|
+
type: "string",
|
|
1376
|
+
title: "Merge Request Name",
|
|
1377
|
+
description: "The name for the merge request"
|
|
1378
|
+
},
|
|
1379
|
+
description: {
|
|
1380
|
+
type: "string",
|
|
1381
|
+
title: "Merge Request Description",
|
|
1382
|
+
description: "The description of the merge request"
|
|
1383
|
+
},
|
|
1384
|
+
branchName: {
|
|
1385
|
+
type: "string",
|
|
1386
|
+
title: "Source Branch Name",
|
|
1387
|
+
description: "The source branch name of the merge request"
|
|
1388
|
+
},
|
|
1389
|
+
targetBranchName: {
|
|
1390
|
+
type: "string",
|
|
1391
|
+
title: "Target Branch Name",
|
|
1392
|
+
description: "The target branch name of the merge request"
|
|
1393
|
+
},
|
|
1394
|
+
sourcePath: {
|
|
1395
|
+
type: "string",
|
|
1396
|
+
title: "Working Subdirectory",
|
|
1397
|
+
description: "Subdirectory of working directory to copy changes from"
|
|
1398
|
+
},
|
|
1399
|
+
targetPath: {
|
|
1400
|
+
type: "string",
|
|
1401
|
+
title: "Repository Subdirectory",
|
|
1402
|
+
description: "Subdirectory of repository to apply changes to"
|
|
1403
|
+
},
|
|
1404
|
+
token: {
|
|
1405
|
+
title: "Authentication Token",
|
|
1406
|
+
type: "string",
|
|
1407
|
+
description: "The token to use for authorization to GitLab"
|
|
1408
|
+
},
|
|
1409
|
+
commitAction: {
|
|
1410
|
+
title: "Commit action",
|
|
1411
|
+
type: "string",
|
|
1412
|
+
enum: ["create", "update", "delete"],
|
|
1413
|
+
description: "The action to be used for git commit. Defaults to create."
|
|
1414
|
+
},
|
|
1415
|
+
removeSourceBranch: {
|
|
1416
|
+
title: "Delete source branch",
|
|
1417
|
+
type: "boolean",
|
|
1418
|
+
description: "Option to delete source branch once the MR has been merged. Default: false"
|
|
1419
|
+
},
|
|
1420
|
+
assignee: {
|
|
1421
|
+
title: "Merge Request Assignee",
|
|
1422
|
+
type: "string",
|
|
1423
|
+
description: "User this merge request will be assigned to"
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
},
|
|
1427
|
+
output: {
|
|
1428
|
+
type: "object",
|
|
1429
|
+
properties: {
|
|
1430
|
+
targetBranchName: {
|
|
1431
|
+
title: "Target branch name of the merge request",
|
|
1432
|
+
type: "string"
|
|
1433
|
+
},
|
|
1434
|
+
projectid: {
|
|
1435
|
+
title: "Gitlab Project id/Name(slug)",
|
|
1436
|
+
type: "string"
|
|
1437
|
+
},
|
|
1438
|
+
projectPath: {
|
|
1439
|
+
title: "Gitlab Project path",
|
|
1440
|
+
type: "string"
|
|
1441
|
+
},
|
|
1442
|
+
mergeRequestUrl: {
|
|
1443
|
+
title: "MergeRequest(MR) URL",
|
|
1444
|
+
type: "string",
|
|
1445
|
+
description: "Link to the merge request in GitLab"
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
736
1449
|
},
|
|
737
1450
|
async handler(ctx) {
|
|
738
1451
|
const {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
const { token, integrationConfig } = getToken(ctx.input, integrations);
|
|
749
|
-
const api = new node.Gitlab({
|
|
750
|
-
host: integrationConfig.config.baseUrl,
|
|
1452
|
+
assignee,
|
|
1453
|
+
branchName,
|
|
1454
|
+
targetBranchName,
|
|
1455
|
+
description,
|
|
1456
|
+
repoUrl,
|
|
1457
|
+
removeSourceBranch,
|
|
1458
|
+
targetPath,
|
|
1459
|
+
sourcePath,
|
|
1460
|
+
title,
|
|
751
1461
|
token
|
|
1462
|
+
} = ctx.input;
|
|
1463
|
+
const { owner, repo, project } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
|
|
1464
|
+
const repoID = project ? project : `${owner}/${repo}`;
|
|
1465
|
+
const api = createGitlabApi({
|
|
1466
|
+
integrations,
|
|
1467
|
+
token,
|
|
1468
|
+
repoUrl
|
|
752
1469
|
});
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1470
|
+
let assigneeId = void 0;
|
|
1471
|
+
if (assignee !== void 0) {
|
|
1472
|
+
try {
|
|
1473
|
+
const assigneeUser = await api.Users.username(assignee);
|
|
1474
|
+
assigneeId = assigneeUser[0].id;
|
|
1475
|
+
} catch (e) {
|
|
1476
|
+
ctx.logger.warn(
|
|
1477
|
+
`Failed to find gitlab user id for ${assignee}: ${e}. Proceeding with MR creation without an assignee.`
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
let fileRoot;
|
|
1482
|
+
if (sourcePath) {
|
|
1483
|
+
fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, sourcePath);
|
|
1484
|
+
} else if (targetPath) {
|
|
1485
|
+
fileRoot = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
|
|
1486
|
+
} else {
|
|
1487
|
+
fileRoot = ctx.workspacePath;
|
|
1488
|
+
}
|
|
1489
|
+
const fileContents = await pluginScaffolderNode.serializeDirectoryContents(fileRoot, {
|
|
1490
|
+
gitignore: true
|
|
761
1491
|
});
|
|
1492
|
+
const actions = fileContents.map((file) => ({
|
|
1493
|
+
action: ctx.input.commitAction ?? "create",
|
|
1494
|
+
filePath: targetPath ? path__default.default.posix.join(targetPath, file.path) : file.path,
|
|
1495
|
+
encoding: "base64",
|
|
1496
|
+
content: file.content.toString("base64"),
|
|
1497
|
+
execute_filemode: file.executable
|
|
1498
|
+
}));
|
|
1499
|
+
let targetBranch = targetBranchName;
|
|
1500
|
+
if (!targetBranch) {
|
|
1501
|
+
const projects = await api.Projects.show(repoID);
|
|
1502
|
+
const { default_branch: defaultBranch } = projects;
|
|
1503
|
+
targetBranch = defaultBranch;
|
|
1504
|
+
}
|
|
1505
|
+
try {
|
|
1506
|
+
await api.Branches.create(repoID, branchName, String(targetBranch));
|
|
1507
|
+
} catch (e) {
|
|
1508
|
+
throw new errors.InputError(
|
|
1509
|
+
`The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${e}`
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
try {
|
|
1513
|
+
await api.Commits.create(repoID, branchName, ctx.input.title, actions);
|
|
1514
|
+
} catch (e) {
|
|
1515
|
+
throw new errors.InputError(
|
|
1516
|
+
`Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${e}`
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1519
|
+
try {
|
|
1520
|
+
const mergeRequestUrl = await api.MergeRequests.create(
|
|
1521
|
+
repoID,
|
|
1522
|
+
branchName,
|
|
1523
|
+
String(targetBranch),
|
|
1524
|
+
title,
|
|
1525
|
+
{
|
|
1526
|
+
description,
|
|
1527
|
+
removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
|
|
1528
|
+
assigneeId
|
|
1529
|
+
}
|
|
1530
|
+
).then((mergeRequest) => {
|
|
1531
|
+
return mergeRequest.web_url;
|
|
1532
|
+
});
|
|
1533
|
+
ctx.output("projectid", repoID);
|
|
1534
|
+
ctx.output("targetBranchName", targetBranch);
|
|
1535
|
+
ctx.output("projectPath", repoID);
|
|
1536
|
+
ctx.output("mergeRequestUrl", mergeRequestUrl);
|
|
1537
|
+
} catch (e) {
|
|
1538
|
+
throw new errors.InputError(`Merge request creation failed${e}`);
|
|
1539
|
+
}
|
|
762
1540
|
}
|
|
763
1541
|
});
|
|
764
1542
|
};
|
|
765
1543
|
|
|
766
|
-
const examples$
|
|
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
|
-
}
|
|
781
|
-
}
|
|
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"
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
]
|
|
804
|
-
})
|
|
805
|
-
},
|
|
1544
|
+
const examples$4 = [
|
|
806
1545
|
{
|
|
807
|
-
description: "
|
|
1546
|
+
description: "Trigger a GitLab Project Pipeline",
|
|
808
1547
|
example: yaml__default.default.stringify({
|
|
809
1548
|
steps: [
|
|
810
1549
|
{
|
|
811
|
-
id: "
|
|
812
|
-
name: "
|
|
813
|
-
action: "gitlab:
|
|
1550
|
+
id: "triggerPipeline",
|
|
1551
|
+
name: "Trigger Project Pipeline",
|
|
1552
|
+
action: "gitlab:pipeline:trigger",
|
|
814
1553
|
input: {
|
|
815
1554
|
...commonGitlabConfigExample,
|
|
816
1555
|
projectId: 12,
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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"
|
|
1556
|
+
tokenDescription: "This is the text that will appear in the pipeline token",
|
|
1557
|
+
token: "glpt-xxxxxxxxxxxx",
|
|
1558
|
+
branch: "main"
|
|
826
1559
|
}
|
|
827
1560
|
}
|
|
828
1561
|
]
|
|
@@ -830,788 +1563,509 @@ const examples$3 = [
|
|
|
830
1563
|
}
|
|
831
1564
|
];
|
|
832
1565
|
|
|
833
|
-
|
|
834
|
-
IssueType2["ISSUE"] = "issue";
|
|
835
|
-
IssueType2["INCIDENT"] = "incident";
|
|
836
|
-
IssueType2["TEST"] = "test_case";
|
|
837
|
-
return IssueType2;
|
|
838
|
-
})(IssueType || {});
|
|
839
|
-
const issueInputProperties = zod.z.object({
|
|
1566
|
+
const pipelineInputProperties = zod.z.object({
|
|
840
1567
|
projectId: zod.z.number().describe("Project Id"),
|
|
841
|
-
|
|
842
|
-
|
|
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()
|
|
1568
|
+
tokenDescription: zod.z.string().describe("Pipeline token description"),
|
|
1569
|
+
branch: zod.z.string().describe("Project branch")
|
|
876
1570
|
});
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
issueId: zod.z.number({ description: "Issue Id" }),
|
|
880
|
-
issueIid: zod.z.number({ description: "Issue Iid" })
|
|
1571
|
+
const pipelineOutputProperties = zod.z.object({
|
|
1572
|
+
pipelineUrl: zod.z.string({ description: "Pipeline Url" })
|
|
881
1573
|
});
|
|
882
|
-
const
|
|
1574
|
+
const createTriggerGitlabPipelineAction = (options) => {
|
|
883
1575
|
const { integrations } = options;
|
|
884
1576
|
return pluginScaffolderNode.createTemplateAction({
|
|
885
|
-
id: "gitlab:
|
|
886
|
-
description: "
|
|
887
|
-
examples: examples$
|
|
1577
|
+
id: "gitlab:pipeline:trigger",
|
|
1578
|
+
description: "Triggers a GitLab Pipeline.",
|
|
1579
|
+
examples: examples$4,
|
|
888
1580
|
schema: {
|
|
889
|
-
input: commonGitlabConfig.merge(
|
|
890
|
-
output:
|
|
1581
|
+
input: commonGitlabConfig.merge(pipelineInputProperties),
|
|
1582
|
+
output: pipelineOutputProperties
|
|
891
1583
|
},
|
|
892
1584
|
async handler(ctx) {
|
|
1585
|
+
let pipelineTokenResponse = null;
|
|
1586
|
+
const { repoUrl, projectId, tokenDescription, token, branch } = commonGitlabConfig.merge(pipelineInputProperties).parse(ctx.input);
|
|
1587
|
+
const { host } = parseRepoUrl(repoUrl, integrations);
|
|
1588
|
+
const api = getClient({ host, integrations, token });
|
|
893
1589
|
try {
|
|
894
|
-
|
|
895
|
-
repoUrl,
|
|
1590
|
+
pipelineTokenResponse = await api.PipelineTriggerTokens.create(
|
|
896
1591
|
projectId,
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
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
|
-
}
|
|
1592
|
+
tokenDescription
|
|
1593
|
+
);
|
|
1594
|
+
if (!pipelineTokenResponse.token) {
|
|
1595
|
+
ctx.logger.error("Failed to create pipeline token.");
|
|
1596
|
+
return;
|
|
928
1597
|
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
(/* @__PURE__ */ new Date()).toISOString()
|
|
1598
|
+
ctx.logger.info(
|
|
1599
|
+
`Pipeline token id ${pipelineTokenResponse.id} created.`
|
|
932
1600
|
);
|
|
933
|
-
const
|
|
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(
|
|
1601
|
+
const pipelineTriggerResponse = await api.PipelineTriggerTokens.trigger(
|
|
949
1602
|
projectId,
|
|
950
|
-
|
|
951
|
-
|
|
1603
|
+
branch,
|
|
1604
|
+
pipelineTokenResponse.token
|
|
952
1605
|
);
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1606
|
+
if (!pipelineTriggerResponse.id) {
|
|
1607
|
+
ctx.logger.error("Failed to trigger pipeline.");
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
ctx.logger.info(`Pipeline id ${pipelineTriggerResponse.id} triggered.`);
|
|
1611
|
+
ctx.output("pipelineUrl", pipelineTriggerResponse.web_url);
|
|
956
1612
|
} catch (error) {
|
|
957
1613
|
if (error instanceof zod.z.ZodError) {
|
|
958
1614
|
throw new errors.InputError(`Validation error: ${error.message}`, {
|
|
959
1615
|
validationErrors: error.errors
|
|
960
1616
|
});
|
|
961
1617
|
}
|
|
962
|
-
throw new errors.InputError(`Failed to
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
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
|
-
}
|
|
1618
|
+
throw new errors.InputError(`Failed to trigger Pipeline: ${error.message}`);
|
|
1619
|
+
} finally {
|
|
1620
|
+
if (pipelineTokenResponse && pipelineTokenResponse.id) {
|
|
1621
|
+
try {
|
|
1622
|
+
await api.PipelineTriggerTokens.remove(
|
|
1623
|
+
projectId,
|
|
1624
|
+
pipelineTokenResponse.id
|
|
1625
|
+
);
|
|
1626
|
+
ctx.logger.info(
|
|
1627
|
+
`Deleted pipeline token ${pipelineTokenResponse.id}.`
|
|
1628
|
+
);
|
|
1629
|
+
} catch (error) {
|
|
1630
|
+
ctx.logger.error(
|
|
1631
|
+
`Failed to delete pipeline token id ${pipelineTokenResponse.id}.`
|
|
1632
|
+
);
|
|
1050
1633
|
}
|
|
1051
1634
|
}
|
|
1052
|
-
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
};
|
|
1639
|
+
|
|
1640
|
+
const examples$3 = [
|
|
1055
1641
|
{
|
|
1056
|
-
description: "
|
|
1642
|
+
description: "Create a GitLab project access token with minimal options.",
|
|
1057
1643
|
example: yaml__default.default.stringify({
|
|
1058
1644
|
steps: [
|
|
1059
1645
|
{
|
|
1060
|
-
id: "
|
|
1061
|
-
action: "
|
|
1062
|
-
name: "
|
|
1646
|
+
id: "createAccessToken",
|
|
1647
|
+
action: "gitlab:projectAccessToken:create",
|
|
1648
|
+
name: "Create GitLab Project Access Token",
|
|
1063
1649
|
input: {
|
|
1064
|
-
repoUrl: "gitlab.com?repo=
|
|
1065
|
-
|
|
1066
|
-
{
|
|
1067
|
-
name: "dev",
|
|
1068
|
-
create: true,
|
|
1069
|
-
protected: true,
|
|
1070
|
-
ref: "master"
|
|
1071
|
-
},
|
|
1072
|
-
{
|
|
1073
|
-
name: "master",
|
|
1074
|
-
protected: true
|
|
1075
|
-
}
|
|
1076
|
-
]
|
|
1650
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1651
|
+
projectId: "456"
|
|
1077
1652
|
}
|
|
1078
1653
|
}
|
|
1079
1654
|
]
|
|
1080
1655
|
})
|
|
1081
1656
|
},
|
|
1082
|
-
{
|
|
1083
|
-
description: "
|
|
1084
|
-
example: yaml__default.default.stringify({
|
|
1085
|
-
steps: [
|
|
1086
|
-
{
|
|
1087
|
-
id: "
|
|
1088
|
-
action: "
|
|
1089
|
-
name: "
|
|
1090
|
-
input: {
|
|
1091
|
-
repoUrl: "gitlab.com?repo=
|
|
1092
|
-
|
|
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
|
-
}
|
|
1657
|
+
{
|
|
1658
|
+
description: "Create a GitLab project access token with custom scopes.",
|
|
1659
|
+
example: yaml__default.default.stringify({
|
|
1660
|
+
steps: [
|
|
1661
|
+
{
|
|
1662
|
+
id: "createAccessToken",
|
|
1663
|
+
action: "gitlab:projectAccessToken:create",
|
|
1664
|
+
name: "Create GitLab Project Access Token",
|
|
1665
|
+
input: {
|
|
1666
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1667
|
+
projectId: "789",
|
|
1668
|
+
scopes: ["read_registry", "write_repository"]
|
|
1306
1669
|
}
|
|
1307
1670
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
},
|
|
1324
|
-
commitHash: {
|
|
1325
|
-
title: "The git commit hash of the initial commit",
|
|
1326
|
-
type: "string"
|
|
1671
|
+
]
|
|
1672
|
+
})
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
description: "Create a GitLab project access token with a specified name.",
|
|
1676
|
+
example: yaml__default.default.stringify({
|
|
1677
|
+
steps: [
|
|
1678
|
+
{
|
|
1679
|
+
id: "createAccessToken",
|
|
1680
|
+
action: "gitlab:projectAccessToken:create",
|
|
1681
|
+
name: "Create GitLab Project Access Token",
|
|
1682
|
+
input: {
|
|
1683
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1684
|
+
projectId: "101112",
|
|
1685
|
+
name: "my-custom-token"
|
|
1327
1686
|
}
|
|
1328
1687
|
}
|
|
1329
|
-
|
|
1688
|
+
]
|
|
1689
|
+
})
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
description: "Create a GitLab project access token with a numeric project ID.",
|
|
1693
|
+
example: yaml__default.default.stringify({
|
|
1694
|
+
steps: [
|
|
1695
|
+
{
|
|
1696
|
+
id: "createAccessToken",
|
|
1697
|
+
action: "gitlab:projectAccessToken:create",
|
|
1698
|
+
name: "Create GitLab Project Access Token",
|
|
1699
|
+
input: {
|
|
1700
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1701
|
+
projectId: 42
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
]
|
|
1705
|
+
})
|
|
1706
|
+
},
|
|
1707
|
+
{
|
|
1708
|
+
description: "Create a GitLab project access token with a specified expired Date.",
|
|
1709
|
+
example: yaml__default.default.stringify({
|
|
1710
|
+
steps: [
|
|
1711
|
+
{
|
|
1712
|
+
id: "createAccessToken",
|
|
1713
|
+
action: "gitlab:projectAccessToken:create",
|
|
1714
|
+
name: "Create GitLab Project Access Token",
|
|
1715
|
+
input: {
|
|
1716
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1717
|
+
projectId: "123",
|
|
1718
|
+
expiresAt: "2024-06-25"
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
]
|
|
1722
|
+
})
|
|
1723
|
+
}
|
|
1724
|
+
];
|
|
1725
|
+
|
|
1726
|
+
const createGitlabProjectAccessTokenAction = (options) => {
|
|
1727
|
+
const { integrations } = options;
|
|
1728
|
+
return pluginScaffolderNode.createTemplateAction({
|
|
1729
|
+
id: "gitlab:projectAccessToken:create",
|
|
1730
|
+
examples: examples$3,
|
|
1731
|
+
schema: {
|
|
1732
|
+
input: zod.z.object({
|
|
1733
|
+
projectId: zod.z.union([zod.z.number(), zod.z.string()], {
|
|
1734
|
+
description: "Project ID/Name(slug) of the Gitlab Project"
|
|
1735
|
+
}),
|
|
1736
|
+
token: zod.z.string({
|
|
1737
|
+
description: "The token to use for authorization to GitLab"
|
|
1738
|
+
}).optional(),
|
|
1739
|
+
name: zod.z.string({ description: "Name of Access Key" }).optional(),
|
|
1740
|
+
repoUrl: zod.z.string({ description: "URL to gitlab instance" }),
|
|
1741
|
+
accessLevel: zod.z.number({
|
|
1742
|
+
description: "Access Level of the Token, 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), and 50 (Owner)"
|
|
1743
|
+
}).optional(),
|
|
1744
|
+
scopes: zod.z.string({
|
|
1745
|
+
description: "Scopes for a project access token"
|
|
1746
|
+
}).array().optional(),
|
|
1747
|
+
expiresAt: zod.z.string({
|
|
1748
|
+
description: "Expiration date of the access token in ISO format (YYYY-MM-DD). If Empty, it will set to the maximum of 365 days."
|
|
1749
|
+
}).optional()
|
|
1750
|
+
}),
|
|
1751
|
+
output: zod.z.object({
|
|
1752
|
+
access_token: zod.z.string({ description: "Access Token" })
|
|
1753
|
+
})
|
|
1330
1754
|
},
|
|
1331
1755
|
async handler(ctx) {
|
|
1756
|
+
ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
|
|
1332
1757
|
const {
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
gitAuthorEmail,
|
|
1339
|
-
setUserAsOwner = false,
|
|
1340
|
-
topics = [],
|
|
1341
|
-
settings = {},
|
|
1342
|
-
branches = [],
|
|
1343
|
-
projectVariables = []
|
|
1758
|
+
projectId,
|
|
1759
|
+
name = "tokenname",
|
|
1760
|
+
accessLevel = 40,
|
|
1761
|
+
scopes = ["read_repository"],
|
|
1762
|
+
expiresAt
|
|
1344
1763
|
} = ctx.input;
|
|
1345
|
-
const {
|
|
1346
|
-
if (!
|
|
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) {
|
|
1764
|
+
const { token, integrationConfig } = getToken(ctx.input, integrations);
|
|
1765
|
+
if (!integrationConfig.config.token && token) {
|
|
1353
1766
|
throw new errors.InputError(
|
|
1354
|
-
`No
|
|
1767
|
+
`No token available for host ${integrationConfig.config.baseUrl}`
|
|
1355
1768
|
);
|
|
1356
1769
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
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({
|
|
1770
|
+
let api;
|
|
1771
|
+
if (!ctx.input.token) {
|
|
1772
|
+
api = new rest.Gitlab({
|
|
1391
1773
|
host: integrationConfig.config.baseUrl,
|
|
1392
|
-
token
|
|
1774
|
+
token
|
|
1775
|
+
});
|
|
1776
|
+
} else {
|
|
1777
|
+
api = new rest.Gitlab({
|
|
1778
|
+
host: integrationConfig.config.baseUrl,
|
|
1779
|
+
oauthToken: token
|
|
1393
1780
|
});
|
|
1394
|
-
await adminClient.ProjectMembers.add(projectId, userId, 50);
|
|
1395
1781
|
}
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1782
|
+
const response = await api.ProjectAccessTokens.create(
|
|
1783
|
+
projectId,
|
|
1784
|
+
name,
|
|
1785
|
+
scopes,
|
|
1786
|
+
{
|
|
1787
|
+
expiresAt: expiresAt || luxon.DateTime.now().plus({ days: 365 }).toISODate(),
|
|
1788
|
+
accessLevel
|
|
1789
|
+
}
|
|
1790
|
+
);
|
|
1791
|
+
if (!response.token) {
|
|
1792
|
+
throw new Error("Could not create project access token");
|
|
1793
|
+
}
|
|
1794
|
+
ctx.output("access_token", response.token);
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
};
|
|
1798
|
+
|
|
1799
|
+
const examples$2 = [
|
|
1800
|
+
{
|
|
1801
|
+
description: "Create a GitLab project deploy token with minimal options.",
|
|
1802
|
+
example: yaml__default.default.stringify({
|
|
1803
|
+
steps: [
|
|
1804
|
+
{
|
|
1805
|
+
id: "createDeployToken",
|
|
1806
|
+
action: "gitlab:projectDeployToken:create",
|
|
1807
|
+
name: "Create GitLab Project Deploy Token",
|
|
1808
|
+
input: {
|
|
1809
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1810
|
+
projectId: "456",
|
|
1811
|
+
name: "tokenname"
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
]
|
|
1815
|
+
})
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
description: "Create a GitLab project deploy token with custom scopes.",
|
|
1819
|
+
example: yaml__default.default.stringify({
|
|
1820
|
+
steps: [
|
|
1821
|
+
{
|
|
1822
|
+
id: "createDeployToken",
|
|
1823
|
+
action: "gitlab:projectDeployToken:create",
|
|
1824
|
+
name: "Create GitLab Project Deploy Token",
|
|
1825
|
+
input: {
|
|
1826
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1827
|
+
projectId: "789",
|
|
1828
|
+
name: "tokenname",
|
|
1829
|
+
scopes: ["read_registry", "write_repository"]
|
|
1433
1830
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1831
|
+
}
|
|
1832
|
+
]
|
|
1833
|
+
})
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
description: "Create a GitLab project deploy token with a specified name.",
|
|
1837
|
+
example: yaml__default.default.stringify({
|
|
1838
|
+
steps: [
|
|
1839
|
+
{
|
|
1840
|
+
id: "createDeployToken",
|
|
1841
|
+
action: "gitlab:projectDeployToken:create",
|
|
1842
|
+
name: "Create GitLab Project Deploy Token",
|
|
1843
|
+
input: {
|
|
1844
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1845
|
+
projectId: "101112",
|
|
1846
|
+
name: "my-custom-token"
|
|
1443
1847
|
}
|
|
1444
1848
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1849
|
+
]
|
|
1850
|
+
})
|
|
1851
|
+
},
|
|
1852
|
+
{
|
|
1853
|
+
description: "Create a GitLab project deploy token with a numeric project ID.",
|
|
1854
|
+
example: yaml__default.default.stringify({
|
|
1855
|
+
steps: [
|
|
1856
|
+
{
|
|
1857
|
+
id: "createDeployToken",
|
|
1858
|
+
action: "gitlab:projectDeployToken:create",
|
|
1859
|
+
name: "Create GitLab Project Deploy Token",
|
|
1860
|
+
input: {
|
|
1861
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1862
|
+
projectId: 42,
|
|
1863
|
+
name: "tokenname"
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
]
|
|
1867
|
+
})
|
|
1868
|
+
},
|
|
1869
|
+
{
|
|
1870
|
+
description: "Create a GitLab project deploy token with a custom username",
|
|
1871
|
+
example: yaml__default.default.stringify({
|
|
1872
|
+
steps: [
|
|
1873
|
+
{
|
|
1874
|
+
id: "createDeployToken",
|
|
1875
|
+
action: "gitlab:projectDeployToken:create",
|
|
1876
|
+
name: "Create GitLab Project Deploy Token",
|
|
1877
|
+
input: {
|
|
1878
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1879
|
+
projectId: 42,
|
|
1880
|
+
name: "tokenname",
|
|
1881
|
+
username: "tokenuser"
|
|
1464
1882
|
}
|
|
1465
1883
|
}
|
|
1884
|
+
]
|
|
1885
|
+
})
|
|
1886
|
+
}
|
|
1887
|
+
];
|
|
1888
|
+
|
|
1889
|
+
const createGitlabProjectDeployTokenAction = (options) => {
|
|
1890
|
+
const { integrations } = options;
|
|
1891
|
+
return pluginScaffolderNode.createTemplateAction({
|
|
1892
|
+
id: "gitlab:projectDeployToken:create",
|
|
1893
|
+
examples: examples$2,
|
|
1894
|
+
schema: {
|
|
1895
|
+
input: commonGitlabConfig.merge(
|
|
1896
|
+
zod.z.object({
|
|
1897
|
+
projectId: zod.z.union([zod.z.number(), zod.z.string()], {
|
|
1898
|
+
description: "Project ID"
|
|
1899
|
+
}),
|
|
1900
|
+
name: zod.z.string({ description: "Deploy Token Name" }),
|
|
1901
|
+
username: zod.z.string({ description: "Deploy Token Username" }).optional(),
|
|
1902
|
+
scopes: zod.z.array(zod.z.string(), { description: "Scopes" }).optional()
|
|
1903
|
+
})
|
|
1904
|
+
),
|
|
1905
|
+
output: zod.z.object({
|
|
1906
|
+
deploy_token: zod.z.string({ description: "Deploy Token" }),
|
|
1907
|
+
user: zod.z.string({ description: "User" })
|
|
1908
|
+
})
|
|
1909
|
+
},
|
|
1910
|
+
async handler(ctx) {
|
|
1911
|
+
ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
|
|
1912
|
+
const { projectId, name, username, scopes } = ctx.input;
|
|
1913
|
+
const { token, integrationConfig } = getToken(ctx.input, integrations);
|
|
1914
|
+
const api = new node.Gitlab({
|
|
1915
|
+
host: integrationConfig.config.baseUrl,
|
|
1916
|
+
token
|
|
1917
|
+
});
|
|
1918
|
+
const deployToken = await api.ProjectDeployTokens.add(
|
|
1919
|
+
projectId,
|
|
1920
|
+
name,
|
|
1921
|
+
scopes,
|
|
1922
|
+
{
|
|
1923
|
+
username
|
|
1924
|
+
}
|
|
1925
|
+
);
|
|
1926
|
+
if (!deployToken.hasOwnProperty("token")) {
|
|
1927
|
+
throw new errors.InputError(`No deploy_token given from gitlab instance`);
|
|
1466
1928
|
}
|
|
1467
|
-
ctx.output("
|
|
1468
|
-
ctx.output("
|
|
1469
|
-
ctx.output("repoContentsUrl", repoContentsUrl);
|
|
1470
|
-
ctx.output("projectId", projectId);
|
|
1929
|
+
ctx.output("deploy_token", deployToken.token);
|
|
1930
|
+
ctx.output("user", deployToken.username);
|
|
1471
1931
|
}
|
|
1472
1932
|
});
|
|
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
|
-
}
|
|
1933
|
+
};
|
|
1497
1934
|
|
|
1498
1935
|
const examples$1 = [
|
|
1499
1936
|
{
|
|
1500
|
-
description: "
|
|
1937
|
+
description: "Creating a GitLab project variable of type env_var",
|
|
1501
1938
|
example: yaml__default.default.stringify({
|
|
1502
1939
|
steps: [
|
|
1503
1940
|
{
|
|
1504
|
-
id: "
|
|
1505
|
-
action: "
|
|
1506
|
-
name: "Create
|
|
1941
|
+
id: "createVariable",
|
|
1942
|
+
action: "gitlab:createGitlabProjectVariableAction",
|
|
1943
|
+
name: "Create GitLab Project Variable",
|
|
1507
1944
|
input: {
|
|
1508
1945
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
assignee: "my-assignee"
|
|
1946
|
+
projectId: "123",
|
|
1947
|
+
key: "MY_VARIABLE",
|
|
1948
|
+
value: "my_value",
|
|
1949
|
+
variableType: "env_var"
|
|
1514
1950
|
}
|
|
1515
1951
|
}
|
|
1516
1952
|
]
|
|
1517
1953
|
})
|
|
1518
1954
|
},
|
|
1519
1955
|
{
|
|
1520
|
-
description: "
|
|
1956
|
+
description: "Creating a GitLab project variable of type file",
|
|
1521
1957
|
example: yaml__default.default.stringify({
|
|
1522
1958
|
steps: [
|
|
1523
1959
|
{
|
|
1524
|
-
id: "
|
|
1525
|
-
action: "
|
|
1526
|
-
name: "Create
|
|
1960
|
+
id: "createVariable",
|
|
1961
|
+
action: "gitlab:createGitlabProjectVariableAction",
|
|
1962
|
+
name: "Create GitLab Project Variable",
|
|
1527
1963
|
input: {
|
|
1528
1964
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
removeSourceBranch: true
|
|
1965
|
+
projectId: "123",
|
|
1966
|
+
key: "MY_VARIABLE",
|
|
1967
|
+
value: "my-file-content",
|
|
1968
|
+
variableType: "file"
|
|
1534
1969
|
}
|
|
1535
1970
|
}
|
|
1536
1971
|
]
|
|
1537
1972
|
})
|
|
1538
1973
|
},
|
|
1539
1974
|
{
|
|
1540
|
-
description: "Create a
|
|
1975
|
+
description: "Create a GitLab project variable that is protected.",
|
|
1541
1976
|
example: yaml__default.default.stringify({
|
|
1542
1977
|
steps: [
|
|
1543
1978
|
{
|
|
1544
|
-
id: "
|
|
1545
|
-
action: "
|
|
1546
|
-
name: "Create
|
|
1979
|
+
id: "createVariable",
|
|
1980
|
+
action: "gitlab:createGitlabProjectVariableAction",
|
|
1981
|
+
name: "Create GitLab Project Variable",
|
|
1547
1982
|
input: {
|
|
1548
1983
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
targetPath: "Subdirectory"
|
|
1984
|
+
projectId: "456",
|
|
1985
|
+
key: "MY_VARIABLE",
|
|
1986
|
+
value: "my_value",
|
|
1987
|
+
variableType: "env_var",
|
|
1988
|
+
variableProtected: true
|
|
1555
1989
|
}
|
|
1556
1990
|
}
|
|
1557
1991
|
]
|
|
1558
1992
|
})
|
|
1559
1993
|
},
|
|
1560
1994
|
{
|
|
1561
|
-
description: "Create a
|
|
1995
|
+
description: "Create a GitLab project variable with masked flag as true",
|
|
1562
1996
|
example: yaml__default.default.stringify({
|
|
1563
1997
|
steps: [
|
|
1564
1998
|
{
|
|
1565
|
-
id: "
|
|
1566
|
-
action: "
|
|
1567
|
-
name: "Create
|
|
1999
|
+
id: "createVariable",
|
|
2000
|
+
action: "gitlab:createGitlabProjectVariableAction",
|
|
2001
|
+
name: "Create GitLab Project Variable",
|
|
1568
2002
|
input: {
|
|
1569
2003
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
2004
|
+
projectId: "789",
|
|
2005
|
+
key: "DB_PASSWORD",
|
|
2006
|
+
value: "password123",
|
|
2007
|
+
variableType: "env_var",
|
|
2008
|
+
masked: true
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
]
|
|
2012
|
+
})
|
|
2013
|
+
},
|
|
2014
|
+
{
|
|
2015
|
+
description: "Create a GitLab project variable that is expandable.",
|
|
2016
|
+
example: yaml__default.default.stringify({
|
|
2017
|
+
steps: [
|
|
2018
|
+
{
|
|
2019
|
+
id: "createVariable",
|
|
2020
|
+
action: "gitlab:projectVariable:create",
|
|
2021
|
+
name: "Create GitLab Project Variable",
|
|
2022
|
+
input: {
|
|
2023
|
+
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
2024
|
+
projectId: "123",
|
|
2025
|
+
key: "MY_VARIABLE",
|
|
2026
|
+
value: "my_value",
|
|
2027
|
+
variableType: "env_var",
|
|
2028
|
+
raw: true
|
|
1575
2029
|
}
|
|
1576
2030
|
}
|
|
1577
2031
|
]
|
|
1578
2032
|
})
|
|
1579
2033
|
},
|
|
1580
2034
|
{
|
|
1581
|
-
description: "Create a
|
|
2035
|
+
description: "Create a GitLab project variable with a specific environment scope.",
|
|
1582
2036
|
example: yaml__default.default.stringify({
|
|
1583
2037
|
steps: [
|
|
1584
2038
|
{
|
|
1585
|
-
id: "
|
|
1586
|
-
action: "
|
|
1587
|
-
name: "Create
|
|
2039
|
+
id: "createVariable",
|
|
2040
|
+
action: "gitlab:projectVariable:create",
|
|
2041
|
+
name: "Create GitLab Project Variable",
|
|
1588
2042
|
input: {
|
|
1589
2043
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
2044
|
+
projectId: "123",
|
|
2045
|
+
key: "MY_VARIABLE",
|
|
2046
|
+
value: "my_value",
|
|
2047
|
+
variableType: "env_var",
|
|
2048
|
+
environmentScope: "production"
|
|
1595
2049
|
}
|
|
1596
2050
|
}
|
|
1597
2051
|
]
|
|
1598
2052
|
})
|
|
1599
2053
|
},
|
|
1600
2054
|
{
|
|
1601
|
-
description: "Create a
|
|
2055
|
+
description: "Create a GitLab project variable with a wildcard environment scope.",
|
|
1602
2056
|
example: yaml__default.default.stringify({
|
|
1603
2057
|
steps: [
|
|
1604
2058
|
{
|
|
1605
|
-
id: "
|
|
1606
|
-
action: "
|
|
1607
|
-
name: "Create
|
|
2059
|
+
id: "createVariable",
|
|
2060
|
+
action: "gitlab:projectVariable:create",
|
|
2061
|
+
name: "Create GitLab Project Variable",
|
|
1608
2062
|
input: {
|
|
1609
2063
|
repoUrl: "gitlab.com?repo=repo&owner=owner",
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
2064
|
+
projectId: "123",
|
|
2065
|
+
key: "MY_VARIABLE",
|
|
2066
|
+
value: "my_value",
|
|
2067
|
+
variableType: "env_var",
|
|
2068
|
+
environmentScope: "*"
|
|
1615
2069
|
}
|
|
1616
2070
|
}
|
|
1617
2071
|
]
|
|
@@ -1619,193 +2073,56 @@ const examples$1 = [
|
|
|
1619
2073
|
}
|
|
1620
2074
|
];
|
|
1621
2075
|
|
|
1622
|
-
const
|
|
2076
|
+
const createGitlabProjectVariableAction = (options) => {
|
|
1623
2077
|
const { integrations } = options;
|
|
1624
2078
|
return pluginScaffolderNode.createTemplateAction({
|
|
1625
|
-
id: "
|
|
2079
|
+
id: "gitlab:projectVariable:create",
|
|
1626
2080
|
examples: examples$1,
|
|
1627
2081
|
schema: {
|
|
1628
|
-
input:
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
},
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
},
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
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
|
-
}
|
|
2082
|
+
input: commonGitlabConfig.merge(
|
|
2083
|
+
zod.z.object({
|
|
2084
|
+
projectId: zod.z.union([zod.z.number(), zod.z.string()], {
|
|
2085
|
+
description: "Project ID"
|
|
2086
|
+
}),
|
|
2087
|
+
key: zod.z.string({
|
|
2088
|
+
description: "The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed"
|
|
2089
|
+
}).regex(/^[A-Za-z0-9_]{1,255}$/),
|
|
2090
|
+
value: zod.z.string({ description: "The value of a variable" }),
|
|
2091
|
+
variableType: zod.z.string({
|
|
2092
|
+
description: "Variable Type (env_var or file)"
|
|
2093
|
+
}),
|
|
2094
|
+
variableProtected: zod.z.boolean({ description: "Whether the variable is protected" }).default(false).optional(),
|
|
2095
|
+
masked: zod.z.boolean({ description: "Whether the variable is masked" }).default(false).optional(),
|
|
2096
|
+
raw: zod.z.boolean({ description: "Whether the variable is expandable" }).default(false).optional(),
|
|
2097
|
+
environmentScope: zod.z.string({ description: "The environment_scope of the variable" }).default("*").optional()
|
|
2098
|
+
})
|
|
2099
|
+
)
|
|
1718
2100
|
},
|
|
1719
2101
|
async handler(ctx) {
|
|
1720
2102
|
const {
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
title,
|
|
1730
|
-
token
|
|
2103
|
+
projectId,
|
|
2104
|
+
key,
|
|
2105
|
+
value,
|
|
2106
|
+
variableType,
|
|
2107
|
+
variableProtected = false,
|
|
2108
|
+
masked = false,
|
|
2109
|
+
raw = false,
|
|
2110
|
+
environmentScope = "*"
|
|
1731
2111
|
} = ctx.input;
|
|
1732
|
-
const {
|
|
1733
|
-
const
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
token,
|
|
1737
|
-
repoUrl
|
|
2112
|
+
const { token, integrationConfig } = getToken(ctx.input, integrations);
|
|
2113
|
+
const api = new node.Gitlab({
|
|
2114
|
+
host: integrationConfig.config.baseUrl,
|
|
2115
|
+
token
|
|
1738
2116
|
});
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
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
|
|
2117
|
+
await api.ProjectVariables.create(projectId, {
|
|
2118
|
+
key,
|
|
2119
|
+
value,
|
|
2120
|
+
variable_type: variableType,
|
|
2121
|
+
protected: variableProtected,
|
|
2122
|
+
masked,
|
|
2123
|
+
raw,
|
|
2124
|
+
environment_scope: environmentScope
|
|
1760
2125
|
});
|
|
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
2126
|
}
|
|
1810
2127
|
});
|
|
1811
2128
|
};
|
|
@@ -2024,14 +2341,17 @@ const gitlabModule = backendPluginApi.createBackendModule({
|
|
|
2024
2341
|
createGitlabProjectDeployTokenAction({ integrations }),
|
|
2025
2342
|
createGitlabProjectVariableAction({ integrations }),
|
|
2026
2343
|
createGitlabRepoPushAction({ integrations }),
|
|
2344
|
+
editGitlabIssueAction({ integrations }),
|
|
2027
2345
|
createPublishGitlabAction({ config, integrations }),
|
|
2028
|
-
createPublishGitlabMergeRequestAction({ integrations })
|
|
2346
|
+
createPublishGitlabMergeRequestAction({ integrations }),
|
|
2347
|
+
createTriggerGitlabPipelineAction({ integrations })
|
|
2029
2348
|
);
|
|
2030
2349
|
}
|
|
2031
2350
|
});
|
|
2032
2351
|
}
|
|
2033
2352
|
});
|
|
2034
2353
|
|
|
2354
|
+
exports.IssueStateEvent = IssueStateEvent;
|
|
2035
2355
|
exports.IssueType = IssueType;
|
|
2036
2356
|
exports.createGitlabGroupEnsureExistsAction = createGitlabGroupEnsureExistsAction;
|
|
2037
2357
|
exports.createGitlabIssueAction = createGitlabIssueAction;
|
|
@@ -2041,5 +2361,7 @@ exports.createGitlabProjectVariableAction = createGitlabProjectVariableAction;
|
|
|
2041
2361
|
exports.createGitlabRepoPushAction = createGitlabRepoPushAction;
|
|
2042
2362
|
exports.createPublishGitlabAction = createPublishGitlabAction;
|
|
2043
2363
|
exports.createPublishGitlabMergeRequestAction = createPublishGitlabMergeRequestAction;
|
|
2364
|
+
exports.createTriggerGitlabPipelineAction = createTriggerGitlabPipelineAction;
|
|
2044
2365
|
exports.default = gitlabModule;
|
|
2366
|
+
exports.editGitlabIssueAction = editGitlabIssueAction;
|
|
2045
2367
|
//# sourceMappingURL=index.cjs.js.map
|