diff --git a/.changeset/old-onions-hear.md b/.changeset/old-onions-hear.md index 82dcc09190..febf2c2bf6 100644 --- a/.changeset/old-onions-hear.md +++ b/.changeset/old-onions-hear.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend': minor --- -Update GitLab Merge Request Action to allow source branch to be deleted +Update GitLab Merge Request Action to allow source branch to be deleted & configure additional gitlab actions: update and delete diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index b0f831fc8c..742293da30 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -346,6 +346,7 @@ export const createPublishGitlabMergeRequestAction: (options: { token?: string | undefined; projectid?: string | undefined; removeSourceBranch?: boolean | undefined; + gitlabAction?: 'update' | 'create' | 'delete' | undefined; }>; // @public diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts index cf2bc57514..889b8b862c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts @@ -79,6 +79,20 @@ jest.mock('@gitbeaker/node', () => ({ }, })); +jest.mock('globby', () => + jest.fn(async (_: any) => { + return ['foo/bar5']; + }), +); + +jest.mock('fs-extra', () => { + return { + readFile: jest.fn(async (_: any) => { + return Buffer.from('some content'); + }), + }; +}); + describe('createGitLabMergeRequest', () => { let instance: TemplateAction; @@ -216,4 +230,165 @@ describe('createGitLabMergeRequest', () => { ); }); }); + + describe('createGitLabMergeRequestWithoutGitlabAction', () => { + it('gitlabAction is create by default when not passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'This MR is really good', + draft: true, + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( + undefined, + 'new-mr', + 'Create my new MR', + [ + { + action: 'create', + filePath: 'foo/bar5', + content: 'some content', + }, + ], + ); + }); + }); + + describe('createGitLabMergeRequestWithGitlabAction', () => { + it('gitlabAction is create when create is passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'MR description', + gitlabAction: 'create', + draft: true, + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( + undefined, + 'new-mr', + 'Create my new MR', + [ + { + action: 'create', + filePath: 'foo/bar5', + content: 'some content', + }, + ], + ); + }); + + it('gitlabAction is update when update is passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'MR description', + gitlabAction: 'update', + draft: true, + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( + undefined, + 'new-mr', + 'Create my new MR', + [ + { + action: 'update', + filePath: 'foo/bar5', + content: 'some content', + }, + ], + ); + }); + + it('gitlabAction is delete when delete is passed in options', async () => { + const input = { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + title: 'Create my new MR', + branchName: 'new-mr', + description: 'other MR description', + gitlabAction: 'delete', + draft: true, + }; + mockFs({ + [workspacePath]: { + source: { 'foo.txt': 'Hello there!' }, + irrelevant: { 'bar.txt': 'Nothing to see here' }, + }, + }); + + const ctx = { + createTemporaryDirectory: jest.fn(), + output: jest.fn(), + logger: getRootLogger(), + logStream: new Writable(), + input, + workspacePath, + }; + await instance.handler(ctx); + + expect(mockGitlabClient.Commits.create).toHaveBeenCalledWith( + undefined, + 'new-mr', + 'Create my new MR', + [ + { + action: 'delete', + filePath: 'foo/bar5', + }, + ], + ); + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts index b1d5b35fa3..7e0949454b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts @@ -43,6 +43,7 @@ export const createPublishGitlabMergeRequestAction = (options: { /** @deprecated Use projectPath instead */ projectid?: string; removeSourceBranch?: boolean; + gitlabAction?: 'create' | 'update' | 'delete'; }>({ id: 'publish:gitlab:merge-request', schema: { @@ -92,6 +93,12 @@ export const createPublishGitlabMergeRequestAction = (options: { description: 'Option to delete source branch once the MR has been merged. Default: false', }, + gitlabAction: { + title: 'GitLab Action', + type: 'string', + description: + 'Option to configure gitlab action. Options are: create (by default), update and delete', + }, }, }, output: {