diff --git a/.changeset/proud-queens-mix.md b/.changeset/proud-queens-mix.md new file mode 100644 index 0000000000..b5a1343998 --- /dev/null +++ b/.changeset/proud-queens-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitlab': minor +--- + +Add examples for gitlab:group:ensureExists scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.test.ts new file mode 100644 index 0000000000..2d077c7400 --- /dev/null +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.test.ts @@ -0,0 +1,198 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createGitlabGroupEnsureExistsAction } from './createGitlabGroupEnsureExistsAction'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; +import { ConfigReader } from '@backstage/core-app-api'; +import { ScmIntegrations } from '@backstage/integration'; +import yaml from 'yaml'; +import { examples } from './createGitlabGroupEnsureExistsAction.examples'; + +const mockGitlabClient = { + Groups: { + search: jest.fn(), + create: jest.fn(), + }, +}; +jest.mock('@gitbeaker/node', () => ({ + Gitlab: class { + constructor() { + return mockGitlabClient; + } + }, +})); + +describe('gitlab:group:ensureExists', () => { + const mockContext = createMockActionContext(); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it(`Should ${examples[0].description}`, async () => { + mockGitlabClient.Groups.search.mockResolvedValue([]); + mockGitlabClient.Groups.create.mockResolvedValue({ + id: 3, + full_path: 'group1', + }); + + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + + const action = createGitlabGroupEnsureExistsAction({ integrations }); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }); + + expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith( + 'group1', + 'group1', + {}, + ); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); + }); + + it(`Should ${examples[1].description}`, async () => { + mockGitlabClient.Groups.search.mockResolvedValue([ + { + id: 1, + full_path: 'group1', + }, + ]); + mockGitlabClient.Groups.create.mockResolvedValue({ + id: 3, + full_path: 'group1/group2', + }); + + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + + const action = createGitlabGroupEnsureExistsAction({ integrations }); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[1].example).steps[0].input, + }); + + expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith( + 'group2', + 'group2', + { + parent_id: 1, + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); + }); + + it(`Should ${examples[2].description}`, async () => { + mockGitlabClient.Groups.search.mockResolvedValue([ + { + id: 1, + full_path: 'group1', + }, + { + id: 2, + full_path: 'group1/group2', + }, + ]); + mockGitlabClient.Groups.create.mockResolvedValue({ + id: 3, + full_path: 'group1/group2/group3', + }); + + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + + const action = createGitlabGroupEnsureExistsAction({ integrations }); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[2].example).steps[0].input, + }); + + expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith( + 'group3', + 'group3', + { + parent_id: 2, + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); + }); + + it(`Should ${examples[3].description}`, async () => { + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + + const action = createGitlabGroupEnsureExistsAction({ integrations }); + + await action.handler({ + ...mockContext, + isDryRun: yaml.parse(examples[3].example).steps[0].isDryRun, + input: yaml.parse(examples[3].example).steps[0].input, + }); + + expect(mockGitlabClient.Groups.search).not.toHaveBeenCalled(); + expect(mockGitlabClient.Groups.create).not.toHaveBeenCalled(); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 42); + }); +}); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.ts new file mode 100644 index 0000000000..41dd822e82 --- /dev/null +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.examples.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Creating a group at the top level', + example: yaml.stringify({ + steps: [ + { + id: 'gitlabGroup', + name: 'Group', + action: 'gitlab:group:ensureExists', + input: { + repoUrl: 'gitlab.com', + path: ['group1'], + }, + }, + ], + }), + }, + { + description: 'Create a group nested within another group', + example: yaml.stringify({ + steps: [ + { + id: 'gitlabGroup', + name: 'Group', + action: 'gitlab:group:ensureExists', + input: { + repoUrl: 'gitlab.com', + path: ['group1', 'group2'], + }, + }, + ], + }), + }, + { + description: 'Create a group nested within multiple other groups', + example: yaml.stringify({ + steps: [ + { + id: 'gitlabGroup', + name: 'Group', + action: 'gitlab:group:ensureExists', + input: { + repoUrl: 'gitlab.com', + path: ['group1', 'group2', 'group3'], + }, + }, + ], + }), + }, + { + description: 'Create a group in dry run mode', + example: yaml.stringify({ + steps: [ + { + id: 'gitlabGroup', + name: 'Group', + action: 'gitlab:group:ensureExists', + isDryRun: true, + input: { + repoUrl: 'https://gitlab.com/my-repo', + path: ['group1', 'group2', 'group3'], + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts index 74d3805254..2cf583a95d 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/createGitlabGroupEnsureExistsAction.ts @@ -21,6 +21,7 @@ import { GroupSchema } from '@gitbeaker/core/dist/types/resources/Groups'; import commonGitlabConfig from '../commonGitlabConfig'; import { getToken } from '../util'; import { z } from 'zod'; +import { examples } from './createGitlabGroupEnsureExistsAction.examples'; /** * Creates an `gitlab:group:ensureExists` Scaffolder action. @@ -36,6 +37,7 @@ export const createGitlabGroupEnsureExistsAction = (options: { id: 'gitlab:group:ensureExists', description: 'Ensures a Gitlab group exists', supportsDryRun: true, + examples, schema: { input: commonGitlabConfig.merge( z.object({