@bonvoy/plugin-gitlab 0.2.2 → 0.3.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/dist/index.d.mts CHANGED
@@ -22,6 +22,7 @@ interface GitLabOperations {
22
22
  createRelease(token: string, host: string, params: GitLabReleaseParams): Promise<void>;
23
23
  createMR(token: string, host: string, params: GitLabMRParams): Promise<GitLabMRResult>;
24
24
  releaseExists(token: string, host: string, projectId: string | number, tagName: string): Promise<boolean>;
25
+ deleteRelease(token: string, host: string, projectId: string | number, tagName: string): Promise<void>;
25
26
  }
26
27
  declare const defaultGitLabOperations: GitLabOperations;
27
28
  //#endregion
@@ -38,6 +39,7 @@ declare class GitLabPlugin implements BonvoyPlugin {
38
39
  private ops;
39
40
  constructor(options?: GitLabPluginOptions, ops?: GitLabOperations);
40
41
  apply(bonvoy: any): void;
42
+ private rollback;
41
43
  private validateReleases;
42
44
  private getProjectId;
43
45
  }
package/dist/index.mjs CHANGED
@@ -35,6 +35,12 @@ const defaultGitLabOperations = {
35
35
  } catch {
36
36
  return false;
37
37
  }
38
+ },
39
+ async deleteRelease(token, host, projectId, tagName) {
40
+ await new Gitlab({
41
+ token,
42
+ host
43
+ }).ProjectReleases.remove(projectId, tagName);
38
44
  }
39
45
  };
40
46
 
@@ -75,6 +81,15 @@ var GitLabPlugin = class {
75
81
  name: `${pkg.name} v${version}`,
76
82
  description: changelog
77
83
  });
84
+ context.actionLog.record({
85
+ plugin: "gitlab",
86
+ action: "release",
87
+ data: {
88
+ tag: tagName,
89
+ projectId: String(projectId),
90
+ host
91
+ }
92
+ });
78
93
  context.logger.info(`✅ Created GitLab release: ${tagName}`);
79
94
  } catch (error) {
80
95
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -112,6 +127,29 @@ var GitLabPlugin = class {
112
127
  throw error;
113
128
  }
114
129
  });
130
+ bonvoy.hooks.rollback.tapPromise(this.name, async (context) => {
131
+ await this.rollback(context);
132
+ });
133
+ }
134
+ async rollback(context) {
135
+ const { logger } = context;
136
+ const actions = context.actions.filter((a) => a.plugin === "gitlab").reverse();
137
+ const token = this.options.token || process.env.GITLAB_TOKEN;
138
+ if (!token) {
139
+ if (actions.length > 0) logger.warn("⚠️ GITLAB_TOKEN not found, cannot rollback GitLab releases");
140
+ return;
141
+ }
142
+ for (const action of actions) {
143
+ if (action.action !== "release") continue;
144
+ const { tag, projectId, host } = action.data;
145
+ try {
146
+ logger.info(` ↩️ Deleting GitLab release: ${tag}`);
147
+ await this.ops.deleteRelease(token, host, projectId, tag);
148
+ } catch (error) {
149
+ const msg = error instanceof Error ? error.message : String(error);
150
+ logger.warn(` ⚠️ Failed to delete GitLab release ${tag}: ${msg}`);
151
+ }
152
+ }
115
153
  }
116
154
  async validateReleases(context) {
117
155
  const { changedPackages, versions, logger } = context;
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/operations.ts","../src/gitlab.ts"],"sourcesContent":["import { Gitlab } from '@gitbeaker/rest';\n\nexport interface GitLabReleaseParams {\n projectId: string | number;\n tagName: string;\n name: string;\n description: string;\n}\n\nexport interface GitLabMRParams {\n projectId: string | number;\n title: string;\n description: string;\n sourceBranch: string;\n targetBranch: string;\n}\n\nexport interface GitLabMRResult {\n url: string;\n iid: number;\n}\n\nexport interface GitLabOperations {\n createRelease(token: string, host: string, params: GitLabReleaseParams): Promise<void>;\n createMR(token: string, host: string, params: GitLabMRParams): Promise<GitLabMRResult>;\n releaseExists(\n token: string,\n host: string,\n projectId: string | number,\n tagName: string,\n ): Promise<boolean>;\n}\n\nexport const defaultGitLabOperations: GitLabOperations = {\n /* v8 ignore start */\n async createRelease(token, host, params) {\n const api = new Gitlab({ token, host });\n await api.ProjectReleases.create(params.projectId, {\n tagName: params.tagName,\n name: params.name,\n description: params.description,\n });\n },\n\n async createMR(token, host, params) {\n const api = new Gitlab({ token, host });\n const mr = await api.MergeRequests.create(\n params.projectId,\n params.sourceBranch,\n params.targetBranch,\n params.title,\n {\n description: params.description,\n },\n );\n return { url: mr.web_url, iid: mr.iid };\n },\n\n async releaseExists(token, host, projectId, tagName) {\n const api = new Gitlab({ token, host });\n try {\n await api.ProjectReleases.show(projectId, tagName);\n return true;\n } catch {\n return false;\n }\n },\n /* v8 ignore stop */\n};\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { BonvoyPlugin, Context, PRContext, ReleaseContext } from '@bonvoy/core';\n\nimport { defaultGitLabOperations, type GitLabOperations } from './operations.js';\n\nexport interface GitLabPluginOptions {\n token?: string;\n host?: string;\n projectId?: string | number;\n tagFormat?: string;\n}\n\nexport default class GitLabPlugin implements BonvoyPlugin {\n name = 'gitlab';\n private options: GitLabPluginOptions;\n private ops: GitLabOperations;\n\n constructor(options: GitLabPluginOptions = {}, ops?: GitLabOperations) {\n this.options = options;\n this.ops = ops ?? defaultGitLabOperations;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Bonvoy type causes circular dependency\n apply(bonvoy: any): void {\n bonvoy.hooks.validateRepo.tapPromise(this.name, async (context: Context) => {\n await this.validateReleases(context);\n });\n\n bonvoy.hooks.makeRelease.tapPromise(this.name, async (context: ReleaseContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would create GitLab releases');\n return;\n }\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) {\n context.logger.warn('⚠️ GITLAB_TOKEN not found, skipping GitLab releases');\n return;\n }\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n const projectId = this.getProjectId(context.rootPath);\n\n for (const pkg of context.changedPackages) {\n const version = context.versions[pkg.name];\n const changelog = context.changelogs[pkg.name] || '';\n const tagFormat = this.options.tagFormat ?? '{name}@{version}';\n const tagName = tagFormat.replace('{name}', pkg.name).replace('{version}', version);\n\n try {\n await this.ops.createRelease(token, host, {\n projectId,\n tagName,\n name: `${pkg.name} v${version}`,\n description: changelog,\n });\n\n context.logger.info(`✅ Created GitLab release: ${tagName}`);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n context.logger.error(`❌ Failed to create release for ${tagName}: ${errorMessage}`);\n throw error;\n }\n }\n });\n\n // MR creation hook\n bonvoy.hooks.createPR.tapPromise(this.name, async (context: PRContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would create GitLab MR');\n return;\n }\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) {\n context.logger.warn('⚠️ GITLAB_TOKEN not found, skipping MR creation');\n return;\n }\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n const projectId = this.getProjectId(context.rootPath);\n\n try {\n const result = await this.ops.createMR(token, host, {\n projectId,\n title: context.title,\n description: context.body,\n sourceBranch: context.branchName,\n targetBranch: context.baseBranch,\n });\n\n context.prUrl = result.url;\n context.prNumber = result.iid;\n context.logger.info(`✅ Created GitLab MR: ${result.url}`);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n context.logger.error(`❌ Failed to create MR: ${errorMessage}`);\n throw error;\n }\n });\n }\n\n private async validateReleases(context: Context): Promise<void> {\n const { changedPackages, versions, logger } = context;\n if (!versions) return;\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) return;\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n let projectId: string | number;\n try {\n projectId = this.getProjectId(context.rootPath);\n } catch {\n return;\n }\n\n const tagFormat = this.options.tagFormat ?? '{name}@{version}';\n const existing: string[] = [];\n\n for (const pkg of changedPackages) {\n const version = versions[pkg.name];\n /* c8 ignore start -- defensive: version always present for changedPackages */\n if (!version) continue;\n /* c8 ignore stop */\n const tag = tagFormat.replace('{name}', pkg.name).replace('{version}', version);\n if (await this.ops.releaseExists(token, host, projectId, tag)) {\n existing.push(tag);\n }\n }\n\n if (existing.length > 0) {\n logger.error(`❌ GitLab releases already exist: ${existing.join(', ')}`);\n throw new Error(\n `Cannot release: GitLab releases already exist (${existing.join(', ')}). Delete them first or bump to a new version.`,\n );\n }\n }\n\n private getProjectId(rootPath: string): string | number {\n if (this.options.projectId) {\n return this.options.projectId;\n }\n\n // Try to read from package.json repository field\n try {\n const pkgPath = join(rootPath, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n const repoUrl = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url;\n\n if (repoUrl) {\n // Match gitlab.com/group/project or gitlab.com/group/subgroup/project\n const match = repoUrl.match(/gitlab\\.com[:/](.+?)(?:\\.git)?$/);\n if (match) {\n return encodeURIComponent(match[1]);\n }\n }\n } catch {\n // Ignore error\n }\n\n throw new Error(\n 'Could not determine GitLab project. Please set \"repository\" in package.json or provide projectId in plugin options.',\n );\n }\n}\n\nexport {\n defaultGitLabOperations,\n type GitLabMRParams,\n type GitLabMRResult,\n type GitLabOperations,\n type GitLabReleaseParams,\n} from './operations.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/operations.ts","../src/gitlab.ts"],"sourcesContent":["import { Gitlab } from '@gitbeaker/rest';\n\nexport interface GitLabReleaseParams {\n projectId: string | number;\n tagName: string;\n name: string;\n description: string;\n}\n\nexport interface GitLabMRParams {\n projectId: string | number;\n title: string;\n description: string;\n sourceBranch: string;\n targetBranch: string;\n}\n\nexport interface GitLabMRResult {\n url: string;\n iid: number;\n}\n\nexport interface GitLabOperations {\n createRelease(token: string, host: string, params: GitLabReleaseParams): Promise<void>;\n createMR(token: string, host: string, params: GitLabMRParams): Promise<GitLabMRResult>;\n releaseExists(\n token: string,\n host: string,\n projectId: string | number,\n tagName: string,\n ): Promise<boolean>;\n deleteRelease(\n token: string,\n host: string,\n projectId: string | number,\n tagName: string,\n ): Promise<void>;\n}\n\nexport const defaultGitLabOperations: GitLabOperations = {\n /* v8 ignore start */\n async createRelease(token, host, params) {\n const api = new Gitlab({ token, host });\n await api.ProjectReleases.create(params.projectId, {\n tagName: params.tagName,\n name: params.name,\n description: params.description,\n });\n },\n\n async createMR(token, host, params) {\n const api = new Gitlab({ token, host });\n const mr = await api.MergeRequests.create(\n params.projectId,\n params.sourceBranch,\n params.targetBranch,\n params.title,\n {\n description: params.description,\n },\n );\n return { url: mr.web_url, iid: mr.iid };\n },\n\n async releaseExists(token, host, projectId, tagName) {\n const api = new Gitlab({ token, host });\n try {\n await api.ProjectReleases.show(projectId, tagName);\n return true;\n } catch {\n return false;\n }\n },\n\n async deleteRelease(token, host, projectId, tagName) {\n const api = new Gitlab({ token, host });\n await api.ProjectReleases.remove(projectId, tagName);\n },\n /* v8 ignore stop */\n};\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type {\n BonvoyPlugin,\n Context,\n PRContext,\n ReleaseContext,\n RollbackContext,\n} from '@bonvoy/core';\n\nimport { defaultGitLabOperations, type GitLabOperations } from './operations.js';\n\nexport interface GitLabPluginOptions {\n token?: string;\n host?: string;\n projectId?: string | number;\n tagFormat?: string;\n}\n\nexport default class GitLabPlugin implements BonvoyPlugin {\n name = 'gitlab';\n private options: GitLabPluginOptions;\n private ops: GitLabOperations;\n\n constructor(options: GitLabPluginOptions = {}, ops?: GitLabOperations) {\n this.options = options;\n this.ops = ops ?? defaultGitLabOperations;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Bonvoy type causes circular dependency\n apply(bonvoy: any): void {\n bonvoy.hooks.validateRepo.tapPromise(this.name, async (context: Context) => {\n await this.validateReleases(context);\n });\n\n bonvoy.hooks.makeRelease.tapPromise(this.name, async (context: ReleaseContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would create GitLab releases');\n return;\n }\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) {\n context.logger.warn('⚠️ GITLAB_TOKEN not found, skipping GitLab releases');\n return;\n }\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n const projectId = this.getProjectId(context.rootPath);\n\n for (const pkg of context.changedPackages) {\n const version = context.versions[pkg.name];\n const changelog = context.changelogs[pkg.name] || '';\n const tagFormat = this.options.tagFormat ?? '{name}@{version}';\n const tagName = tagFormat.replace('{name}', pkg.name).replace('{version}', version);\n\n try {\n await this.ops.createRelease(token, host, {\n projectId,\n tagName,\n name: `${pkg.name} v${version}`,\n description: changelog,\n });\n\n context.actionLog.record({\n plugin: 'gitlab',\n action: 'release',\n data: { tag: tagName, projectId: String(projectId), host },\n });\n\n context.logger.info(`✅ Created GitLab release: ${tagName}`);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n context.logger.error(`❌ Failed to create release for ${tagName}: ${errorMessage}`);\n throw error;\n }\n }\n });\n\n // MR creation hook\n bonvoy.hooks.createPR.tapPromise(this.name, async (context: PRContext) => {\n if (context.isDryRun) {\n context.logger.info('🔍 [dry-run] Would create GitLab MR');\n return;\n }\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) {\n context.logger.warn('⚠️ GITLAB_TOKEN not found, skipping MR creation');\n return;\n }\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n const projectId = this.getProjectId(context.rootPath);\n\n try {\n const result = await this.ops.createMR(token, host, {\n projectId,\n title: context.title,\n description: context.body,\n sourceBranch: context.branchName,\n targetBranch: context.baseBranch,\n });\n\n context.prUrl = result.url;\n context.prNumber = result.iid;\n context.logger.info(`✅ Created GitLab MR: ${result.url}`);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n context.logger.error(`❌ Failed to create MR: ${errorMessage}`);\n throw error;\n }\n });\n\n bonvoy.hooks.rollback.tapPromise(this.name, async (context: RollbackContext) => {\n await this.rollback(context);\n });\n }\n\n private async rollback(context: RollbackContext): Promise<void> {\n const { logger } = context;\n const actions = context.actions.filter((a) => a.plugin === 'gitlab').reverse();\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) {\n if (actions.length > 0) {\n logger.warn('⚠️ GITLAB_TOKEN not found, cannot rollback GitLab releases');\n }\n return;\n }\n\n for (const action of actions) {\n if (action.action !== 'release') continue;\n const { tag, projectId, host } = action.data as {\n tag: string;\n projectId: string;\n host: string;\n };\n try {\n logger.info(` ↩️ Deleting GitLab release: ${tag}`);\n await this.ops.deleteRelease(token, host, projectId, tag);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.warn(` ⚠️ Failed to delete GitLab release ${tag}: ${msg}`);\n }\n }\n }\n\n private async validateReleases(context: Context): Promise<void> {\n const { changedPackages, versions, logger } = context;\n if (!versions) return;\n\n const token = this.options.token || process.env.GITLAB_TOKEN;\n if (!token) return;\n\n const host = this.options.host || process.env.GITLAB_HOST || 'https://gitlab.com';\n let projectId: string | number;\n try {\n projectId = this.getProjectId(context.rootPath);\n } catch {\n return;\n }\n\n const tagFormat = this.options.tagFormat ?? '{name}@{version}';\n const existing: string[] = [];\n\n for (const pkg of changedPackages) {\n const version = versions[pkg.name];\n /* c8 ignore start -- defensive: version always present for changedPackages */\n if (!version) continue;\n /* c8 ignore stop */\n const tag = tagFormat.replace('{name}', pkg.name).replace('{version}', version);\n if (await this.ops.releaseExists(token, host, projectId, tag)) {\n existing.push(tag);\n }\n }\n\n if (existing.length > 0) {\n logger.error(`❌ GitLab releases already exist: ${existing.join(', ')}`);\n throw new Error(\n `Cannot release: GitLab releases already exist (${existing.join(', ')}). Delete them first or bump to a new version.`,\n );\n }\n }\n\n private getProjectId(rootPath: string): string | number {\n if (this.options.projectId) {\n return this.options.projectId;\n }\n\n // Try to read from package.json repository field\n try {\n const pkgPath = join(rootPath, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n const repoUrl = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url;\n\n if (repoUrl) {\n // Match gitlab.com/group/project or gitlab.com/group/subgroup/project\n const match = repoUrl.match(/gitlab\\.com[:/](.+?)(?:\\.git)?$/);\n if (match) {\n return encodeURIComponent(match[1]);\n }\n }\n } catch {\n // Ignore error\n }\n\n throw new Error(\n 'Could not determine GitLab project. Please set \"repository\" in package.json or provide projectId in plugin options.',\n );\n }\n}\n\nexport {\n defaultGitLabOperations,\n type GitLabMRParams,\n type GitLabMRResult,\n type GitLabOperations,\n type GitLabReleaseParams,\n} from './operations.js';\n"],"mappings":";;;;;AAuCA,MAAa,0BAA4C;CAEvD,MAAM,cAAc,OAAO,MAAM,QAAQ;AAEvC,QADY,IAAI,OAAO;GAAE;GAAO;GAAM,CAAC,CAC7B,gBAAgB,OAAO,OAAO,WAAW;GACjD,SAAS,OAAO;GAChB,MAAM,OAAO;GACb,aAAa,OAAO;GACrB,CAAC;;CAGJ,MAAM,SAAS,OAAO,MAAM,QAAQ;EAElC,MAAM,KAAK,MADC,IAAI,OAAO;GAAE;GAAO;GAAM,CAAC,CAClB,cAAc,OACjC,OAAO,WACP,OAAO,cACP,OAAO,cACP,OAAO,OACP,EACE,aAAa,OAAO,aACrB,CACF;AACD,SAAO;GAAE,KAAK,GAAG;GAAS,KAAK,GAAG;GAAK;;CAGzC,MAAM,cAAc,OAAO,MAAM,WAAW,SAAS;EACnD,MAAM,MAAM,IAAI,OAAO;GAAE;GAAO;GAAM,CAAC;AACvC,MAAI;AACF,SAAM,IAAI,gBAAgB,KAAK,WAAW,QAAQ;AAClD,UAAO;UACD;AACN,UAAO;;;CAIX,MAAM,cAAc,OAAO,MAAM,WAAW,SAAS;AAEnD,QADY,IAAI,OAAO;GAAE;GAAO;GAAM,CAAC,CAC7B,gBAAgB,OAAO,WAAW,QAAQ;;CAGvD;;;;AC3DD,IAAqB,eAArB,MAA0D;CACxD,OAAO;CACP,AAAQ;CACR,AAAQ;CAER,YAAY,UAA+B,EAAE,EAAE,KAAwB;AACrE,OAAK,UAAU;AACf,OAAK,MAAM,OAAO;;CAIpB,MAAM,QAAmB;AACvB,SAAO,MAAM,aAAa,WAAW,KAAK,MAAM,OAAO,YAAqB;AAC1E,SAAM,KAAK,iBAAiB,QAAQ;IACpC;AAEF,SAAO,MAAM,YAAY,WAAW,KAAK,MAAM,OAAO,YAA4B;AAChF,OAAI,QAAQ,UAAU;AACpB,YAAQ,OAAO,KAAK,4CAA4C;AAChE;;GAGF,MAAM,QAAQ,KAAK,QAAQ,SAAS,QAAQ,IAAI;AAChD,OAAI,CAAC,OAAO;AACV,YAAQ,OAAO,KAAK,uDAAuD;AAC3E;;GAGF,MAAM,OAAO,KAAK,QAAQ,QAAQ,QAAQ,IAAI,eAAe;GAC7D,MAAM,YAAY,KAAK,aAAa,QAAQ,SAAS;AAErD,QAAK,MAAM,OAAO,QAAQ,iBAAiB;IACzC,MAAM,UAAU,QAAQ,SAAS,IAAI;IACrC,MAAM,YAAY,QAAQ,WAAW,IAAI,SAAS;IAElD,MAAM,WADY,KAAK,QAAQ,aAAa,oBAClB,QAAQ,UAAU,IAAI,KAAK,CAAC,QAAQ,aAAa,QAAQ;AAEnF,QAAI;AACF,WAAM,KAAK,IAAI,cAAc,OAAO,MAAM;MACxC;MACA;MACA,MAAM,GAAG,IAAI,KAAK,IAAI;MACtB,aAAa;MACd,CAAC;AAEF,aAAQ,UAAU,OAAO;MACvB,QAAQ;MACR,QAAQ;MACR,MAAM;OAAE,KAAK;OAAS,WAAW,OAAO,UAAU;OAAE;OAAM;MAC3D,CAAC;AAEF,aAAQ,OAAO,KAAK,6BAA6B,UAAU;aACpD,OAAgB;KACvB,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,aAAQ,OAAO,MAAM,kCAAkC,QAAQ,IAAI,eAAe;AAClF,WAAM;;;IAGV;AAGF,SAAO,MAAM,SAAS,WAAW,KAAK,MAAM,OAAO,YAAuB;AACxE,OAAI,QAAQ,UAAU;AACpB,YAAQ,OAAO,KAAK,sCAAsC;AAC1D;;GAGF,MAAM,QAAQ,KAAK,QAAQ,SAAS,QAAQ,IAAI;AAChD,OAAI,CAAC,OAAO;AACV,YAAQ,OAAO,KAAK,mDAAmD;AACvE;;GAGF,MAAM,OAAO,KAAK,QAAQ,QAAQ,QAAQ,IAAI,eAAe;GAC7D,MAAM,YAAY,KAAK,aAAa,QAAQ,SAAS;AAErD,OAAI;IACF,MAAM,SAAS,MAAM,KAAK,IAAI,SAAS,OAAO,MAAM;KAClD;KACA,OAAO,QAAQ;KACf,aAAa,QAAQ;KACrB,cAAc,QAAQ;KACtB,cAAc,QAAQ;KACvB,CAAC;AAEF,YAAQ,QAAQ,OAAO;AACvB,YAAQ,WAAW,OAAO;AAC1B,YAAQ,OAAO,KAAK,wBAAwB,OAAO,MAAM;YAClD,OAAgB;IACvB,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,YAAQ,OAAO,MAAM,0BAA0B,eAAe;AAC9D,UAAM;;IAER;AAEF,SAAO,MAAM,SAAS,WAAW,KAAK,MAAM,OAAO,YAA6B;AAC9E,SAAM,KAAK,SAAS,QAAQ;IAC5B;;CAGJ,MAAc,SAAS,SAAyC;EAC9D,MAAM,EAAE,WAAW;EACnB,MAAM,UAAU,QAAQ,QAAQ,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,SAAS;EAE9E,MAAM,QAAQ,KAAK,QAAQ,SAAS,QAAQ,IAAI;AAChD,MAAI,CAAC,OAAO;AACV,OAAI,QAAQ,SAAS,EACnB,QAAO,KAAK,8DAA8D;AAE5E;;AAGF,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,OAAO,WAAW,UAAW;GACjC,MAAM,EAAE,KAAK,WAAW,SAAS,OAAO;AAKxC,OAAI;AACF,WAAO,KAAK,kCAAkC,MAAM;AACpD,UAAM,KAAK,IAAI,cAAc,OAAO,MAAM,WAAW,IAAI;YAClD,OAAgB;IACvB,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAClE,WAAO,KAAK,yCAAyC,IAAI,IAAI,MAAM;;;;CAKzE,MAAc,iBAAiB,SAAiC;EAC9D,MAAM,EAAE,iBAAiB,UAAU,WAAW;AAC9C,MAAI,CAAC,SAAU;EAEf,MAAM,QAAQ,KAAK,QAAQ,SAAS,QAAQ,IAAI;AAChD,MAAI,CAAC,MAAO;EAEZ,MAAM,OAAO,KAAK,QAAQ,QAAQ,QAAQ,IAAI,eAAe;EAC7D,IAAI;AACJ,MAAI;AACF,eAAY,KAAK,aAAa,QAAQ,SAAS;UACzC;AACN;;EAGF,MAAM,YAAY,KAAK,QAAQ,aAAa;EAC5C,MAAM,WAAqB,EAAE;AAE7B,OAAK,MAAM,OAAO,iBAAiB;GACjC,MAAM,UAAU,SAAS,IAAI;;AAE7B,OAAI,CAAC,QAAS;;GAEd,MAAM,MAAM,UAAU,QAAQ,UAAU,IAAI,KAAK,CAAC,QAAQ,aAAa,QAAQ;AAC/E,OAAI,MAAM,KAAK,IAAI,cAAc,OAAO,MAAM,WAAW,IAAI,CAC3D,UAAS,KAAK,IAAI;;AAItB,MAAI,SAAS,SAAS,GAAG;AACvB,UAAO,MAAM,oCAAoC,SAAS,KAAK,KAAK,GAAG;AACvE,SAAM,IAAI,MACR,kDAAkD,SAAS,KAAK,KAAK,CAAC,gDACvE;;;CAIL,AAAQ,aAAa,UAAmC;AACtD,MAAI,KAAK,QAAQ,UACf,QAAO,KAAK,QAAQ;AAItB,MAAI;GACF,MAAM,UAAU,KAAK,UAAU,eAAe;GAC9C,MAAM,MAAM,KAAK,MAAM,aAAa,SAAS,QAAQ,CAAC;GACtD,MAAM,UAAU,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa,IAAI,YAAY;AAEtF,OAAI,SAAS;IAEX,MAAM,QAAQ,QAAQ,MAAM,kCAAkC;AAC9D,QAAI,MACF,QAAO,mBAAmB,MAAM,GAAG;;UAGjC;AAIR,QAAM,IAAI,MACR,wHACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bonvoy/plugin-gitlab",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "🚢 GitLab releases plugin for bonvoy",
5
5
  "keywords": [
6
6
  "bonvoy",
@@ -35,8 +35,8 @@
35
35
  "test": "vitest"
36
36
  },
37
37
  "dependencies": {
38
- "@bonvoy/core": "^0.4.0",
39
- "@gitbeaker/rest": "^42.5.0"
38
+ "@bonvoy/core": "^0.7.0",
39
+ "@gitbeaker/rest": "^43.8.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">= 20.5"