feat(gitlab): Allow setting optional description on group creation
Signed-off-by: Jellyfrog <Jellyfrog@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
|
||||
---
|
||||
|
||||
Allow setting optional description on group creation
|
||||
@@ -22,6 +22,7 @@ export const createGitlabGroupEnsureExistsAction: (options: {
|
||||
}
|
||||
)[];
|
||||
token?: string | undefined;
|
||||
description?: string | undefined;
|
||||
},
|
||||
{
|
||||
groupId?: number | undefined;
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ describe('gitlab:group:ensureExists', () => {
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith(
|
||||
'group1',
|
||||
'group1',
|
||||
{},
|
||||
{ description: 'This is a top-level group' },
|
||||
);
|
||||
|
||||
expect(mockContext.output).toHaveBeenCalledWith('groupId', 3);
|
||||
|
||||
+2
-1
@@ -18,7 +18,7 @@ import yaml from 'yaml';
|
||||
|
||||
export const examples: TemplateExample[] = [
|
||||
{
|
||||
description: 'Creating a group at the top level',
|
||||
description: 'Creating a group at the top level, with a description',
|
||||
example: yaml.stringify({
|
||||
steps: [
|
||||
{
|
||||
@@ -28,6 +28,7 @@ export const examples: TemplateExample[] = [
|
||||
input: {
|
||||
repoUrl: 'gitlab.com',
|
||||
path: ['group1'],
|
||||
description: 'This is a top-level group',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -86,16 +86,73 @@ describe('gitlab:group:ensureExists', () => {
|
||||
input: {
|
||||
repoUrl: 'gitlab.com?repo=repo&owner=owner',
|
||||
path: ['foo', 'bar'],
|
||||
description: 'my cool group',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenCalledWith('bar', 'bar', {
|
||||
description: 'my cool group',
|
||||
parentId: 2,
|
||||
});
|
||||
|
||||
expect(mockContext.output).toHaveBeenCalledWith('groupId', 3);
|
||||
});
|
||||
|
||||
it('should only apply description to the last created group', async () => {
|
||||
mockGitlabClient.Groups.search.mockResolvedValue([]);
|
||||
|
||||
mockGitlabClient.Groups.create
|
||||
.mockResolvedValueOnce({
|
||||
id: 1,
|
||||
full_path: 'foo',
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
id: 2,
|
||||
full_path: 'foo/bar',
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
id: 3,
|
||||
full_path: 'foo/bar/baz',
|
||||
});
|
||||
|
||||
await action.handler({
|
||||
...mockContext,
|
||||
input: {
|
||||
repoUrl: 'gitlab.com?repo=repo&owner=owner',
|
||||
path: ['foo', 'bar', 'baz'],
|
||||
description: 'only for innermost group',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenCalledTimes(3);
|
||||
|
||||
// First group: no description
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'foo',
|
||||
'foo',
|
||||
{},
|
||||
);
|
||||
|
||||
// Second group: no description
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'bar',
|
||||
'bar',
|
||||
{ parentId: 1 },
|
||||
);
|
||||
|
||||
// Third (last) group: has description
|
||||
expect(mockGitlabClient.Groups.create).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
'baz',
|
||||
'baz',
|
||||
{ parentId: 2, description: 'only for innermost group' },
|
||||
);
|
||||
|
||||
expect(mockContext.output).toHaveBeenCalledWith('groupId', 3);
|
||||
});
|
||||
|
||||
it('should create a new group from pathstring if it does not exists', async () => {
|
||||
mockGitlabClient.Groups.search.mockResolvedValue([
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { GroupSchema } from '@gitbeaker/rest';
|
||||
import { GroupSchema, CreateGroupOptions } from '@gitbeaker/rest';
|
||||
import { getClient, parseRepoUrl } from '../util';
|
||||
import { examples } from './gitlabGroupEnsureExists.examples';
|
||||
|
||||
@@ -47,6 +47,12 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
description: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The group’s description',
|
||||
})
|
||||
.optional(),
|
||||
path: z =>
|
||||
z
|
||||
.array(
|
||||
@@ -77,8 +83,7 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
ctx.output('groupId', 42);
|
||||
return;
|
||||
}
|
||||
|
||||
const { token, repoUrl, path } = ctx.input;
|
||||
const { token, repoUrl, path, description } = ctx.input;
|
||||
|
||||
const { host } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
@@ -86,7 +91,10 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
|
||||
let currentPath: string | null = null;
|
||||
let parentId: number | null = null;
|
||||
for (const { name, slug } of pathIterator(path)) {
|
||||
const pathParts = [...pathIterator(path)];
|
||||
const lastIndex = pathParts.length - 1;
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const { name, slug } = pathParts[i];
|
||||
const fullPath: string = currentPath ? `${currentPath}/${slug}` : slug;
|
||||
const result = (await api.Groups.search(
|
||||
fullPath,
|
||||
@@ -101,17 +109,11 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
key: `ensure.${name}.${slug}.${parentId}`,
|
||||
// eslint-disable-next-line no-loop-func
|
||||
fn: async () => {
|
||||
return (
|
||||
await api.Groups.create(
|
||||
name,
|
||||
slug,
|
||||
parentId
|
||||
? {
|
||||
parentId: parentId,
|
||||
}
|
||||
: {},
|
||||
)
|
||||
)?.id;
|
||||
const groupOptions: CreateGroupOptions = {
|
||||
...(parentId ? { parentId } : {}),
|
||||
...(description && i === lastIndex ? { description } : {}),
|
||||
};
|
||||
return (await api.Groups.create(name, slug, groupOptions))?.id;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user