@backstage/plugin-scaffolder-backend-module-gitlab 0.8.0-next.3 → 0.8.1-next.0
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 +30 -0
- package/dist/actions/gitlabGroupEnsureExists.cjs.js +13 -7
- package/dist/actions/gitlabGroupEnsureExists.cjs.js.map +1 -1
- package/dist/actions/gitlabIssueCreate.cjs.js +30 -14
- package/dist/actions/gitlabIssueCreate.cjs.js.map +1 -1
- package/dist/actions/gitlabMergeRequest.cjs.js +79 -57
- package/dist/actions/gitlabMergeRequest.cjs.js.map +1 -1
- package/dist/actions/gitlabRepoPush.cjs.js +1 -1
- package/dist/actions/gitlabRepoPush.cjs.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-backend-module-gitlab
|
|
2
2
|
|
|
3
|
+
## 0.8.1-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-plugin-api@1.2.1-next.0
|
|
9
|
+
- @backstage/plugin-scaffolder-node@0.7.1-next.0
|
|
10
|
+
|
|
11
|
+
## 0.8.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 06eee14: Support empty repository creation in gitlab without workspace pushing and conditionally skip if the repository already exists.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- a0419a6: Made gitlab:group:ensureExists action idempotent
|
|
20
|
+
- 9d04e91: Fix automated assignment of reviewers for instances without premium/ultimate license (404). Introduce opt-in flag for automatic reviewer assignment based on approval rules
|
|
21
|
+
- 9545c5f: `createGitlabProjectMigrateAction` can now output the `migrationId`
|
|
22
|
+
- e52cee6: Made gitlab:issues:create action idempotent.
|
|
23
|
+
- fe44946: Fixed bug of passing wrong value to `onChange` handler when using `GitLab` autocomplete
|
|
24
|
+
- 66e392f: Making publish:gitlab:merge-request idempotent.
|
|
25
|
+
- a7b22eb: Fixed bug in gitlabRepoPush where it was looking in the wrong place in the exception response from gitbeaker when checking if the branch already exists
|
|
26
|
+
- Updated dependencies
|
|
27
|
+
- @backstage/backend-plugin-api@1.2.0
|
|
28
|
+
- @backstage/plugin-scaffolder-node@0.7.0
|
|
29
|
+
- @backstage/config@1.3.2
|
|
30
|
+
- @backstage/errors@1.2.7
|
|
31
|
+
- @backstage/integration@1.16.1
|
|
32
|
+
|
|
3
33
|
## 0.8.0-next.3
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -55,13 +55,19 @@ const createGitlabGroupEnsureExistsAction = (options) => {
|
|
|
55
55
|
);
|
|
56
56
|
if (!subGroup) {
|
|
57
57
|
ctx.logger.info(`creating missing group ${fullPath}`);
|
|
58
|
-
parentId =
|
|
59
|
-
name
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
parentId = await ctx.checkpoint({
|
|
59
|
+
key: `ensure.${name}.${slug}.${parentId}`,
|
|
60
|
+
// eslint-disable-next-line no-loop-func
|
|
61
|
+
fn: async () => {
|
|
62
|
+
return (await api.Groups.create(
|
|
63
|
+
name,
|
|
64
|
+
slug,
|
|
65
|
+
parentId ? {
|
|
66
|
+
parentId
|
|
67
|
+
} : {}
|
|
68
|
+
))?.id;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
65
71
|
} else {
|
|
66
72
|
parentId = subGroup.id;
|
|
67
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlabGroupEnsureExists.cjs.js","sources":["../../src/actions/gitlabGroupEnsureExists.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { GroupSchema } from '@gitbeaker/rest';\nimport { z } from 'zod';\nimport commonGitlabConfig from '../commonGitlabConfig';\nimport { getClient, parseRepoUrl } from '../util';\nimport { examples } from './gitlabGroupEnsureExists.examples';\n\n/**\n * Creates an `gitlab:group:ensureExists` Scaffolder action.\n *\n * @public\n */\nexport const createGitlabGroupEnsureExistsAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction({\n id: 'gitlab:group:ensureExists',\n description: 'Ensures a Gitlab group exists',\n supportsDryRun: true,\n examples,\n schema: {\n input: commonGitlabConfig.merge(\n z.object({\n path: z\n .array(\n z.string().or(\n z.object({\n name: z.string(),\n slug: z.string(),\n }),\n ),\n {\n description:\n 'A path of group names or objects (name and slug) that is ensured to exist',\n },\n )\n .min(1),\n }),\n ),\n output: z.object({\n groupId: z\n .number({ description: 'The id of the innermost sub-group' })\n .optional(),\n }),\n },\n async handler(ctx) {\n if (ctx.isDryRun) {\n ctx.output('groupId', 42);\n return;\n }\n\n const { token, repoUrl, path } = ctx.input;\n\n const { host } = parseRepoUrl(repoUrl, integrations);\n\n const api = getClient({ host, integrations, token });\n\n let currentPath: string | null = null;\n let parentId: number | null = null;\n for (const pathElement of path) {\n const slug =\n typeof pathElement === 'string' ? pathElement : pathElement.slug;\n const name =\n typeof pathElement === 'string' ? pathElement : pathElement.name;\n const fullPath: string = currentPath ? `${currentPath}/${slug}` : slug;\n const result = (await api.Groups.search(\n fullPath,\n )) as unknown as Array<GroupSchema>; // recast since the return type for search is wrong in the gitbeaker typings\n const subGroup = result.find(\n searchPathElem => searchPathElem.full_path === fullPath,\n );\n if (!subGroup) {\n ctx.logger.info(`creating missing group ${fullPath}`);\n parentId = (\n await api.Groups.create(\n
|
|
1
|
+
{"version":3,"file":"gitlabGroupEnsureExists.cjs.js","sources":["../../src/actions/gitlabGroupEnsureExists.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { GroupSchema } from '@gitbeaker/rest';\nimport { z } from 'zod';\nimport commonGitlabConfig from '../commonGitlabConfig';\nimport { getClient, parseRepoUrl } from '../util';\nimport { examples } from './gitlabGroupEnsureExists.examples';\n\n/**\n * Creates an `gitlab:group:ensureExists` Scaffolder action.\n *\n * @public\n */\nexport const createGitlabGroupEnsureExistsAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction({\n id: 'gitlab:group:ensureExists',\n description: 'Ensures a Gitlab group exists',\n supportsDryRun: true,\n examples,\n schema: {\n input: commonGitlabConfig.merge(\n z.object({\n path: z\n .array(\n z.string().or(\n z.object({\n name: z.string(),\n slug: z.string(),\n }),\n ),\n {\n description:\n 'A path of group names or objects (name and slug) that is ensured to exist',\n },\n )\n .min(1),\n }),\n ),\n output: z.object({\n groupId: z\n .number({ description: 'The id of the innermost sub-group' })\n .optional(),\n }),\n },\n async handler(ctx) {\n if (ctx.isDryRun) {\n ctx.output('groupId', 42);\n return;\n }\n\n const { token, repoUrl, path } = ctx.input;\n\n const { host } = parseRepoUrl(repoUrl, integrations);\n\n const api = getClient({ host, integrations, token });\n\n let currentPath: string | null = null;\n let parentId: number | null = null;\n for (const pathElement of path) {\n const slug =\n typeof pathElement === 'string' ? pathElement : pathElement.slug;\n const name =\n typeof pathElement === 'string' ? pathElement : pathElement.name;\n const fullPath: string = currentPath ? `${currentPath}/${slug}` : slug;\n const result = (await api.Groups.search(\n fullPath,\n )) as unknown as Array<GroupSchema>; // recast since the return type for search is wrong in the gitbeaker typings\n const subGroup = result.find(\n searchPathElem => searchPathElem.full_path === fullPath,\n );\n if (!subGroup) {\n ctx.logger.info(`creating missing group ${fullPath}`);\n\n parentId = await ctx.checkpoint({\n key: `ensure.${name}.${slug}.${parentId}`,\n // eslint-disable-next-line no-loop-func\n fn: async () => {\n return (\n await api.Groups.create(\n name,\n slug,\n parentId\n ? {\n parentId: parentId,\n }\n : {},\n )\n )?.id;\n },\n });\n } else {\n parentId = subGroup.id;\n }\n currentPath = fullPath;\n }\n if (parentId !== null) {\n ctx.output('groupId', parentId);\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","commonGitlabConfig","z","parseRepoUrl","getClient"],"mappings":"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"}
|
|
@@ -84,16 +84,22 @@ const createGitlabIssueAction = (options) => {
|
|
|
84
84
|
const { host } = util.parseRepoUrl(repoUrl, integrations);
|
|
85
85
|
const api = util.getClient({ host, integrations, token });
|
|
86
86
|
let isEpicScoped = false;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
isEpicScoped = await ctx.checkpoint({
|
|
88
|
+
key: `is.epic.scoped.${projectId}.${title}`,
|
|
89
|
+
fn: async () => {
|
|
90
|
+
if (epicId) {
|
|
91
|
+
isEpicScoped = await util.checkEpicScope(api, projectId, epicId);
|
|
92
|
+
if (isEpicScoped) {
|
|
93
|
+
ctx.logger.info("Epic is within Project Scope");
|
|
94
|
+
} else {
|
|
95
|
+
ctx.logger.warn(
|
|
96
|
+
"Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return isEpicScoped;
|
|
95
101
|
}
|
|
96
|
-
}
|
|
102
|
+
});
|
|
97
103
|
const mappedCreatedAt = util.convertDate(
|
|
98
104
|
String(createdAt),
|
|
99
105
|
(/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -113,11 +119,21 @@ const createGitlabIssueAction = (options) => {
|
|
|
113
119
|
milestoneId,
|
|
114
120
|
weight
|
|
115
121
|
};
|
|
116
|
-
const response = await
|
|
117
|
-
projectId
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
const response = await ctx.checkpoint({
|
|
123
|
+
key: `issue.${projectId}.${title}`,
|
|
124
|
+
fn: async () => {
|
|
125
|
+
const issue = await api.Issues.create(
|
|
126
|
+
projectId,
|
|
127
|
+
title,
|
|
128
|
+
issueOptions
|
|
129
|
+
);
|
|
130
|
+
return {
|
|
131
|
+
id: issue.id,
|
|
132
|
+
web_url: issue.web_url,
|
|
133
|
+
iid: issue.iid
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
});
|
|
121
137
|
ctx.output("issueId", response.id);
|
|
122
138
|
ctx.output("issueUrl", response.web_url);
|
|
123
139
|
ctx.output("issueIid", response.iid);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlabIssueCreate.cjs.js","sources":["../../src/actions/gitlabIssueCreate.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport commonGitlabConfig, { IssueType } from '../commonGitlabConfig';\nimport { examples } from './gitlabIssueCreate.examples';\nimport { z } from 'zod';\nimport { checkEpicScope, convertDate, getClient, parseRepoUrl } from '../util';\nimport { CreateIssueOptions, IssueSchema } from '@gitbeaker/rest';\nimport { getErrorMessage } from './helpers';\n\nconst issueInputProperties = z.object({\n projectId: z.number().describe('Project Id'),\n title: z.string({ description: 'Title of the issue' }),\n assignees: z\n .array(z.number(), {\n description: 'IDs of the users to assign the issue to.',\n })\n .optional(),\n confidential: z.boolean({ description: 'Issue Confidentiality' }).optional(),\n description: z.string().describe('Issue description').max(1048576).optional(),\n createdAt: z\n .string()\n .describe('Creation date/time')\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/,\n 'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',\n )\n .optional(),\n dueDate: z\n .string()\n .describe('Due date/time')\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/,\n 'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',\n )\n .optional(),\n discussionToResolve: z\n .string({\n description:\n 'Id of a discussion to resolve. Use in combination with \"merge_request_to_resolve_discussions_of\"',\n })\n .optional(),\n epicId: z\n .number({ description: 'Id of the linked Epic' })\n .min(0, 'Valid values should be equal or greater than zero')\n .optional(),\n labels: z.string({ description: 'Labels to apply' }).optional(),\n issueType: z\n .nativeEnum(IssueType, {\n description: 'Type of the issue',\n })\n .optional(),\n mergeRequestToResolveDiscussionsOf: z\n .number({\n description: 'IID of a merge request in which to resolve all issues',\n })\n .optional(),\n milestoneId: z\n .number({ description: 'Global ID of a milestone to assign the issue' })\n .optional(),\n weight: z\n .number({ description: 'The issue weight' })\n .min(0)\n .refine(value => {\n const isValid = value >= 0;\n if (!isValid) {\n return {\n message: 'Valid values should be equal or greater than zero',\n };\n }\n return isValid;\n })\n .optional(),\n});\n\nconst issueOutputProperties = z.object({\n issueUrl: z.string({ description: 'Issue Url' }),\n issueId: z.number({ description: 'Issue Id' }),\n issueIid: z.number({ description: 'Issue Iid' }),\n});\n\n/**\n * Creates a `gitlab:issues:create` Scaffolder action.\n *\n * @param options - Templating configuration.\n * @public\n */\nexport const createGitlabIssueAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n return createTemplateAction({\n id: 'gitlab:issues:create',\n description: 'Creates a Gitlab issue.',\n examples,\n schema: {\n input: commonGitlabConfig.merge(issueInputProperties),\n output: issueOutputProperties,\n },\n async handler(ctx) {\n try {\n const {\n repoUrl,\n projectId,\n title,\n description = '',\n confidential = false,\n assignees = [],\n createdAt = '',\n dueDate,\n discussionToResolve = '',\n epicId,\n labels = '',\n issueType,\n mergeRequestToResolveDiscussionsOf,\n milestoneId,\n weight,\n token,\n } = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);\n\n const { host } = parseRepoUrl(repoUrl, integrations);\n const api = getClient({ host, integrations, token });\n\n let isEpicScoped = false;\n\n if (epicId) {\n isEpicScoped = await checkEpicScope(api, projectId, epicId);\n\n if (isEpicScoped) {\n ctx.logger.info('Epic is within Project Scope');\n } else {\n ctx.logger.warn(\n 'Chosen epic is not within the Project Scope. The issue will be created without an associated epic.',\n );\n }\n }\n const mappedCreatedAt = convertDate(\n String(createdAt),\n new Date().toISOString(),\n );\n const mappedDueDate = dueDate\n ? convertDate(String(dueDate), new Date().toISOString())\n : undefined;\n\n const issueOptions: CreateIssueOptions = {\n description,\n assigneeIds: assignees,\n confidential,\n epicId: isEpicScoped ? epicId : undefined,\n labels,\n createdAt: mappedCreatedAt,\n dueDate: mappedDueDate,\n discussionToResolve,\n issueType,\n mergeRequestToResolveDiscussionsOf,\n milestoneId,\n weight,\n };\n\n const response = (await api.Issues.create(\n projectId,\n title,\n issueOptions,\n )) as IssueSchema;\n\n ctx.output('issueId', response.id);\n ctx.output('issueUrl', response.web_url);\n ctx.output('issueIid', response.iid);\n } catch (error: any) {\n if (error instanceof z.ZodError) {\n // Handling Zod validation errors\n throw new InputError(`Validation error: ${error.message}`, {\n validationErrors: error.errors,\n });\n }\n // Handling other errors\n throw new InputError(\n `Failed to create GitLab issue: ${getErrorMessage(error)}`,\n );\n }\n },\n });\n};\n"],"names":["z","IssueType","createTemplateAction","examples","commonGitlabConfig","parseRepoUrl","getClient","checkEpicScope","convertDate","InputError","getErrorMessage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gitlabIssueCreate.cjs.js","sources":["../../src/actions/gitlabIssueCreate.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport commonGitlabConfig, { IssueType } from '../commonGitlabConfig';\nimport { examples } from './gitlabIssueCreate.examples';\nimport { z } from 'zod';\nimport { checkEpicScope, convertDate, getClient, parseRepoUrl } from '../util';\nimport { CreateIssueOptions, IssueSchema } from '@gitbeaker/rest';\nimport { getErrorMessage } from './helpers';\n\nconst issueInputProperties = z.object({\n projectId: z.number().describe('Project Id'),\n title: z.string({ description: 'Title of the issue' }),\n assignees: z\n .array(z.number(), {\n description: 'IDs of the users to assign the issue to.',\n })\n .optional(),\n confidential: z.boolean({ description: 'Issue Confidentiality' }).optional(),\n description: z.string().describe('Issue description').max(1048576).optional(),\n createdAt: z\n .string()\n .describe('Creation date/time')\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/,\n 'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',\n )\n .optional(),\n dueDate: z\n .string()\n .describe('Due date/time')\n .regex(\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/,\n 'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',\n )\n .optional(),\n discussionToResolve: z\n .string({\n description:\n 'Id of a discussion to resolve. Use in combination with \"merge_request_to_resolve_discussions_of\"',\n })\n .optional(),\n epicId: z\n .number({ description: 'Id of the linked Epic' })\n .min(0, 'Valid values should be equal or greater than zero')\n .optional(),\n labels: z.string({ description: 'Labels to apply' }).optional(),\n issueType: z\n .nativeEnum(IssueType, {\n description: 'Type of the issue',\n })\n .optional(),\n mergeRequestToResolveDiscussionsOf: z\n .number({\n description: 'IID of a merge request in which to resolve all issues',\n })\n .optional(),\n milestoneId: z\n .number({ description: 'Global ID of a milestone to assign the issue' })\n .optional(),\n weight: z\n .number({ description: 'The issue weight' })\n .min(0)\n .refine(value => {\n const isValid = value >= 0;\n if (!isValid) {\n return {\n message: 'Valid values should be equal or greater than zero',\n };\n }\n return isValid;\n })\n .optional(),\n});\n\nconst issueOutputProperties = z.object({\n issueUrl: z.string({ description: 'Issue Url' }),\n issueId: z.number({ description: 'Issue Id' }),\n issueIid: z.number({ description: 'Issue Iid' }),\n});\n\n/**\n * Creates a `gitlab:issues:create` Scaffolder action.\n *\n * @param options - Templating configuration.\n * @public\n */\nexport const createGitlabIssueAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n return createTemplateAction({\n id: 'gitlab:issues:create',\n description: 'Creates a Gitlab issue.',\n examples,\n schema: {\n input: commonGitlabConfig.merge(issueInputProperties),\n output: issueOutputProperties,\n },\n async handler(ctx) {\n try {\n const {\n repoUrl,\n projectId,\n title,\n description = '',\n confidential = false,\n assignees = [],\n createdAt = '',\n dueDate,\n discussionToResolve = '',\n epicId,\n labels = '',\n issueType,\n mergeRequestToResolveDiscussionsOf,\n milestoneId,\n weight,\n token,\n } = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);\n\n const { host } = parseRepoUrl(repoUrl, integrations);\n const api = getClient({ host, integrations, token });\n\n let isEpicScoped = false;\n\n isEpicScoped = await ctx.checkpoint({\n key: `is.epic.scoped.${projectId}.${title}`,\n fn: async () => {\n if (epicId) {\n isEpicScoped = await checkEpicScope(api, projectId, epicId);\n\n if (isEpicScoped) {\n ctx.logger.info('Epic is within Project Scope');\n } else {\n ctx.logger.warn(\n 'Chosen epic is not within the Project Scope. The issue will be created without an associated epic.',\n );\n }\n }\n return isEpicScoped;\n },\n });\n\n const mappedCreatedAt = convertDate(\n String(createdAt),\n new Date().toISOString(),\n );\n const mappedDueDate = dueDate\n ? convertDate(String(dueDate), new Date().toISOString())\n : undefined;\n\n const issueOptions: CreateIssueOptions = {\n description,\n assigneeIds: assignees,\n confidential,\n epicId: isEpicScoped ? epicId : undefined,\n labels,\n createdAt: mappedCreatedAt,\n dueDate: mappedDueDate,\n discussionToResolve,\n issueType,\n mergeRequestToResolveDiscussionsOf,\n milestoneId,\n weight,\n };\n\n const response = await ctx.checkpoint({\n key: `issue.${projectId}.${title}`,\n fn: async () => {\n const issue = (await api.Issues.create(\n projectId,\n title,\n issueOptions,\n )) as IssueSchema;\n\n return {\n id: issue.id,\n web_url: issue.web_url,\n iid: issue.iid,\n };\n },\n });\n\n ctx.output('issueId', response.id);\n ctx.output('issueUrl', response.web_url);\n ctx.output('issueIid', response.iid);\n } catch (error: any) {\n if (error instanceof z.ZodError) {\n // Handling Zod validation errors\n throw new InputError(`Validation error: ${error.message}`, {\n validationErrors: error.errors,\n });\n }\n // Handling other errors\n throw new InputError(\n `Failed to create GitLab issue: ${getErrorMessage(error)}`,\n );\n }\n },\n });\n};\n"],"names":["z","IssueType","createTemplateAction","examples","commonGitlabConfig","parseRepoUrl","getClient","checkEpicScope","convertDate","InputError","getErrorMessage"],"mappings":"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"}
|
|
@@ -316,71 +316,93 @@ which uses additional API calls in order to detect whether to 'create', 'update'
|
|
|
316
316
|
);
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
|
|
339
|
-
assigneeId,
|
|
340
|
-
reviewerIds
|
|
319
|
+
await ctx.checkpoint({
|
|
320
|
+
key: `commit.to.${repoID}.${branchName}`,
|
|
321
|
+
fn: async () => {
|
|
322
|
+
if (actions.length) {
|
|
323
|
+
try {
|
|
324
|
+
const commit = await api.Commits.create(
|
|
325
|
+
repoID,
|
|
326
|
+
branchName,
|
|
327
|
+
title,
|
|
328
|
+
actions
|
|
329
|
+
);
|
|
330
|
+
return commit.id;
|
|
331
|
+
} catch (e) {
|
|
332
|
+
throw new errors.InputError(
|
|
333
|
+
`Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${helpers.getErrorMessage(
|
|
334
|
+
e
|
|
335
|
+
)}`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
341
338
|
}
|
|
342
|
-
|
|
343
|
-
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
const { mrId, mrWebUrl } = await ctx.checkpoint({
|
|
343
|
+
key: `create.mr.${repoID}.${branchName}`,
|
|
344
|
+
fn: async () => {
|
|
344
345
|
try {
|
|
345
|
-
const
|
|
346
|
-
api,
|
|
347
|
-
mergeRequest.iid,
|
|
346
|
+
const mergeRequest = await api.MergeRequests.create(
|
|
348
347
|
repoID,
|
|
349
|
-
|
|
348
|
+
branchName,
|
|
349
|
+
String(targetBranch),
|
|
350
|
+
title,
|
|
351
|
+
{
|
|
352
|
+
description,
|
|
353
|
+
removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
|
|
354
|
+
assigneeId,
|
|
355
|
+
reviewerIds
|
|
356
|
+
}
|
|
350
357
|
);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
]);
|
|
356
|
-
mergeRequest = await api.MergeRequests.edit(
|
|
357
|
-
repoID,
|
|
358
|
-
mergeRequest.iid,
|
|
359
|
-
{
|
|
360
|
-
reviewerIds: Array.from(eligibleUserIds)
|
|
361
|
-
}
|
|
362
|
-
);
|
|
363
|
-
}
|
|
358
|
+
return {
|
|
359
|
+
mrId: mergeRequest.iid,
|
|
360
|
+
mrWebUrl: mergeRequest.web_url ?? mergeRequest.webUrl
|
|
361
|
+
};
|
|
364
362
|
} catch (e) {
|
|
365
|
-
|
|
366
|
-
`
|
|
367
|
-
e
|
|
368
|
-
)}.`
|
|
363
|
+
throw new errors.InputError(
|
|
364
|
+
`Merge request creation failed. ${helpers.getErrorMessage(e)}`
|
|
369
365
|
);
|
|
370
366
|
}
|
|
371
367
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
368
|
+
});
|
|
369
|
+
await ctx.checkpoint({
|
|
370
|
+
key: `create.mr.assign.reviewers.${repoID}.${branchName}`,
|
|
371
|
+
fn: async () => {
|
|
372
|
+
if (ctx.input.assignReviewersFromApprovalRules) {
|
|
373
|
+
try {
|
|
374
|
+
const reviewersFromApprovalRules = await getReviewersFromApprovalRules(api, mrId, repoID, ctx);
|
|
375
|
+
if (reviewersFromApprovalRules.length > 0) {
|
|
376
|
+
const eligibleUserIds = /* @__PURE__ */ new Set([
|
|
377
|
+
...reviewersFromApprovalRules,
|
|
378
|
+
...reviewerIds ?? []
|
|
379
|
+
]);
|
|
380
|
+
const mergeRequest = await api.MergeRequests.edit(
|
|
381
|
+
repoID,
|
|
382
|
+
mrId,
|
|
383
|
+
{
|
|
384
|
+
reviewerIds: Array.from(eligibleUserIds)
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
return {
|
|
388
|
+
mrWebUrl: mergeRequest.web_url ?? mergeRequest.webUrl
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
} catch (e) {
|
|
392
|
+
ctx.logger.warn(
|
|
393
|
+
`Failed to assign reviewers from approval rules: ${helpers.getErrorMessage(
|
|
394
|
+
e
|
|
395
|
+
)}.`
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return { mrWebUrl };
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
ctx.output("projectid", repoID);
|
|
403
|
+
ctx.output("targetBranchName", targetBranch);
|
|
404
|
+
ctx.output("projectPath", repoID);
|
|
405
|
+
ctx.output("mergeRequestUrl", mrWebUrl);
|
|
384
406
|
}
|
|
385
407
|
});
|
|
386
408
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlabMergeRequest.cjs.js","sources":["../../src/actions/gitlabMergeRequest.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createTemplateAction,\n parseRepoUrl,\n SerializedFile,\n serializeDirectoryContents,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n Gitlab,\n RepositoryTreeSchema,\n CommitAction,\n SimpleUserSchema,\n ExpandedMergeRequestSchema,\n Camelize,\n} from '@gitbeaker/rest';\nimport path from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { InputError } from '@backstage/errors';\nimport {\n LoggerService,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport { createGitlabApi, getErrorMessage } from './helpers';\nimport { examples } from './gitlabMergeRequest.examples';\nimport { createHash } from 'crypto';\n\nfunction computeSha256(file: SerializedFile): string {\n const hash = createHash('sha256');\n hash.update(file.content);\n return hash.digest('hex');\n}\n\nasync function getFileAction(\n fileInfo: { file: SerializedFile; targetPath?: string },\n target: { repoID: string; branch: string },\n api: InstanceType<typeof Gitlab>,\n logger: LoggerService,\n remoteFiles: RepositoryTreeSchema[],\n defaultCommitAction:\n | 'create'\n | 'delete'\n | 'update'\n | 'skip'\n | 'auto' = 'auto',\n): Promise<'create' | 'delete' | 'update' | 'skip'> {\n if (defaultCommitAction === 'auto') {\n const filePath = path.join(fileInfo.targetPath ?? '', fileInfo.file.path);\n\n if (remoteFiles?.some(remoteFile => remoteFile.path === filePath)) {\n try {\n const targetFile = await api.RepositoryFiles.show(\n target.repoID,\n filePath,\n target.branch,\n );\n if (computeSha256(fileInfo.file) === targetFile.content_sha256) {\n return 'skip';\n }\n } catch (error) {\n logger.warn(\n `Unable to retrieve detailed information for remote file ${filePath}`,\n );\n }\n return 'update';\n }\n return 'create';\n }\n return defaultCommitAction;\n}\n\nasync function getReviewersFromApprovalRules(\n api: InstanceType<typeof Gitlab>,\n mergerequestIId: number,\n repoID: string,\n ctx: any,\n): Promise<number[]> {\n try {\n // Because we don't know the code owners before the MR is created, we can't check the approval rules beforehand.\n // Getting the approval rules beforehand is very difficult, especially, because of the inheritance rules for groups.\n // Code owners take a moment to be processed and added to the approval rules after the MR is created.\n\n let mergeRequest:\n | ExpandedMergeRequestSchema\n | Camelize<ExpandedMergeRequestSchema> = await api.MergeRequests.show(\n repoID,\n mergerequestIId,\n );\n\n while (\n mergeRequest.detailed_merge_status === 'preparing' ||\n mergeRequest.detailed_merge_status === 'approvals_syncing' ||\n mergeRequest.detailed_merge_status === 'checking'\n ) {\n mergeRequest = await api.MergeRequests.show(repoID, mergeRequest.iid);\n ctx.logger.info(`${mergeRequest.detailed_merge_status}`);\n }\n\n const approvalRules = await api.MergeRequestApprovals.allApprovalRules(\n repoID,\n {\n mergerequestIId: mergeRequest.iid,\n },\n );\n\n return approvalRules\n .filter(rule => rule.eligible_approvers !== undefined)\n .map(rule => {\n return rule.eligible_approvers as SimpleUserSchema[];\n })\n .flat()\n .map(user => user.id);\n } catch (e) {\n ctx.logger.warn(\n `Failed to retrieve approval rules for MR ${mergerequestIId}: ${getErrorMessage(\n e,\n )}. Proceeding with MR creation without reviewers from approval rules.`,\n );\n return [];\n }\n}\n\n/**\n * Create a new action that creates a gitlab merge request.\n *\n * @public\n */\nexport const createPublishGitlabMergeRequestAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction<{\n repoUrl: string;\n title: string;\n description: string;\n branchName: string;\n targetBranchName?: string;\n sourcePath?: string;\n targetPath?: string;\n token?: string;\n commitAction?: 'create' | 'delete' | 'update' | 'skip' | 'auto';\n /** @deprecated projectID passed as query parameters in the repoUrl */\n projectid?: string;\n removeSourceBranch?: boolean;\n assignee?: string;\n reviewers?: string[];\n assignReviewersFromApprovalRules?: boolean;\n }>({\n id: 'publish:gitlab:merge-request',\n examples,\n schema: {\n input: {\n required: ['repoUrl', 'branchName'],\n type: 'object',\n properties: {\n repoUrl: {\n type: 'string',\n title: 'Repository Location',\n description: `\\\nAccepts the format 'gitlab.com?repo=project_name&owner=group_name' where \\\n'project_name' is the repository name and 'group_name' is a group or username`,\n },\n /** @deprecated projectID is passed as query parameters in the repoUrl */\n projectid: {\n type: 'string',\n title: 'projectid',\n description: 'Project ID/Name(slug) of the Gitlab Project',\n },\n title: {\n type: 'string',\n title: 'Merge Request Name',\n description: 'The name for the merge request',\n },\n description: {\n type: 'string',\n title: 'Merge Request Description',\n description: 'The description of the merge request',\n },\n branchName: {\n type: 'string',\n title: 'Source Branch Name',\n description: 'The source branch name of the merge request',\n },\n targetBranchName: {\n type: 'string',\n title: 'Target Branch Name',\n description: 'The target branch name of the merge request',\n },\n sourcePath: {\n type: 'string',\n title: 'Working Subdirectory',\n description: `\\\nSubdirectory of working directory to copy changes from. \\\nFor reasons of backward compatibility, any specified 'targetPath' input will \\\nbe applied in place of an absent/falsy value for this input. \\\nCircumvent this behavior using '.'`,\n },\n targetPath: {\n type: 'string',\n title: 'Repository Subdirectory',\n description: 'Subdirectory of repository to apply changes to',\n },\n token: {\n title: 'Authentication Token',\n type: 'string',\n description: 'The token to use for authorization to GitLab',\n },\n commitAction: {\n title: 'Commit action',\n type: 'string',\n enum: ['create', 'update', 'delete', 'auto'],\n description: `\\\nThe action to be used for git commit. Defaults to the custom 'auto' action provided by backstage,\nwhich uses additional API calls in order to detect whether to 'create', 'update' or 'skip' each source file.`,\n },\n removeSourceBranch: {\n title: 'Delete source branch',\n type: 'boolean',\n description:\n 'Option to delete source branch once the MR has been merged. Default: false',\n },\n assignee: {\n title: 'Merge Request Assignee',\n type: 'string',\n description: 'User this merge request will be assigned to',\n },\n reviewers: {\n title: 'Merge Request Reviewers',\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'Users that will be assigned as reviewers',\n },\n assignReviewersFromApprovalRules: {\n title: 'Assign reviewers from approval rules',\n type: 'boolean',\n description:\n 'Automatically assign reviewers from the approval rules of the MR. Includes Codeowners',\n },\n },\n },\n output: {\n type: 'object',\n properties: {\n targetBranchName: {\n title: 'Target branch name of the merge request',\n type: 'string',\n },\n projectid: {\n title: 'Gitlab Project id/Name(slug)',\n type: 'string',\n },\n projectPath: {\n title: 'Gitlab Project path',\n type: 'string',\n },\n mergeRequestUrl: {\n title: 'MergeRequest(MR) URL',\n type: 'string',\n description: 'Link to the merge request in GitLab',\n },\n },\n },\n },\n async handler(ctx) {\n const {\n assignee,\n reviewers,\n branchName,\n targetBranchName,\n description,\n repoUrl,\n removeSourceBranch,\n targetPath,\n sourcePath,\n title,\n token,\n } = ctx.input;\n\n const { owner, repo, project } = parseRepoUrl(repoUrl, integrations);\n const repoID = project ? project : `${owner}/${repo}`;\n\n const api = createGitlabApi({\n integrations,\n token,\n repoUrl,\n });\n\n let assigneeId = undefined;\n\n if (assignee !== undefined) {\n try {\n const assigneeUser = await api.Users.all({ username: assignee });\n assigneeId = assigneeUser[0].id;\n } catch (e) {\n ctx.logger.warn(\n `Failed to find gitlab user id for ${assignee}: ${getErrorMessage(\n e,\n )}. Proceeding with MR creation without an assignee.`,\n );\n }\n }\n\n let reviewerIds: number[] | undefined = undefined; // Explicitly set to undefined. Strangely, passing an empty array to the API will result the other options being undefined also being explicity passed to the Gitlab API call (e.g. assigneeId)\n if (reviewers !== undefined) {\n reviewerIds = (\n await Promise.all(\n reviewers.map(async reviewer => {\n try {\n const reviewerUser = await api.Users.all({\n username: reviewer,\n });\n return reviewerUser[0].id;\n } catch (e) {\n ctx.logger.warn(\n `Failed to find gitlab user id for ${reviewer}: ${e}. Proceeding with MR creation without reviewer.`,\n );\n return undefined;\n }\n }),\n )\n ).filter(id => id !== undefined) as number[];\n }\n\n let fileRoot: string;\n if (sourcePath) {\n fileRoot = resolveSafeChildPath(ctx.workspacePath, sourcePath);\n } else if (targetPath) {\n // for backward compatibility\n fileRoot = resolveSafeChildPath(ctx.workspacePath, targetPath);\n } else {\n fileRoot = ctx.workspacePath;\n }\n\n const fileContents = await serializeDirectoryContents(fileRoot, {\n gitignore: true,\n });\n\n let targetBranch = targetBranchName;\n if (!targetBranch) {\n const projects = await api.Projects.show(repoID);\n const defaultBranch = projects.default_branch ?? projects.defaultBranch;\n if (typeof defaultBranch !== 'string' || !defaultBranch) {\n throw new InputError(\n `The branch creation failed. Target branch was not provided, and could not find default branch from project settings. Project: ${JSON.stringify(\n project,\n )}`,\n );\n }\n targetBranch = defaultBranch;\n }\n\n let remoteFiles: RepositoryTreeSchema[] = [];\n if ((ctx.input.commitAction ?? 'auto') === 'auto') {\n try {\n remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {\n ref: targetBranch,\n recursive: true,\n path: targetPath ?? undefined,\n });\n } catch (e) {\n ctx.logger.warn(\n `Could not retrieve the list of files for ${repoID} (branch: ${targetBranch}) : ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n const actions: CommitAction[] =\n ctx.input.commitAction === 'skip'\n ? []\n : (\n (\n await Promise.all(\n fileContents.map(async file => {\n const action = await getFileAction(\n { file, targetPath },\n { repoID, branch: targetBranch! },\n api,\n ctx.logger,\n remoteFiles,\n ctx.input.commitAction,\n );\n return { file, action };\n }),\n )\n ).filter(o => o.action !== 'skip') as {\n file: SerializedFile;\n action: CommitAction['action'];\n }[]\n ).map(({ file, action }) => ({\n action,\n filePath: targetPath\n ? path.posix.join(targetPath, file.path)\n : file.path,\n encoding: 'base64',\n content: file.content.toString('base64'),\n execute_filemode: file.executable,\n }));\n\n let createBranch: boolean;\n if (actions.length) {\n createBranch = true;\n } else {\n try {\n await api.Branches.show(repoID, branchName);\n createBranch = false;\n ctx.logger.info(\n `Using existing branch ${branchName} without modification.`,\n );\n } catch (e) {\n createBranch = true;\n }\n }\n if (createBranch) {\n try {\n await api.Branches.create(repoID, branchName, String(targetBranch));\n } catch (e) {\n throw new InputError(\n `The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n if (actions.length) {\n try {\n await api.Commits.create(repoID, branchName, title, actions);\n } catch (e) {\n throw new InputError(\n `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n try {\n let mergeRequest = await api.MergeRequests.create(\n repoID,\n branchName,\n String(targetBranch),\n title,\n {\n description,\n removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,\n assigneeId,\n reviewerIds,\n },\n );\n\n if (ctx.input.assignReviewersFromApprovalRules) {\n try {\n const reviewersFromApprovalRules =\n await getReviewersFromApprovalRules(\n api,\n mergeRequest.iid,\n repoID,\n ctx,\n );\n if (reviewersFromApprovalRules.length > 0) {\n const eligibleUserIds = new Set([\n ...reviewersFromApprovalRules,\n ...(reviewerIds ?? []),\n ]);\n\n mergeRequest = await api.MergeRequests.edit(\n repoID,\n mergeRequest.iid,\n {\n reviewerIds: Array.from(eligibleUserIds),\n },\n );\n }\n } catch (e) {\n ctx.logger.warn(\n `Failed to assign reviewers from approval rules: ${getErrorMessage(\n e,\n )}.`,\n );\n }\n }\n ctx.output('projectid', repoID);\n ctx.output('targetBranchName', targetBranch);\n ctx.output('projectPath', repoID);\n ctx.output(\n 'mergeRequestUrl',\n mergeRequest.web_url ?? mergeRequest.webUrl,\n );\n } catch (e) {\n throw new InputError(\n `Merge request creation failed. ${getErrorMessage(e)}`,\n );\n }\n },\n });\n};\n"],"names":["createHash","path","getErrorMessage","createTemplateAction","examples","parseRepoUrl","createGitlabApi","resolveSafeChildPath","serializeDirectoryContents","InputError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gitlabMergeRequest.cjs.js","sources":["../../src/actions/gitlabMergeRequest.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createTemplateAction,\n parseRepoUrl,\n SerializedFile,\n serializeDirectoryContents,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n Camelize,\n CommitAction,\n ExpandedMergeRequestSchema,\n Gitlab,\n RepositoryTreeSchema,\n SimpleUserSchema,\n} from '@gitbeaker/rest';\nimport path from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { InputError } from '@backstage/errors';\nimport {\n LoggerService,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport { createGitlabApi, getErrorMessage } from './helpers';\nimport { examples } from './gitlabMergeRequest.examples';\nimport { createHash } from 'crypto';\n\nfunction computeSha256(file: SerializedFile): string {\n const hash = createHash('sha256');\n hash.update(file.content);\n return hash.digest('hex');\n}\n\nasync function getFileAction(\n fileInfo: { file: SerializedFile; targetPath?: string },\n target: { repoID: string; branch: string },\n api: InstanceType<typeof Gitlab>,\n logger: LoggerService,\n remoteFiles: RepositoryTreeSchema[],\n defaultCommitAction:\n | 'create'\n | 'delete'\n | 'update'\n | 'skip'\n | 'auto' = 'auto',\n): Promise<'create' | 'delete' | 'update' | 'skip'> {\n if (defaultCommitAction === 'auto') {\n const filePath = path.join(fileInfo.targetPath ?? '', fileInfo.file.path);\n\n if (remoteFiles?.some(remoteFile => remoteFile.path === filePath)) {\n try {\n const targetFile = await api.RepositoryFiles.show(\n target.repoID,\n filePath,\n target.branch,\n );\n if (computeSha256(fileInfo.file) === targetFile.content_sha256) {\n return 'skip';\n }\n } catch (error) {\n logger.warn(\n `Unable to retrieve detailed information for remote file ${filePath}`,\n );\n }\n return 'update';\n }\n return 'create';\n }\n return defaultCommitAction;\n}\n\nasync function getReviewersFromApprovalRules(\n api: InstanceType<typeof Gitlab>,\n mergerequestIId: number,\n repoID: string,\n ctx: any,\n): Promise<number[]> {\n try {\n // Because we don't know the code owners before the MR is created, we can't check the approval rules beforehand.\n // Getting the approval rules beforehand is very difficult, especially, because of the inheritance rules for groups.\n // Code owners take a moment to be processed and added to the approval rules after the MR is created.\n\n let mergeRequest:\n | ExpandedMergeRequestSchema\n | Camelize<ExpandedMergeRequestSchema> = await api.MergeRequests.show(\n repoID,\n mergerequestIId,\n );\n\n while (\n mergeRequest.detailed_merge_status === 'preparing' ||\n mergeRequest.detailed_merge_status === 'approvals_syncing' ||\n mergeRequest.detailed_merge_status === 'checking'\n ) {\n mergeRequest = await api.MergeRequests.show(repoID, mergeRequest.iid);\n ctx.logger.info(`${mergeRequest.detailed_merge_status}`);\n }\n\n const approvalRules = await api.MergeRequestApprovals.allApprovalRules(\n repoID,\n {\n mergerequestIId: mergeRequest.iid,\n },\n );\n\n return approvalRules\n .filter(rule => rule.eligible_approvers !== undefined)\n .map(rule => {\n return rule.eligible_approvers as SimpleUserSchema[];\n })\n .flat()\n .map(user => user.id);\n } catch (e) {\n ctx.logger.warn(\n `Failed to retrieve approval rules for MR ${mergerequestIId}: ${getErrorMessage(\n e,\n )}. Proceeding with MR creation without reviewers from approval rules.`,\n );\n return [];\n }\n}\n\n/**\n * Create a new action that creates a gitlab merge request.\n *\n * @public\n */\nexport const createPublishGitlabMergeRequestAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction<{\n repoUrl: string;\n title: string;\n description: string;\n branchName: string;\n targetBranchName?: string;\n sourcePath?: string;\n targetPath?: string;\n token?: string;\n commitAction?: 'create' | 'delete' | 'update' | 'skip' | 'auto';\n /** @deprecated projectID passed as query parameters in the repoUrl */\n projectid?: string;\n removeSourceBranch?: boolean;\n assignee?: string;\n reviewers?: string[];\n assignReviewersFromApprovalRules?: boolean;\n }>({\n id: 'publish:gitlab:merge-request',\n examples,\n schema: {\n input: {\n required: ['repoUrl', 'branchName'],\n type: 'object',\n properties: {\n repoUrl: {\n type: 'string',\n title: 'Repository Location',\n description: `\\\nAccepts the format 'gitlab.com?repo=project_name&owner=group_name' where \\\n'project_name' is the repository name and 'group_name' is a group or username`,\n },\n /** @deprecated projectID is passed as query parameters in the repoUrl */\n projectid: {\n type: 'string',\n title: 'projectid',\n description: 'Project ID/Name(slug) of the Gitlab Project',\n },\n title: {\n type: 'string',\n title: 'Merge Request Name',\n description: 'The name for the merge request',\n },\n description: {\n type: 'string',\n title: 'Merge Request Description',\n description: 'The description of the merge request',\n },\n branchName: {\n type: 'string',\n title: 'Source Branch Name',\n description: 'The source branch name of the merge request',\n },\n targetBranchName: {\n type: 'string',\n title: 'Target Branch Name',\n description: 'The target branch name of the merge request',\n },\n sourcePath: {\n type: 'string',\n title: 'Working Subdirectory',\n description: `\\\nSubdirectory of working directory to copy changes from. \\\nFor reasons of backward compatibility, any specified 'targetPath' input will \\\nbe applied in place of an absent/falsy value for this input. \\\nCircumvent this behavior using '.'`,\n },\n targetPath: {\n type: 'string',\n title: 'Repository Subdirectory',\n description: 'Subdirectory of repository to apply changes to',\n },\n token: {\n title: 'Authentication Token',\n type: 'string',\n description: 'The token to use for authorization to GitLab',\n },\n commitAction: {\n title: 'Commit action',\n type: 'string',\n enum: ['create', 'update', 'delete', 'auto'],\n description: `\\\nThe action to be used for git commit. Defaults to the custom 'auto' action provided by backstage,\nwhich uses additional API calls in order to detect whether to 'create', 'update' or 'skip' each source file.`,\n },\n removeSourceBranch: {\n title: 'Delete source branch',\n type: 'boolean',\n description:\n 'Option to delete source branch once the MR has been merged. Default: false',\n },\n assignee: {\n title: 'Merge Request Assignee',\n type: 'string',\n description: 'User this merge request will be assigned to',\n },\n reviewers: {\n title: 'Merge Request Reviewers',\n type: 'array',\n items: {\n type: 'string',\n },\n description: 'Users that will be assigned as reviewers',\n },\n assignReviewersFromApprovalRules: {\n title: 'Assign reviewers from approval rules',\n type: 'boolean',\n description:\n 'Automatically assign reviewers from the approval rules of the MR. Includes Codeowners',\n },\n },\n },\n output: {\n type: 'object',\n properties: {\n targetBranchName: {\n title: 'Target branch name of the merge request',\n type: 'string',\n },\n projectid: {\n title: 'Gitlab Project id/Name(slug)',\n type: 'string',\n },\n projectPath: {\n title: 'Gitlab Project path',\n type: 'string',\n },\n mergeRequestUrl: {\n title: 'MergeRequest(MR) URL',\n type: 'string',\n description: 'Link to the merge request in GitLab',\n },\n },\n },\n },\n async handler(ctx) {\n const {\n assignee,\n reviewers,\n branchName,\n targetBranchName,\n description,\n repoUrl,\n removeSourceBranch,\n targetPath,\n sourcePath,\n title,\n token,\n } = ctx.input;\n\n const { owner, repo, project } = parseRepoUrl(repoUrl, integrations);\n const repoID = project ? project : `${owner}/${repo}`;\n\n const api = createGitlabApi({\n integrations,\n token,\n repoUrl,\n });\n\n let assigneeId: number | undefined = undefined;\n\n if (assignee !== undefined) {\n try {\n const assigneeUser = await api.Users.all({ username: assignee });\n assigneeId = assigneeUser[0].id;\n } catch (e) {\n ctx.logger.warn(\n `Failed to find gitlab user id for ${assignee}: ${getErrorMessage(\n e,\n )}. Proceeding with MR creation without an assignee.`,\n );\n }\n }\n\n let reviewerIds: number[] | undefined = undefined; // Explicitly set to undefined. Strangely, passing an empty array to the API will result the other options being undefined also being explicity passed to the Gitlab API call (e.g. assigneeId)\n if (reviewers !== undefined) {\n reviewerIds = (\n await Promise.all(\n reviewers.map(async reviewer => {\n try {\n const reviewerUser = await api.Users.all({\n username: reviewer,\n });\n return reviewerUser[0].id;\n } catch (e) {\n ctx.logger.warn(\n `Failed to find gitlab user id for ${reviewer}: ${e}. Proceeding with MR creation without reviewer.`,\n );\n return undefined;\n }\n }),\n )\n ).filter(id => id !== undefined) as number[];\n }\n\n let fileRoot: string;\n if (sourcePath) {\n fileRoot = resolveSafeChildPath(ctx.workspacePath, sourcePath);\n } else if (targetPath) {\n // for backward compatibility\n fileRoot = resolveSafeChildPath(ctx.workspacePath, targetPath);\n } else {\n fileRoot = ctx.workspacePath;\n }\n\n const fileContents = await serializeDirectoryContents(fileRoot, {\n gitignore: true,\n });\n\n let targetBranch = targetBranchName;\n if (!targetBranch) {\n const projects = await api.Projects.show(repoID);\n const defaultBranch = projects.default_branch ?? projects.defaultBranch;\n if (typeof defaultBranch !== 'string' || !defaultBranch) {\n throw new InputError(\n `The branch creation failed. Target branch was not provided, and could not find default branch from project settings. Project: ${JSON.stringify(\n project,\n )}`,\n );\n }\n targetBranch = defaultBranch;\n }\n\n let remoteFiles: RepositoryTreeSchema[] = [];\n if ((ctx.input.commitAction ?? 'auto') === 'auto') {\n try {\n remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {\n ref: targetBranch,\n recursive: true,\n path: targetPath ?? undefined,\n });\n } catch (e) {\n ctx.logger.warn(\n `Could not retrieve the list of files for ${repoID} (branch: ${targetBranch}) : ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n const actions: CommitAction[] =\n ctx.input.commitAction === 'skip'\n ? []\n : (\n (\n await Promise.all(\n fileContents.map(async file => {\n const action = await getFileAction(\n { file, targetPath },\n { repoID, branch: targetBranch! },\n api,\n ctx.logger,\n remoteFiles,\n ctx.input.commitAction,\n );\n return { file, action };\n }),\n )\n ).filter(o => o.action !== 'skip') as {\n file: SerializedFile;\n action: CommitAction['action'];\n }[]\n ).map(({ file, action }) => ({\n action,\n filePath: targetPath\n ? path.posix.join(targetPath, file.path)\n : file.path,\n encoding: 'base64',\n content: file.content.toString('base64'),\n execute_filemode: file.executable,\n }));\n\n let createBranch: boolean;\n if (actions.length) {\n createBranch = true;\n } else {\n try {\n await api.Branches.show(repoID, branchName);\n createBranch = false;\n ctx.logger.info(\n `Using existing branch ${branchName} without modification.`,\n );\n } catch (e) {\n createBranch = true;\n }\n }\n if (createBranch) {\n try {\n await api.Branches.create(repoID, branchName, String(targetBranch));\n } catch (e) {\n throw new InputError(\n `The branch creation failed. Please check that your repo does not already contain a branch named '${branchName}'. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n await ctx.checkpoint({\n key: `commit.to.${repoID}.${branchName}`,\n fn: async () => {\n if (actions.length) {\n try {\n const commit = await api.Commits.create(\n repoID,\n branchName,\n title,\n actions,\n );\n return commit.id;\n } catch (e) {\n throw new InputError(\n `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n return null;\n },\n });\n\n const { mrId, mrWebUrl } = await ctx.checkpoint({\n key: `create.mr.${repoID}.${branchName}`,\n fn: async () => {\n try {\n const mergeRequest = await api.MergeRequests.create(\n repoID,\n branchName,\n String(targetBranch),\n title,\n {\n description,\n removeSourceBranch: removeSourceBranch\n ? removeSourceBranch\n : false,\n assigneeId,\n reviewerIds,\n },\n );\n return {\n mrId: mergeRequest.iid,\n mrWebUrl: mergeRequest.web_url ?? mergeRequest.webUrl,\n };\n } catch (e) {\n throw new InputError(\n `Merge request creation failed. ${getErrorMessage(e)}`,\n );\n }\n },\n });\n\n await ctx.checkpoint({\n key: `create.mr.assign.reviewers.${repoID}.${branchName}`,\n fn: async () => {\n if (ctx.input.assignReviewersFromApprovalRules) {\n try {\n const reviewersFromApprovalRules =\n await getReviewersFromApprovalRules(api, mrId, repoID, ctx);\n if (reviewersFromApprovalRules.length > 0) {\n const eligibleUserIds = new Set([\n ...reviewersFromApprovalRules,\n ...(reviewerIds ?? []),\n ]);\n\n const mergeRequest = await api.MergeRequests.edit(\n repoID,\n mrId,\n {\n reviewerIds: Array.from(eligibleUserIds),\n },\n );\n return {\n mrWebUrl: mergeRequest.web_url ?? mergeRequest.webUrl,\n };\n }\n } catch (e) {\n ctx.logger.warn(\n `Failed to assign reviewers from approval rules: ${getErrorMessage(\n e,\n )}.`,\n );\n }\n }\n return { mrWebUrl };\n },\n });\n\n ctx.output('projectid', repoID);\n ctx.output('targetBranchName', targetBranch);\n ctx.output('projectPath', repoID);\n ctx.output('mergeRequestUrl', mrWebUrl);\n },\n });\n};\n"],"names":["createHash","path","getErrorMessage","createTemplateAction","examples","parseRepoUrl","createGitlabApi","resolveSafeChildPath","serializeDirectoryContents","InputError"],"mappings":";;;;;;;;;;;;;;AAyCA,SAAS,cAAc,IAA8B,EAAA;AACnD,EAAM,MAAA,IAAA,GAAOA,kBAAW,QAAQ,CAAA;AAChC,EAAK,IAAA,CAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACxB,EAAO,OAAA,IAAA,CAAK,OAAO,KAAK,CAAA;AAC1B;AAEA,eAAe,cACb,QACA,EAAA,MAAA,EACA,KACA,MACA,EAAA,WAAA,EACA,sBAKa,MACqC,EAAA;AAClD,EAAA,IAAI,wBAAwB,MAAQ,EAAA;AAClC,IAAM,MAAA,QAAA,GAAWC,sBAAK,IAAK,CAAA,QAAA,CAAS,cAAc,EAAI,EAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAExE,IAAA,IAAI,aAAa,IAAK,CAAA,CAAA,UAAA,KAAc,UAAW,CAAA,IAAA,KAAS,QAAQ,CAAG,EAAA;AACjE,MAAI,IAAA;AACF,QAAM,MAAA,UAAA,GAAa,MAAM,GAAA,CAAI,eAAgB,CAAA,IAAA;AAAA,UAC3C,MAAO,CAAA,MAAA;AAAA,UACP,QAAA;AAAA,UACA,MAAO,CAAA;AAAA,SACT;AACA,QAAA,IAAI,aAAc,CAAA,QAAA,CAAS,IAAI,CAAA,KAAM,WAAW,cAAgB,EAAA;AAC9D,UAAO,OAAA,MAAA;AAAA;AACT,eACO,KAAO,EAAA;AACd,QAAO,MAAA,CAAA,IAAA;AAAA,UACL,2DAA2D,QAAQ,CAAA;AAAA,SACrE;AAAA;AAEF,MAAO,OAAA,QAAA;AAAA;AAET,IAAO,OAAA,QAAA;AAAA;AAET,EAAO,OAAA,mBAAA;AACT;AAEA,eAAe,6BACb,CAAA,GAAA,EACA,eACA,EAAA,MAAA,EACA,GACmB,EAAA;AACnB,EAAI,IAAA;AAKF,IAAI,IAAA,YAAA,GAEuC,MAAM,GAAA,CAAI,aAAc,CAAA,IAAA;AAAA,MACjE,MAAA;AAAA,MACA;AAAA,KACF;AAEA,IACE,OAAA,YAAA,CAAa,0BAA0B,WACvC,IAAA,YAAA,CAAa,0BAA0B,mBACvC,IAAA,YAAA,CAAa,0BAA0B,UACvC,EAAA;AACA,MAAA,YAAA,GAAe,MAAM,GAAI,CAAA,aAAA,CAAc,IAAK,CAAA,MAAA,EAAQ,aAAa,GAAG,CAAA;AACpE,MAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAG,EAAA,YAAA,CAAa,qBAAqB,CAAE,CAAA,CAAA;AAAA;AAGzD,IAAM,MAAA,aAAA,GAAgB,MAAM,GAAA,CAAI,qBAAsB,CAAA,gBAAA;AAAA,MACpD,MAAA;AAAA,MACA;AAAA,QACE,iBAAiB,YAAa,CAAA;AAAA;AAChC,KACF;AAEA,IAAO,OAAA,aAAA,CACJ,OAAO,CAAQ,IAAA,KAAA,IAAA,CAAK,uBAAuB,KAAS,CAAA,CAAA,CACpD,IAAI,CAAQ,IAAA,KAAA;AACX,MAAA,OAAO,IAAK,CAAA,kBAAA;AAAA,KACb,CACA,CAAA,IAAA,GACA,GAAI,CAAA,CAAA,IAAA,KAAQ,KAAK,EAAE,CAAA;AAAA,WACf,CAAG,EAAA;AACV,IAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,MACT,CAAA,yCAAA,EAA4C,eAAe,CAAK,EAAA,EAAAC,uBAAA;AAAA,QAC9D;AAAA,OACD,CAAA,oEAAA;AAAA,KACH;AACA,IAAA,OAAO,EAAC;AAAA;AAEZ;AAOa,MAAA,qCAAA,GAAwC,CAAC,OAEhD,KAAA;AACJ,EAAM,MAAA,EAAE,cAAiB,GAAA,OAAA;AAEzB,EAAA,OAAOC,yCAgBJ,CAAA;AAAA,IACD,EAAI,EAAA,8BAAA;AAAA,cACJC,oCAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,SAAA,EAAW,YAAY,CAAA;AAAA,QAClC,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,OAAS,EAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,qBAAA;AAAA,YACP,WAAa,EAAA,CAAA,sJAAA;AAAA,WAGf;AAAA;AAAA,UAEA,SAAW,EAAA;AAAA,YACT,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,WAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,KAAO,EAAA;AAAA,YACL,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,oBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,WAAa,EAAA;AAAA,YACX,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,2BAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,oBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,gBAAkB,EAAA;AAAA,YAChB,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,oBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,sBAAA;AAAA,YACP,WAAa,EAAA,CAAA,oOAAA;AAAA,WAKf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,yBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,sBAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,WAAa,EAAA;AAAA,WACf;AAAA,UACA,YAAc,EAAA;AAAA,YACZ,KAAO,EAAA,eAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,IAAM,EAAA,CAAC,QAAU,EAAA,QAAA,EAAU,UAAU,MAAM,CAAA;AAAA,YAC3C,WAAa,EAAA,CAAA;AAAA,4GAAA;AAAA,WAGf;AAAA,UACA,kBAAoB,EAAA;AAAA,YAClB,KAAO,EAAA,sBAAA;AAAA,YACP,IAAM,EAAA,SAAA;AAAA,YACN,WACE,EAAA;AAAA,WACJ;AAAA,UACA,QAAU,EAAA;AAAA,YACR,KAAO,EAAA,wBAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,WAAa,EAAA;AAAA,WACf;AAAA,UACA,SAAW,EAAA;AAAA,YACT,KAAO,EAAA,yBAAA;AAAA,YACP,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA,aACR;AAAA,YACA,WAAa,EAAA;AAAA,WACf;AAAA,UACA,gCAAkC,EAAA;AAAA,YAChC,KAAO,EAAA,sCAAA;AAAA,YACP,IAAM,EAAA,SAAA;AAAA,YACN,WACE,EAAA;AAAA;AACJ;AACF,OACF;AAAA,MACA,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,gBAAkB,EAAA;AAAA,YAChB,KAAO,EAAA,yCAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,SAAW,EAAA;AAAA,YACT,KAAO,EAAA,8BAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,WAAa,EAAA;AAAA,YACX,KAAO,EAAA,qBAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,eAAiB,EAAA;AAAA,YACf,KAAO,EAAA,sBAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,WAAa,EAAA;AAAA;AACf;AACF;AACF,KACF;AAAA,IACA,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAM,MAAA;AAAA,QACJ,QAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA,gBAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA,kBAAA;AAAA,QACA,UAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,UACE,GAAI,CAAA,KAAA;AAER,MAAA,MAAM,EAAE,KAAO,EAAA,IAAA,EAAM,SAAY,GAAAC,iCAAA,CAAa,SAAS,YAAY,CAAA;AACnE,MAAA,MAAM,SAAS,OAAU,GAAA,OAAA,GAAU,CAAG,EAAA,KAAK,IAAI,IAAI,CAAA,CAAA;AAEnD,MAAA,MAAM,MAAMC,uBAAgB,CAAA;AAAA,QAC1B,YAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,IAAI,UAAiC,GAAA,KAAA,CAAA;AAErC,MAAA,IAAI,aAAa,KAAW,CAAA,EAAA;AAC1B,QAAI,IAAA;AACF,UAAM,MAAA,YAAA,GAAe,MAAM,GAAI,CAAA,KAAA,CAAM,IAAI,EAAE,QAAA,EAAU,UAAU,CAAA;AAC/D,UAAa,UAAA,GAAA,YAAA,CAAa,CAAC,CAAE,CAAA,EAAA;AAAA,iBACtB,CAAG,EAAA;AACV,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,YACT,CAAA,kCAAA,EAAqC,QAAQ,CAAK,EAAA,EAAAJ,uBAAA;AAAA,cAChD;AAAA,aACD,CAAA,kDAAA;AAAA,WACH;AAAA;AACF;AAGF,MAAA,IAAI,WAAoC,GAAA,KAAA,CAAA;AACxC,MAAA,IAAI,cAAc,KAAW,CAAA,EAAA;AAC3B,QAAA,WAAA,GAAA,CACE,MAAM,OAAQ,CAAA,GAAA;AAAA,UACZ,SAAA,CAAU,GAAI,CAAA,OAAM,QAAY,KAAA;AAC9B,YAAI,IAAA;AACF,cAAA,MAAM,YAAe,GAAA,MAAM,GAAI,CAAA,KAAA,CAAM,GAAI,CAAA;AAAA,gBACvC,QAAU,EAAA;AAAA,eACX,CAAA;AACD,cAAO,OAAA,YAAA,CAAa,CAAC,CAAE,CAAA,EAAA;AAAA,qBAChB,CAAG,EAAA;AACV,cAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,gBACT,CAAA,kCAAA,EAAqC,QAAQ,CAAA,EAAA,EAAK,CAAC,CAAA,+CAAA;AAAA,eACrD;AACA,cAAO,OAAA,KAAA,CAAA;AAAA;AACT,WACD;AAAA,SAEH,EAAA,MAAA,CAAO,CAAM,EAAA,KAAA,EAAA,KAAO,KAAS,CAAA,CAAA;AAAA;AAGjC,MAAI,IAAA,QAAA;AACJ,MAAA,IAAI,UAAY,EAAA;AACd,QAAW,QAAA,GAAAK,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,UAAU,CAAA;AAAA,iBACpD,UAAY,EAAA;AAErB,QAAW,QAAA,GAAAA,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,UAAU,CAAA;AAAA,OACxD,MAAA;AACL,QAAA,QAAA,GAAW,GAAI,CAAA,aAAA;AAAA;AAGjB,MAAM,MAAA,YAAA,GAAe,MAAMC,+CAAA,CAA2B,QAAU,EAAA;AAAA,QAC9D,SAAW,EAAA;AAAA,OACZ,CAAA;AAED,MAAA,IAAI,YAAe,GAAA,gBAAA;AACnB,MAAA,IAAI,CAAC,YAAc,EAAA;AACjB,QAAA,MAAM,QAAW,GAAA,MAAM,GAAI,CAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAC/C,QAAM,MAAA,aAAA,GAAgB,QAAS,CAAA,cAAA,IAAkB,QAAS,CAAA,aAAA;AAC1D,QAAA,IAAI,OAAO,aAAA,KAAkB,QAAY,IAAA,CAAC,aAAe,EAAA;AACvD,UAAA,MAAM,IAAIC,iBAAA;AAAA,YACR,iIAAiI,IAAK,CAAA,SAAA;AAAA,cACpI;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AAEF,QAAe,YAAA,GAAA,aAAA;AAAA;AAGjB,MAAA,IAAI,cAAsC,EAAC;AAC3C,MAAA,IAAA,CAAK,GAAI,CAAA,KAAA,CAAM,YAAgB,IAAA,MAAA,MAAY,MAAQ,EAAA;AACjD,QAAI,IAAA;AACF,UAAA,WAAA,GAAc,MAAM,GAAA,CAAI,YAAa,CAAA,kBAAA,CAAmB,MAAQ,EAAA;AAAA,YAC9D,GAAK,EAAA,YAAA;AAAA,YACL,SAAW,EAAA,IAAA;AAAA,YACX,MAAM,UAAc,IAAA,KAAA;AAAA,WACrB,CAAA;AAAA,iBACM,CAAG,EAAA;AACV,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,YACT,CAA4C,yCAAA,EAAA,MAAM,CAAa,UAAA,EAAA,YAAY,CAAO,IAAA,EAAAP,uBAAA;AAAA,cAChF;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAEF,MAAM,MAAA,OAAA,GACJ,IAAI,KAAM,CAAA,YAAA,KAAiB,SACvB,EAAC,GAAA,CAGG,MAAM,OAAQ,CAAA,GAAA;AAAA,QACZ,YAAA,CAAa,GAAI,CAAA,OAAM,IAAQ,KAAA;AAC7B,UAAA,MAAM,SAAS,MAAM,aAAA;AAAA,YACnB,EAAE,MAAM,UAAW,EAAA;AAAA,YACnB,EAAE,MAAQ,EAAA,MAAA,EAAQ,YAAc,EAAA;AAAA,YAChC,GAAA;AAAA,YACA,GAAI,CAAA,MAAA;AAAA,YACJ,WAAA;AAAA,YACA,IAAI,KAAM,CAAA;AAAA,WACZ;AACA,UAAO,OAAA,EAAE,MAAM,MAAO,EAAA;AAAA,SACvB;AAAA,OAEH,EAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,CAAE,MAAW,KAAA,MAAM,CAIjC,CAAA,GAAA,CAAI,CAAC,EAAE,IAAM,EAAA,MAAA,EAAc,MAAA;AAAA,QAC3B,MAAA;AAAA,QACA,QAAA,EAAU,aACND,qBAAK,CAAA,KAAA,CAAM,KAAK,UAAY,EAAA,IAAA,CAAK,IAAI,CAAA,GACrC,IAAK,CAAA,IAAA;AAAA,QACT,QAAU,EAAA,QAAA;AAAA,QACV,OAAS,EAAA,IAAA,CAAK,OAAQ,CAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,QACvC,kBAAkB,IAAK,CAAA;AAAA,OACvB,CAAA,CAAA;AAER,MAAI,IAAA,YAAA;AACJ,MAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,QAAe,YAAA,GAAA,IAAA;AAAA,OACV,MAAA;AACL,QAAI,IAAA;AACF,UAAA,MAAM,GAAI,CAAA,QAAA,CAAS,IAAK,CAAA,MAAA,EAAQ,UAAU,CAAA;AAC1C,UAAe,YAAA,GAAA,KAAA;AACf,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,YACT,yBAAyB,UAAU,CAAA,sBAAA;AAAA,WACrC;AAAA,iBACO,CAAG,EAAA;AACV,UAAe,YAAA,GAAA,IAAA;AAAA;AACjB;AAEF,MAAA,IAAI,YAAc,EAAA;AAChB,QAAI,IAAA;AACF,UAAA,MAAM,IAAI,QAAS,CAAA,MAAA,CAAO,QAAQ,UAAY,EAAA,MAAA,CAAO,YAAY,CAAC,CAAA;AAAA,iBAC3D,CAAG,EAAA;AACV,UAAA,MAAM,IAAIQ,iBAAA;AAAA,YACR,CAAA,iGAAA,EAAoG,UAAU,CAAM,GAAA,EAAAP,uBAAA;AAAA,cAClH;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAEF,MAAA,MAAM,IAAI,UAAW,CAAA;AAAA,QACnB,GAAK,EAAA,CAAA,UAAA,EAAa,MAAM,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,QACtC,IAAI,YAAY;AACd,UAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,YAAI,IAAA;AACF,cAAM,MAAA,MAAA,GAAS,MAAM,GAAA,CAAI,OAAQ,CAAA,MAAA;AAAA,gBAC/B,MAAA;AAAA,gBACA,UAAA;AAAA,gBACA,KAAA;AAAA,gBACA;AAAA,eACF;AACA,cAAA,OAAO,MAAO,CAAA,EAAA;AAAA,qBACP,CAAG,EAAA;AACV,cAAA,MAAM,IAAIO,iBAAA;AAAA,gBACR,CAAA,0BAAA,EAA6B,UAAU,CAAwF,qFAAA,EAAAP,uBAAA;AAAA,kBAC7H;AAAA,iBACD,CAAA;AAAA,eACH;AAAA;AACF;AAEF,UAAO,OAAA,IAAA;AAAA;AACT,OACD,CAAA;AAED,MAAA,MAAM,EAAE,IAAM,EAAA,QAAA,EAAa,GAAA,MAAM,IAAI,UAAW,CAAA;AAAA,QAC9C,GAAK,EAAA,CAAA,UAAA,EAAa,MAAM,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,QACtC,IAAI,YAAY;AACd,UAAI,IAAA;AACF,YAAM,MAAA,YAAA,GAAe,MAAM,GAAA,CAAI,aAAc,CAAA,MAAA;AAAA,cAC3C,MAAA;AAAA,cACA,UAAA;AAAA,cACA,OAAO,YAAY,CAAA;AAAA,cACnB,KAAA;AAAA,cACA;AAAA,gBACE,WAAA;AAAA,gBACA,kBAAA,EAAoB,qBAChB,kBACA,GAAA,KAAA;AAAA,gBACJ,UAAA;AAAA,gBACA;AAAA;AACF,aACF;AACA,YAAO,OAAA;AAAA,cACL,MAAM,YAAa,CAAA,GAAA;AAAA,cACnB,QAAA,EAAU,YAAa,CAAA,OAAA,IAAW,YAAa,CAAA;AAAA,aACjD;AAAA,mBACO,CAAG,EAAA;AACV,YAAA,MAAM,IAAIO,iBAAA;AAAA,cACR,CAAA,+BAAA,EAAkCP,uBAAgB,CAAA,CAAC,CAAC,CAAA;AAAA,aACtD;AAAA;AACF;AACF,OACD,CAAA;AAED,MAAA,MAAM,IAAI,UAAW,CAAA;AAAA,QACnB,GAAK,EAAA,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,QACvD,IAAI,YAAY;AACd,UAAI,IAAA,GAAA,CAAI,MAAM,gCAAkC,EAAA;AAC9C,YAAI,IAAA;AACF,cAAA,MAAM,6BACJ,MAAM,6BAAA,CAA8B,GAAK,EAAA,IAAA,EAAM,QAAQ,GAAG,CAAA;AAC5D,cAAI,IAAA,0BAAA,CAA2B,SAAS,CAAG,EAAA;AACzC,gBAAM,MAAA,eAAA,uBAAsB,GAAI,CAAA;AAAA,kBAC9B,GAAG,0BAAA;AAAA,kBACH,GAAI,eAAe;AAAC,iBACrB,CAAA;AAED,gBAAM,MAAA,YAAA,GAAe,MAAM,GAAA,CAAI,aAAc,CAAA,IAAA;AAAA,kBAC3C,MAAA;AAAA,kBACA,IAAA;AAAA,kBACA;AAAA,oBACE,WAAA,EAAa,KAAM,CAAA,IAAA,CAAK,eAAe;AAAA;AACzC,iBACF;AACA,gBAAO,OAAA;AAAA,kBACL,QAAA,EAAU,YAAa,CAAA,OAAA,IAAW,YAAa,CAAA;AAAA,iBACjD;AAAA;AACF,qBACO,CAAG,EAAA;AACV,cAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,gBACT,CAAmD,gDAAA,EAAAA,uBAAA;AAAA,kBACjD;AAAA,iBACD,CAAA,CAAA;AAAA,eACH;AAAA;AACF;AAEF,UAAA,OAAO,EAAE,QAAS,EAAA;AAAA;AACpB,OACD,CAAA;AAED,MAAI,GAAA,CAAA,MAAA,CAAO,aAAa,MAAM,CAAA;AAC9B,MAAI,GAAA,CAAA,MAAA,CAAO,oBAAoB,YAAY,CAAA;AAC3C,MAAI,GAAA,CAAA,MAAA,CAAO,eAAe,MAAM,CAAA;AAChC,MAAI,GAAA,CAAA,MAAA,CAAO,mBAAmB,QAAQ,CAAA;AAAA;AACxC,GACD,CAAA;AACH;;;;"}
|
|
@@ -114,7 +114,7 @@ const createGitlabRepoPushAction = (options) => {
|
|
|
114
114
|
await api.Branches.show(repoID, branchName);
|
|
115
115
|
branchExists = true;
|
|
116
116
|
} catch (e) {
|
|
117
|
-
if (e.response?.
|
|
117
|
+
if (e.cause?.response?.status !== 404) {
|
|
118
118
|
throw new errors.InputError(
|
|
119
119
|
`Failed to check status of branch '${branchName}'. Please make sure that branch already exists or Backstage has permissions to create one. ${helpers.getErrorMessage(
|
|
120
120
|
e
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlabRepoPush.cjs.js","sources":["../../src/actions/gitlabRepoPush.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createTemplateAction,\n parseRepoUrl,\n serializeDirectoryContents,\n} from '@backstage/plugin-scaffolder-node';\nimport { CommitAction } from '@gitbeaker/rest';\nimport path from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { createGitlabApi, getErrorMessage } from './helpers';\nimport { examples } from './gitlabRepoPush.examples';\n\n/**\n * Create a new action that commits into a gitlab repository.\n *\n * @public\n */\nexport const createGitlabRepoPushAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction<{\n repoUrl: string;\n branchName: string;\n commitMessage: string;\n sourcePath?: string;\n targetPath?: string;\n token?: string;\n commitAction?: 'create' | 'delete' | 'update';\n }>({\n id: 'gitlab:repo:push',\n examples,\n schema: {\n input: {\n required: ['repoUrl', 'branchName', 'commitMessage'],\n type: 'object',\n properties: {\n repoUrl: {\n type: 'string',\n title: 'Repository Location',\n 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`,\n },\n branchName: {\n type: 'string',\n title: 'Source Branch Name',\n description: 'The branch name for the commit',\n },\n commitMessage: {\n type: 'string',\n title: 'Commit Message',\n description: `The commit message`,\n },\n sourcePath: {\n type: 'string',\n title: 'Working Subdirectory',\n description:\n 'Subdirectory of working directory to copy changes from',\n },\n targetPath: {\n type: 'string',\n title: 'Repository Subdirectory',\n description: 'Subdirectory of repository to apply changes to',\n },\n token: {\n title: 'Authentication Token',\n type: 'string',\n description: 'The token to use for authorization to GitLab',\n },\n commitAction: {\n title: 'Commit action',\n type: 'string',\n enum: ['create', 'update', 'delete'],\n description:\n 'The action to be used for git commit. Defaults to create.',\n },\n },\n },\n output: {\n type: 'object',\n properties: {\n projectid: {\n title: 'Gitlab Project id/Name(slug)',\n type: 'string',\n },\n projectPath: {\n title: 'Gitlab Project path',\n type: 'string',\n },\n commitHash: {\n title: 'The git commit hash of the commit',\n type: 'string',\n },\n },\n },\n },\n async handler(ctx) {\n const {\n branchName,\n repoUrl,\n targetPath,\n sourcePath,\n token,\n commitAction,\n } = ctx.input;\n\n const { owner, repo, project } = parseRepoUrl(repoUrl, integrations);\n const repoID = project ? project : `${owner}/${repo}`;\n\n const api = createGitlabApi({\n integrations,\n token,\n repoUrl,\n });\n\n let fileRoot: string;\n if (sourcePath) {\n fileRoot = resolveSafeChildPath(ctx.workspacePath, sourcePath);\n } else {\n fileRoot = ctx.workspacePath;\n }\n\n const fileContents = await serializeDirectoryContents(fileRoot, {\n gitignore: true,\n });\n\n const actions: CommitAction[] = fileContents.map(file => ({\n action: commitAction ?? 'create',\n filePath: targetPath\n ? path.posix.join(targetPath, file.path)\n : file.path,\n encoding: 'base64',\n content: file.content.toString('base64'),\n execute_filemode: file.executable,\n }));\n\n let branchExists = false;\n try {\n await api.Branches.show(repoID, branchName);\n branchExists = true;\n } catch (e: any) {\n if (e.response?.statusCode !== 404) {\n throw new InputError(\n `Failed to check status of branch '${branchName}'. Please make sure that branch already exists or Backstage has permissions to create one. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n\n if (!branchExists) {\n // create a branch using the default branch as ref\n try {\n const projects = await api.Projects.show(repoID);\n const { default_branch: defaultBranch } = projects;\n await api.Branches.create(repoID, branchName, String(defaultBranch));\n } catch (e) {\n throw new InputError(\n `The branch '${branchName}' was not found and creation failed with error. Please make sure that branch already exists or Backstage has permissions to create one. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n\n try {\n const commit = await api.Commits.create(\n repoID,\n branchName,\n ctx.input.commitMessage,\n actions,\n );\n ctx.output('projectid', repoID);\n ctx.output('projectPath', repoID);\n ctx.output('commitHash', commit.id);\n } catch (e) {\n throw new InputError(\n `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${getErrorMessage(\n e,\n )}`,\n );\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","parseRepoUrl","createGitlabApi","resolveSafeChildPath","serializeDirectoryContents","path","InputError","getErrorMessage"],"mappings":";;;;;;;;;;;;;AAkCa,MAAA,0BAAA,GAA6B,CAAC,OAErC,KAAA;AACJ,EAAM,MAAA,EAAE,cAAiB,GAAA,OAAA;AAEzB,EAAA,OAAOA,yCAQJ,CAAA;AAAA,IACD,EAAI,EAAA,kBAAA;AAAA,cACJC,gCAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAU,EAAA,CAAC,SAAW,EAAA,YAAA,EAAc,eAAe,CAAA;AAAA,QACnD,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,OAAS,EAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,qBAAA;AAAA,YACP,WAAa,EAAA,CAAA,sJAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,oBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,aAAe,EAAA;AAAA,YACb,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,gBAAA;AAAA,YACP,WAAa,EAAA,CAAA,kBAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,sBAAA;AAAA,YACP,WACE,EAAA;AAAA,WACJ;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,yBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,sBAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,WAAa,EAAA;AAAA,WACf;AAAA,UACA,YAAc,EAAA;AAAA,YACZ,KAAO,EAAA,eAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,IAAM,EAAA,CAAC,QAAU,EAAA,QAAA,EAAU,QAAQ,CAAA;AAAA,YACnC,WACE,EAAA;AAAA;AACJ;AACF,OACF;AAAA,MACA,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,SAAW,EAAA;AAAA,YACT,KAAO,EAAA,8BAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,WAAa,EAAA;AAAA,YACX,KAAO,EAAA,qBAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,UAAY,EAAA;AAAA,YACV,KAAO,EAAA,mCAAA;AAAA,YACP,IAAM,EAAA;AAAA;AACR;AACF;AACF,KACF;AAAA,IACA,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAM,MAAA;AAAA,QACJ,UAAA;AAAA,QACA,OAAA;AAAA,QACA,UAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,UACE,GAAI,CAAA,KAAA;AAER,MAAA,MAAM,EAAE,KAAO,EAAA,IAAA,EAAM,SAAY,GAAAC,iCAAA,CAAa,SAAS,YAAY,CAAA;AACnE,MAAA,MAAM,SAAS,OAAU,GAAA,OAAA,GAAU,CAAG,EAAA,KAAK,IAAI,IAAI,CAAA,CAAA;AAEnD,MAAA,MAAM,MAAMC,uBAAgB,CAAA;AAAA,QAC1B,YAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAI,IAAA,QAAA;AACJ,MAAA,IAAI,UAAY,EAAA;AACd,QAAW,QAAA,GAAAC,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,UAAU,CAAA;AAAA,OACxD,MAAA;AACL,QAAA,QAAA,GAAW,GAAI,CAAA,aAAA;AAAA;AAGjB,MAAM,MAAA,YAAA,GAAe,MAAMC,+CAAA,CAA2B,QAAU,EAAA;AAAA,QAC9D,SAAW,EAAA;AAAA,OACZ,CAAA;AAED,MAAM,MAAA,OAAA,GAA0B,YAAa,CAAA,GAAA,CAAI,CAAS,IAAA,MAAA;AAAA,QACxD,QAAQ,YAAgB,IAAA,QAAA;AAAA,QACxB,QAAA,EAAU,aACNC,qBAAK,CAAA,KAAA,CAAM,KAAK,UAAY,EAAA,IAAA,CAAK,IAAI,CAAA,GACrC,IAAK,CAAA,IAAA;AAAA,QACT,QAAU,EAAA,QAAA;AAAA,QACV,OAAS,EAAA,IAAA,CAAK,OAAQ,CAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,QACvC,kBAAkB,IAAK,CAAA;AAAA,OACvB,CAAA,CAAA;AAEF,MAAA,IAAI,YAAe,GAAA,KAAA;AACnB,MAAI,IAAA;AACF,QAAA,MAAM,GAAI,CAAA,QAAA,CAAS,IAAK,CAAA,MAAA,EAAQ,UAAU,CAAA;AAC1C,QAAe,YAAA,GAAA,IAAA;AAAA,eACR,CAAQ,EAAA;AACf,QAAI,IAAA,CAAA,CAAE,QAAU,EAAA,UAAA,KAAe,GAAK,EAAA;AAClC,UAAA,MAAM,IAAIC,iBAAA;AAAA,YACR,CAAA,kCAAA,EAAqC,UAAU,CAA8F,2FAAA,EAAAC,uBAAA;AAAA,cAC3I;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAGF,MAAA,IAAI,CAAC,YAAc,EAAA;AAEjB,QAAI,IAAA;AACF,UAAA,MAAM,QAAW,GAAA,MAAM,GAAI,CAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAC/C,UAAM,MAAA,EAAE,cAAgB,EAAA,aAAA,EAAkB,GAAA,QAAA;AAC1C,UAAA,MAAM,IAAI,QAAS,CAAA,MAAA,CAAO,QAAQ,UAAY,EAAA,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,iBAC5D,CAAG,EAAA;AACV,UAAA,MAAM,IAAID,iBAAA;AAAA,YACR,CAAA,YAAA,EAAe,UAAU,CAA2I,wIAAA,EAAAC,uBAAA;AAAA,cAClK;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAGF,MAAI,IAAA;AACF,QAAM,MAAA,MAAA,GAAS,MAAM,GAAA,CAAI,OAAQ,CAAA,MAAA;AAAA,UAC/B,MAAA;AAAA,UACA,UAAA;AAAA,UACA,IAAI,KAAM,CAAA,aAAA;AAAA,UACV;AAAA,SACF;AACA,QAAI,GAAA,CAAA,MAAA,CAAO,aAAa,MAAM,CAAA;AAC9B,QAAI,GAAA,CAAA,MAAA,CAAO,eAAe,MAAM,CAAA;AAChC,QAAI,GAAA,CAAA,MAAA,CAAO,YAAc,EAAA,MAAA,CAAO,EAAE,CAAA;AAAA,eAC3B,CAAG,EAAA;AACV,QAAA,MAAM,IAAID,iBAAA;AAAA,UACR,CAAA,0BAAA,EAA6B,UAAU,CAAwF,qFAAA,EAAAC,uBAAA;AAAA,YAC7H;AAAA,WACD,CAAA;AAAA,SACH;AAAA;AACF;AACF,GACD,CAAA;AACH;;;;"}
|
|
1
|
+
{"version":3,"file":"gitlabRepoPush.cjs.js","sources":["../../src/actions/gitlabRepoPush.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createTemplateAction,\n parseRepoUrl,\n serializeDirectoryContents,\n} from '@backstage/plugin-scaffolder-node';\nimport { CommitAction } from '@gitbeaker/rest';\nimport path from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { createGitlabApi, getErrorMessage } from './helpers';\nimport { examples } from './gitlabRepoPush.examples';\n\n/**\n * Create a new action that commits into a gitlab repository.\n *\n * @public\n */\nexport const createGitlabRepoPushAction = (options: {\n integrations: ScmIntegrationRegistry;\n}) => {\n const { integrations } = options;\n\n return createTemplateAction<{\n repoUrl: string;\n branchName: string;\n commitMessage: string;\n sourcePath?: string;\n targetPath?: string;\n token?: string;\n commitAction?: 'create' | 'delete' | 'update';\n }>({\n id: 'gitlab:repo:push',\n examples,\n schema: {\n input: {\n required: ['repoUrl', 'branchName', 'commitMessage'],\n type: 'object',\n properties: {\n repoUrl: {\n type: 'string',\n title: 'Repository Location',\n 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`,\n },\n branchName: {\n type: 'string',\n title: 'Source Branch Name',\n description: 'The branch name for the commit',\n },\n commitMessage: {\n type: 'string',\n title: 'Commit Message',\n description: `The commit message`,\n },\n sourcePath: {\n type: 'string',\n title: 'Working Subdirectory',\n description:\n 'Subdirectory of working directory to copy changes from',\n },\n targetPath: {\n type: 'string',\n title: 'Repository Subdirectory',\n description: 'Subdirectory of repository to apply changes to',\n },\n token: {\n title: 'Authentication Token',\n type: 'string',\n description: 'The token to use for authorization to GitLab',\n },\n commitAction: {\n title: 'Commit action',\n type: 'string',\n enum: ['create', 'update', 'delete'],\n description:\n 'The action to be used for git commit. Defaults to create.',\n },\n },\n },\n output: {\n type: 'object',\n properties: {\n projectid: {\n title: 'Gitlab Project id/Name(slug)',\n type: 'string',\n },\n projectPath: {\n title: 'Gitlab Project path',\n type: 'string',\n },\n commitHash: {\n title: 'The git commit hash of the commit',\n type: 'string',\n },\n },\n },\n },\n async handler(ctx) {\n const {\n branchName,\n repoUrl,\n targetPath,\n sourcePath,\n token,\n commitAction,\n } = ctx.input;\n\n const { owner, repo, project } = parseRepoUrl(repoUrl, integrations);\n const repoID = project ? project : `${owner}/${repo}`;\n\n const api = createGitlabApi({\n integrations,\n token,\n repoUrl,\n });\n\n let fileRoot: string;\n if (sourcePath) {\n fileRoot = resolveSafeChildPath(ctx.workspacePath, sourcePath);\n } else {\n fileRoot = ctx.workspacePath;\n }\n\n const fileContents = await serializeDirectoryContents(fileRoot, {\n gitignore: true,\n });\n\n const actions: CommitAction[] = fileContents.map(file => ({\n action: commitAction ?? 'create',\n filePath: targetPath\n ? path.posix.join(targetPath, file.path)\n : file.path,\n encoding: 'base64',\n content: file.content.toString('base64'),\n execute_filemode: file.executable,\n }));\n\n let branchExists = false;\n try {\n await api.Branches.show(repoID, branchName);\n branchExists = true;\n } catch (e: any) {\n if (e.cause?.response?.status !== 404) {\n throw new InputError(\n `Failed to check status of branch '${branchName}'. Please make sure that branch already exists or Backstage has permissions to create one. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n\n if (!branchExists) {\n // create a branch using the default branch as ref\n try {\n const projects = await api.Projects.show(repoID);\n const { default_branch: defaultBranch } = projects;\n await api.Branches.create(repoID, branchName, String(defaultBranch));\n } catch (e) {\n throw new InputError(\n `The branch '${branchName}' was not found and creation failed with error. Please make sure that branch already exists or Backstage has permissions to create one. ${getErrorMessage(\n e,\n )}`,\n );\n }\n }\n\n try {\n const commit = await api.Commits.create(\n repoID,\n branchName,\n ctx.input.commitMessage,\n actions,\n );\n ctx.output('projectid', repoID);\n ctx.output('projectPath', repoID);\n ctx.output('commitHash', commit.id);\n } catch (e) {\n throw new InputError(\n `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${getErrorMessage(\n e,\n )}`,\n );\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","parseRepoUrl","createGitlabApi","resolveSafeChildPath","serializeDirectoryContents","path","InputError","getErrorMessage"],"mappings":";;;;;;;;;;;;;AAkCa,MAAA,0BAAA,GAA6B,CAAC,OAErC,KAAA;AACJ,EAAM,MAAA,EAAE,cAAiB,GAAA,OAAA;AAEzB,EAAA,OAAOA,yCAQJ,CAAA;AAAA,IACD,EAAI,EAAA,kBAAA;AAAA,cACJC,gCAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAU,EAAA,CAAC,SAAW,EAAA,YAAA,EAAc,eAAe,CAAA;AAAA,QACnD,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,OAAS,EAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,qBAAA;AAAA,YACP,WAAa,EAAA,CAAA,sJAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,oBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,aAAe,EAAA;AAAA,YACb,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,gBAAA;AAAA,YACP,WAAa,EAAA,CAAA,kBAAA;AAAA,WACf;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,sBAAA;AAAA,YACP,WACE,EAAA;AAAA,WACJ;AAAA,UACA,UAAY,EAAA;AAAA,YACV,IAAM,EAAA,QAAA;AAAA,YACN,KAAO,EAAA,yBAAA;AAAA,YACP,WAAa,EAAA;AAAA,WACf;AAAA,UACA,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,sBAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,WAAa,EAAA;AAAA,WACf;AAAA,UACA,YAAc,EAAA;AAAA,YACZ,KAAO,EAAA,eAAA;AAAA,YACP,IAAM,EAAA,QAAA;AAAA,YACN,IAAM,EAAA,CAAC,QAAU,EAAA,QAAA,EAAU,QAAQ,CAAA;AAAA,YACnC,WACE,EAAA;AAAA;AACJ;AACF,OACF;AAAA,MACA,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,SAAW,EAAA;AAAA,YACT,KAAO,EAAA,8BAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,WAAa,EAAA;AAAA,YACX,KAAO,EAAA,qBAAA;AAAA,YACP,IAAM,EAAA;AAAA,WACR;AAAA,UACA,UAAY,EAAA;AAAA,YACV,KAAO,EAAA,mCAAA;AAAA,YACP,IAAM,EAAA;AAAA;AACR;AACF;AACF,KACF;AAAA,IACA,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAM,MAAA;AAAA,QACJ,UAAA;AAAA,QACA,OAAA;AAAA,QACA,UAAA;AAAA,QACA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,UACE,GAAI,CAAA,KAAA;AAER,MAAA,MAAM,EAAE,KAAO,EAAA,IAAA,EAAM,SAAY,GAAAC,iCAAA,CAAa,SAAS,YAAY,CAAA;AACnE,MAAA,MAAM,SAAS,OAAU,GAAA,OAAA,GAAU,CAAG,EAAA,KAAK,IAAI,IAAI,CAAA,CAAA;AAEnD,MAAA,MAAM,MAAMC,uBAAgB,CAAA;AAAA,QAC1B,YAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAI,IAAA,QAAA;AACJ,MAAA,IAAI,UAAY,EAAA;AACd,QAAW,QAAA,GAAAC,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,UAAU,CAAA;AAAA,OACxD,MAAA;AACL,QAAA,QAAA,GAAW,GAAI,CAAA,aAAA;AAAA;AAGjB,MAAM,MAAA,YAAA,GAAe,MAAMC,+CAAA,CAA2B,QAAU,EAAA;AAAA,QAC9D,SAAW,EAAA;AAAA,OACZ,CAAA;AAED,MAAM,MAAA,OAAA,GAA0B,YAAa,CAAA,GAAA,CAAI,CAAS,IAAA,MAAA;AAAA,QACxD,QAAQ,YAAgB,IAAA,QAAA;AAAA,QACxB,QAAA,EAAU,aACNC,qBAAK,CAAA,KAAA,CAAM,KAAK,UAAY,EAAA,IAAA,CAAK,IAAI,CAAA,GACrC,IAAK,CAAA,IAAA;AAAA,QACT,QAAU,EAAA,QAAA;AAAA,QACV,OAAS,EAAA,IAAA,CAAK,OAAQ,CAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,QACvC,kBAAkB,IAAK,CAAA;AAAA,OACvB,CAAA,CAAA;AAEF,MAAA,IAAI,YAAe,GAAA,KAAA;AACnB,MAAI,IAAA;AACF,QAAA,MAAM,GAAI,CAAA,QAAA,CAAS,IAAK,CAAA,MAAA,EAAQ,UAAU,CAAA;AAC1C,QAAe,YAAA,GAAA,IAAA;AAAA,eACR,CAAQ,EAAA;AACf,QAAA,IAAI,CAAE,CAAA,KAAA,EAAO,QAAU,EAAA,MAAA,KAAW,GAAK,EAAA;AACrC,UAAA,MAAM,IAAIC,iBAAA;AAAA,YACR,CAAA,kCAAA,EAAqC,UAAU,CAA8F,2FAAA,EAAAC,uBAAA;AAAA,cAC3I;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAGF,MAAA,IAAI,CAAC,YAAc,EAAA;AAEjB,QAAI,IAAA;AACF,UAAA,MAAM,QAAW,GAAA,MAAM,GAAI,CAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAC/C,UAAM,MAAA,EAAE,cAAgB,EAAA,aAAA,EAAkB,GAAA,QAAA;AAC1C,UAAA,MAAM,IAAI,QAAS,CAAA,MAAA,CAAO,QAAQ,UAAY,EAAA,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,iBAC5D,CAAG,EAAA;AACV,UAAA,MAAM,IAAID,iBAAA;AAAA,YACR,CAAA,YAAA,EAAe,UAAU,CAA2I,wIAAA,EAAAC,uBAAA;AAAA,cAClK;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAGF,MAAI,IAAA;AACF,QAAM,MAAA,MAAA,GAAS,MAAM,GAAA,CAAI,OAAQ,CAAA,MAAA;AAAA,UAC/B,MAAA;AAAA,UACA,UAAA;AAAA,UACA,IAAI,KAAM,CAAA,aAAA;AAAA,UACV;AAAA,SACF;AACA,QAAI,GAAA,CAAA,MAAA,CAAO,aAAa,MAAM,CAAA;AAC9B,QAAI,GAAA,CAAA,MAAA,CAAO,eAAe,MAAM,CAAA;AAChC,QAAI,GAAA,CAAA,MAAA,CAAO,YAAc,EAAA,MAAA,CAAO,EAAE,CAAA;AAAA,eAC3B,CAAG,EAAA;AACV,QAAA,MAAM,IAAID,iBAAA;AAAA,UACR,CAAA,0BAAA,EAA6B,UAAU,CAAwF,qFAAA,EAAAC,uBAAA;AAAA,YAC7H;AAAA,WACD,CAAA;AAAA,SACH;AAAA;AACF;AACF,GACD,CAAA;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-scaffolder-backend-module-gitlab",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1-next.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "backend-plugin-module",
|
|
6
6
|
"pluginId": "scaffolder",
|
|
@@ -54,11 +54,11 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@backstage/backend-common": "^0.25.0",
|
|
57
|
-
"@backstage/backend-plugin-api": "1.2.
|
|
57
|
+
"@backstage/backend-plugin-api": "1.2.1-next.0",
|
|
58
58
|
"@backstage/config": "1.3.2",
|
|
59
59
|
"@backstage/errors": "1.2.7",
|
|
60
60
|
"@backstage/integration": "1.16.1",
|
|
61
|
-
"@backstage/plugin-scaffolder-node": "0.7.
|
|
61
|
+
"@backstage/plugin-scaffolder-node": "0.7.1-next.0",
|
|
62
62
|
"@gitbeaker/rest": "^41.2.0",
|
|
63
63
|
"luxon": "^3.0.0",
|
|
64
64
|
"winston": "^3.2.1",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"zod": "^3.22.4"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@backstage/backend-test-utils": "1.3.
|
|
70
|
-
"@backstage/cli": "0.30.0
|
|
71
|
-
"@backstage/core-app-api": "1.15.5
|
|
72
|
-
"@backstage/plugin-scaffolder-node-test-utils": "0.1.
|
|
69
|
+
"@backstage/backend-test-utils": "1.3.1-next.0",
|
|
70
|
+
"@backstage/cli": "0.30.0",
|
|
71
|
+
"@backstage/core-app-api": "1.15.5",
|
|
72
|
+
"@backstage/plugin-scaffolder-node-test-utils": "0.1.20-next.0"
|
|
73
73
|
}
|
|
74
74
|
}
|