From 003dc1563f7388bf0525b12b13a3a2d006f54f76 Mon Sep 17 00:00:00 2001 From: Johannes Will Date: Wed, 26 Mar 2025 14:14:38 +0100 Subject: [PATCH 1/2] feat: support pathes in gitlab:group:ensureExists (#29399) Signed-off-by: Johannes Will --- .changeset/crazy-hands-film.md | 5 ++ .../gitlabGroupEnsureExists.examples.test.ts | 51 +++++++++++++++++++ .../gitlabGroupEnsureExists.examples.ts | 21 ++++++++ .../actions/gitlabGroupEnsureExists.test.ts | 32 ++++++++++++ .../src/actions/gitlabGroupEnsureExists.ts | 22 ++++++-- 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 .changeset/crazy-hands-film.md diff --git a/.changeset/crazy-hands-film.md b/.changeset/crazy-hands-film.md new file mode 100644 index 0000000000..694aa7b8e7 --- /dev/null +++ b/.changeset/crazy-hands-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +--- + +Updated the path field in the `gitlab:group:ensureExists` action to suport also strings with multiple segments (e.g. group/subgroup) diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.test.ts index eaeb65ae9c..4d8e0fd0c0 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.test.ts @@ -243,4 +243,55 @@ describe('gitlab:group:ensureExists', () => { expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); }); + + it(`Should ${examples[5].description}`, async () => { + mockGitlabClient.Groups.search.mockResolvedValue([ + { + id: 1, + full_path: 'group1', + }, + { + id: 2, + full_path: 'group1/group2', + }, + { + id: 3, + full_path: 'group1/group2/group3', + }, + ]); + mockGitlabClient.Groups.create.mockResolvedValue({ + id: 4, + full_path: 'group1/group2/group3/group4', + }); + + 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[5].example).steps[0].input, + }); + + expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith( + 'Group 4', + 'group4', + { + parentId: 3, + }, + ); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 4); + }); }); diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.ts index bbe7ad4722..f379bd38ec 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.examples.ts @@ -102,4 +102,25 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: + 'Create a group nested within another group using path and objects', + example: yaml.stringify({ + steps: [ + { + id: 'gitlabGroup', + name: 'Group', + action: 'gitlab:group:ensureExists', + input: { + repoUrl: 'gitlab.com', + path: [ + 'group1/group2', + { name: 'Group 3', slug: 'group3' }, + { name: 'Group 4', slug: 'group4' }, + ], + }, + }, + ], + }), + }, ]; diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.test.ts index f9dc12eb54..3d703eb91f 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.test.ts @@ -94,6 +94,38 @@ describe('gitlab:group:ensureExists', () => { expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); }); + it('should create a new group from pathstring if it does not exists', async () => { + mockGitlabClient.Groups.search.mockResolvedValue([ + { + id: 1, + full_path: 'bar', + }, + { + id: 2, + full_path: 'foo', + }, + ]); + + mockGitlabClient.Groups.create.mockResolvedValue({ + id: 3, + full_path: 'foo/bar', + }); + + await action.handler({ + ...mockContext, + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + path: ['foo/bar', 'baz'], + }, + }); + + expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith('bar', 'bar', { + parentId: 2, + }); + + expect(mockContext.output).toHaveBeenCalledWith('groupId', 3); + }); + it('should create a new group from object if it does not exists', async () => { mockGitlabClient.Groups.search.mockResolvedValue([ { diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.ts index 5be5b7c10d..7e5b03ce04 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabGroupEnsureExists.ts @@ -76,11 +76,7 @@ export const createGitlabGroupEnsureExistsAction = (options: { let currentPath: string | null = null; let parentId: number | null = null; - for (const pathElement of path) { - const slug = - typeof pathElement === 'string' ? pathElement : pathElement.slug; - const name = - typeof pathElement === 'string' ? pathElement : pathElement.name; + for (const { name, slug } of pathIterator(path)) { const fullPath: string = currentPath ? `${currentPath}/${slug}` : slug; const result = (await api.Groups.search( fullPath, @@ -119,3 +115,19 @@ export const createGitlabGroupEnsureExistsAction = (options: { }, }); }; + +type PathPart = { name: string; slug: string }; +type PathItem = string | PathPart; + +function* pathIterator(items: PathItem[]): Generator { + for (const item of items) { + if (typeof item === 'string') { + const parts = item.split('/'); + for (const part of parts) { + yield { name: part, slug: part }; + } + } else { + yield item; + } + } +} From 9eec76377d96a10f748dc388c67c44616d879d59 Mon Sep 17 00:00:00 2001 From: benjdlambert Date: Tue, 1 Apr 2025 11:14:29 +0100 Subject: [PATCH 2/2] chore: fixing changeset Signed-off-by: benjdlambert --- .changeset/crazy-hands-film.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/crazy-hands-film.md b/.changeset/crazy-hands-film.md index 694aa7b8e7..1d5933b317 100644 --- a/.changeset/crazy-hands-film.md +++ b/.changeset/crazy-hands-film.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend-module-gitlab': patch --- -Updated the path field in the `gitlab:group:ensureExists` action to suport also strings with multiple segments (e.g. group/subgroup) +Updated the path field in the `gitlab:group:ensureExists` action to support also strings with multiple segments (e.g. `group/subgroup`)