@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 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 = (await api.Groups.create(
59
- name,
60
- slug,
61
- parentId ? {
62
- parentId
63
- } : {}
64
- ))?.id;
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 name,\n slug,\n parentId\n ? {\n parentId: parentId,\n }\n : {},\n )\n )?.id;\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":";;;;;;;;AA6Ba,MAAA,mCAAA,GAAsC,CAAC,OAE9C,KAAA;AACJ,EAAM,MAAA,EAAE,cAAiB,GAAA,OAAA;AAEzB,EAAA,OAAOA,yCAAqB,CAAA;AAAA,IAC1B,EAAI,EAAA,2BAAA;AAAA,IACJ,WAAa,EAAA,+BAAA;AAAA,IACb,cAAgB,EAAA,IAAA;AAAA,cAChBC,yCAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,OAAOC,0BAAmB,CAAA,KAAA;AAAA,QACxBC,MAAE,MAAO,CAAA;AAAA,UACP,MAAMA,KACH,CAAA,KAAA;AAAA,YACCA,KAAA,CAAE,QAAS,CAAA,EAAA;AAAA,cACTA,MAAE,MAAO,CAAA;AAAA,gBACP,IAAA,EAAMA,MAAE,MAAO,EAAA;AAAA,gBACf,IAAA,EAAMA,MAAE,MAAO;AAAA,eAChB;AAAA,aACH;AAAA,YACA;AAAA,cACE,WACE,EAAA;AAAA;AACJ,WACF,CACC,IAAI,CAAC;AAAA,SACT;AAAA,OACH;AAAA,MACA,MAAA,EAAQA,MAAE,MAAO,CAAA;AAAA,QACf,OAAA,EAASA,MACN,MAAO,CAAA,EAAE,aAAa,mCAAoC,EAAC,EAC3D,QAAS;AAAA,OACb;AAAA,KACH;AAAA,IACA,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,IAAI,QAAU,EAAA;AAChB,QAAI,GAAA,CAAA,MAAA,CAAO,WAAW,EAAE,CAAA;AACxB,QAAA;AAAA;AAGF,MAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,IAAA,KAAS,GAAI,CAAA,KAAA;AAErC,MAAA,MAAM,EAAE,IAAA,EAAS,GAAAC,iBAAA,CAAa,SAAS,YAAY,CAAA;AAEnD,MAAA,MAAM,MAAMC,cAAU,CAAA,EAAE,IAAM,EAAA,YAAA,EAAc,OAAO,CAAA;AAEnD,MAAA,IAAI,WAA6B,GAAA,IAAA;AACjC,MAAA,IAAI,QAA0B,GAAA,IAAA;AAC9B,MAAA,KAAA,MAAW,eAAe,IAAM,EAAA;AAC9B,QAAA,MAAM,IACJ,GAAA,OAAO,WAAgB,KAAA,QAAA,GAAW,cAAc,WAAY,CAAA,IAAA;AAC9D,QAAA,MAAM,IACJ,GAAA,OAAO,WAAgB,KAAA,QAAA,GAAW,cAAc,WAAY,CAAA,IAAA;AAC9D,QAAA,MAAM,WAAmB,WAAc,GAAA,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,IAAI,CAAK,CAAA,GAAA,IAAA;AAClE,QAAM,MAAA,MAAA,GAAU,MAAM,GAAA,CAAI,MAAO,CAAA,MAAA;AAAA,UAC/B;AAAA,SACF;AACA,QAAA,MAAM,WAAW,MAAO,CAAA,IAAA;AAAA,UACtB,CAAA,cAAA,KAAkB,eAAe,SAAc,KAAA;AAAA,SACjD;AACA,QAAA,IAAI,CAAC,QAAU,EAAA;AACb,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAA0B,uBAAA,EAAA,QAAQ,CAAE,CAAA,CAAA;AACpD,UACE,QAAA,GAAA,CAAA,MAAM,IAAI,MAAO,CAAA,MAAA;AAAA,YACf,IAAA;AAAA,YACA,IAAA;AAAA,YACA,QACI,GAAA;AAAA,cACE;AAAA,gBAEF;AAAC,WAEN,GAAA,EAAA;AAAA,SACE,MAAA;AACL,UAAA,QAAA,GAAW,QAAS,CAAA,EAAA;AAAA;AAEtB,QAAc,WAAA,GAAA,QAAA;AAAA;AAEhB,MAAA,IAAI,aAAa,IAAM,EAAA;AACrB,QAAI,GAAA,CAAA,MAAA,CAAO,WAAW,QAAQ,CAAA;AAAA;AAChC;AACF,GACD,CAAA;AACH;;;;"}
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
- if (epicId) {
88
- isEpicScoped = await util.checkEpicScope(api, projectId, epicId);
89
- if (isEpicScoped) {
90
- ctx.logger.info("Epic is within Project Scope");
91
- } else {
92
- ctx.logger.warn(
93
- "Chosen epic is not within the Project Scope. The issue will be created without an associated epic."
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 api.Issues.create(
117
- projectId,
118
- title,
119
- issueOptions
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
- if (actions.length) {
320
- try {
321
- await api.Commits.create(repoID, branchName, title, actions);
322
- } catch (e) {
323
- throw new errors.InputError(
324
- `Committing the changes to ${branchName} failed. Please check that none of the files created by the template already exists. ${helpers.getErrorMessage(
325
- e
326
- )}`
327
- );
328
- }
329
- }
330
- try {
331
- let mergeRequest = await api.MergeRequests.create(
332
- repoID,
333
- branchName,
334
- String(targetBranch),
335
- title,
336
- {
337
- description,
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
- if (ctx.input.assignReviewersFromApprovalRules) {
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 reviewersFromApprovalRules = await getReviewersFromApprovalRules(
346
- api,
347
- mergeRequest.iid,
346
+ const mergeRequest = await api.MergeRequests.create(
348
347
  repoID,
349
- ctx
348
+ branchName,
349
+ String(targetBranch),
350
+ title,
351
+ {
352
+ description,
353
+ removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
354
+ assigneeId,
355
+ reviewerIds
356
+ }
350
357
  );
351
- if (reviewersFromApprovalRules.length > 0) {
352
- const eligibleUserIds = /* @__PURE__ */ new Set([
353
- ...reviewersFromApprovalRules,
354
- ...reviewerIds ?? []
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
- ctx.logger.warn(
366
- `Failed to assign reviewers from approval rules: ${helpers.getErrorMessage(
367
- e
368
- )}.`
363
+ throw new errors.InputError(
364
+ `Merge request creation failed. ${helpers.getErrorMessage(e)}`
369
365
  );
370
366
  }
371
367
  }
372
- ctx.output("projectid", repoID);
373
- ctx.output("targetBranchName", targetBranch);
374
- ctx.output("projectPath", repoID);
375
- ctx.output(
376
- "mergeRequestUrl",
377
- mergeRequest.web_url ?? mergeRequest.webUrl
378
- );
379
- } catch (e) {
380
- throw new errors.InputError(
381
- `Merge request creation failed. ${helpers.getErrorMessage(e)}`
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":";;;;;;;;;;;;;;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,UAAa,GAAA,KAAA,CAAA;AAEjB,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,IAAI,QAAQ,MAAQ,EAAA;AAClB,QAAI,IAAA;AACF,UAAA,MAAM,IAAI,OAAQ,CAAA,MAAA,CAAO,MAAQ,EAAA,UAAA,EAAY,OAAO,OAAO,CAAA;AAAA,iBACpD,CAAG,EAAA;AACV,UAAA,MAAM,IAAIO,iBAAA;AAAA,YACR,CAAA,0BAAA,EAA6B,UAAU,CAAwF,qFAAA,EAAAP,uBAAA;AAAA,cAC7H;AAAA,aACD,CAAA;AAAA,WACH;AAAA;AACF;AAEF,MAAI,IAAA;AACF,QAAI,IAAA,YAAA,GAAe,MAAM,GAAA,CAAI,aAAc,CAAA,MAAA;AAAA,UACzC,MAAA;AAAA,UACA,UAAA;AAAA,UACA,OAAO,YAAY,CAAA;AAAA,UACnB,KAAA;AAAA,UACA;AAAA,YACE,WAAA;AAAA,YACA,kBAAA,EAAoB,qBAAqB,kBAAqB,GAAA,KAAA;AAAA,YAC9D,UAAA;AAAA,YACA;AAAA;AACF,SACF;AAEA,QAAI,IAAA,GAAA,CAAI,MAAM,gCAAkC,EAAA;AAC9C,UAAI,IAAA;AACF,YAAA,MAAM,6BACJ,MAAM,6BAAA;AAAA,cACJ,GAAA;AAAA,cACA,YAAa,CAAA,GAAA;AAAA,cACb,MAAA;AAAA,cACA;AAAA,aACF;AACF,YAAI,IAAA,0BAAA,CAA2B,SAAS,CAAG,EAAA;AACzC,cAAM,MAAA,eAAA,uBAAsB,GAAI,CAAA;AAAA,gBAC9B,GAAG,0BAAA;AAAA,gBACH,GAAI,eAAe;AAAC,eACrB,CAAA;AAED,cAAe,YAAA,GAAA,MAAM,IAAI,aAAc,CAAA,IAAA;AAAA,gBACrC,MAAA;AAAA,gBACA,YAAa,CAAA,GAAA;AAAA,gBACb;AAAA,kBACE,WAAA,EAAa,KAAM,CAAA,IAAA,CAAK,eAAe;AAAA;AACzC,eACF;AAAA;AACF,mBACO,CAAG,EAAA;AACV,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,cACT,CAAmD,gDAAA,EAAAA,uBAAA;AAAA,gBACjD;AAAA,eACD,CAAA,CAAA;AAAA,aACH;AAAA;AACF;AAEF,QAAI,GAAA,CAAA,MAAA,CAAO,aAAa,MAAM,CAAA;AAC9B,QAAI,GAAA,CAAA,MAAA,CAAO,oBAAoB,YAAY,CAAA;AAC3C,QAAI,GAAA,CAAA,MAAA,CAAO,eAAe,MAAM,CAAA;AAChC,QAAI,GAAA,CAAA,MAAA;AAAA,UACF,iBAAA;AAAA,UACA,YAAA,CAAa,WAAW,YAAa,CAAA;AAAA,SACvC;AAAA,eACO,CAAG,EAAA;AACV,QAAA,MAAM,IAAIO,iBAAA;AAAA,UACR,CAAA,+BAAA,EAAkCP,uBAAgB,CAAA,CAAC,CAAC,CAAA;AAAA,SACtD;AAAA;AACF;AACF,GACD,CAAA;AACH;;;;"}
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":"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"}
@@ -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?.statusCode !== 404) {
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":"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"}
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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-backend-module-gitlab",
3
- "version": "0.8.0-next.3",
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.0-next.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.0-next.2",
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.0-next.3",
70
- "@backstage/cli": "0.30.0-next.3",
71
- "@backstage/core-app-api": "1.15.5-next.0",
72
- "@backstage/plugin-scaffolder-node-test-utils": "0.1.19-next.3"
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
  }