From 768d521c794b3969efd69a84587ec8e5762c0d29 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 09:22:06 +0200 Subject: [PATCH 01/16] feat: add publish:gitlab project settings support Signed-off-by: Ilya Katlinski --- .../builtin/publish/gitlab.examples.ts | 21 ++++++++++ .../actions/builtin/publish/gitlab.test.ts | 41 +++++++++++++++++++ .../actions/builtin/publish/gitlab.ts | 15 ++++++- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index ac259866e3..c010042701 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -68,4 +68,25 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: 'Initializes a git repository with additional settings.', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + settings: { + ci_config_path: '.gitlab-ci.yml', + visibility: 'public', + initialize_with_readme: true, + default_branch: 'main', + }, + }, + }, + ], + }), + }, ]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 994d1c580a..53b525a6bf 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -77,6 +77,26 @@ describe('publish:gitlab', () => { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, + settings: { + ci_config_path: '.gitlab-ci.yml', + }, + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + const mockContextWithOptions = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + topics: ['topic'], + settings: { + ci_config_path: '.gitlab-ci.yml', + visibility: 'internal', + topics: ['topic1', 'topic2'], + }, }, workspacePath: 'lol', logger: getVoidLogger(), @@ -162,6 +182,7 @@ describe('publish:gitlab', () => { namespace_id: 1234, name: 'repo', visibility: 'private', + ci_config_path: '.gitlab-ci.yml', }); }); @@ -179,6 +200,26 @@ describe('publish:gitlab', () => { namespace_id: 12345, name: 'repo', visibility: 'private', + ci_config_path: '.gitlab-ci.yml', + }); + }); + + it('should call the correct Gitlab APIs when using project options with override of visibility and topics', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithOptions); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'internal', + topics: ['topic1', 'topic2'], + ci_config_path: '.gitlab-ci.yml', }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index dbab7b11b8..302d006e05 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -38,6 +38,7 @@ export function createPublishGitlabAction(options: { return createTemplateAction<{ repoUrl: string; defaultBranch?: string; + /** @deprecated in favour of settings field */ repoVisibility?: 'private' | 'internal' | 'public'; sourcePath?: string; token?: string; @@ -45,7 +46,9 @@ export function createPublishGitlabAction(options: { gitAuthorName?: string; gitAuthorEmail?: string; setUserAsOwner?: boolean; + /** @deprecated in favour of settings field */ topics?: string[]; + settings?: Record; }>({ id: 'publish:gitlab', description: @@ -63,6 +66,7 @@ export function createPublishGitlabAction(options: { }, repoVisibility: { title: 'Repository Visibility', + description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings instead)`, type: 'string', enum: ['private', 'public', 'internal'], }, @@ -105,12 +109,19 @@ export function createPublishGitlabAction(options: { }, topics: { title: 'Topic labels', - description: 'Topic labels to apply on the repository.', + description: + 'Topic labels to apply on the repository. (deprecated, use settings instead)', type: 'array', items: { type: 'string', }, }, + settings: { + title: 'Project settings', + description: + 'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes', + type: 'object', + }, }, }, output: { @@ -145,6 +156,7 @@ export function createPublishGitlabAction(options: { gitAuthorEmail, setUserAsOwner = false, topics = [], + settings = {}, } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -191,6 +203,7 @@ export function createPublishGitlabAction(options: { name: repo, visibility: repoVisibility, ...(topics.length ? { topics } : {}), + ...(Object.keys(settings).length ? { ...settings } : {}), }); // When setUserAsOwner is true the input token is expected to come from an unprivileged user GitLab From ec8c69d9c38665488bc9aafa5e0f5d5efe0a03e1 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 10:13:59 +0200 Subject: [PATCH 02/16] feat: add publish:gitlab branches configuration support Signed-off-by: Ilya Katlinski --- .../src/scaffolder/actions/builtin/helpers.ts | 4 + .../builtin/publish/gitlab.examples.ts | 27 ++++++ .../actions/builtin/publish/gitlab.test.ts | 87 ++++++++++++++++++- .../actions/builtin/publish/gitlab.ts | 73 +++++++++++++++- 4 files changed, 187 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 5ac92128ca..1ea3a13687 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -251,3 +251,7 @@ export function getGitCommitMessage( export function entityRefToName(name: string): string { return name.replace(/^.*[:/]/g, ''); } + +export function printGitlabError(error: any): string { + return JSON.stringify({ code: error.code, message: error.description }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index c010042701..a2f5a20745 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -89,4 +89,31 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: 'Initializes a git repository with branches settings', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + branches: [ + { + name: 'dev', + create: true, + protected: true, + ref: 'master', + }, + { + name: 'master', + protected: true, + }, + ], + }, + }, + ], + }), + }, ]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 53b525a6bf..59d05eb226 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -45,6 +45,12 @@ const mockGitlabClient = { ProjectMembers: { add: jest.fn(), }, + Branches: { + create: jest.fn(), + }, + ProtectedBranches: { + protect: jest.fn(), + }, }; jest.mock('@gitbeaker/node', () => ({ Gitlab: class { @@ -87,7 +93,7 @@ describe('publish:gitlab', () => { output: jest.fn(), createTemporaryDirectory: jest.fn(), }; - const mockContextWithOptions = { + const mockContextWithSettings = { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, @@ -104,6 +110,33 @@ describe('publish:gitlab', () => { output: jest.fn(), createTemporaryDirectory: jest.fn(), }; + const mockContextWithBranches = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + branches: [ + { + name: 'dev', + create: true, + ref: 'master', + protect: true, + }, + { + name: 'stage', + create: true, + }, + { + name: 'perf', + protect: true, + }, + ], + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; beforeEach(() => { jest.resetAllMocks(); @@ -166,6 +199,8 @@ describe('publish:gitlab', () => { name: 'bob', visibility: 'private', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); }); it('should call the correct Gitlab APIs when the owner is an organization', async () => { @@ -184,6 +219,8 @@ describe('publish:gitlab', () => { visibility: 'private', ci_config_path: '.gitlab-ci.yml', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); }); it('should call the correct Gitlab APIs when the owner is not an organization', async () => { @@ -202,16 +239,18 @@ describe('publish:gitlab', () => { visibility: 'private', ci_config_path: '.gitlab-ci.yml', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); }); - it('should call the correct Gitlab APIs when using project options with override of visibility and topics', async () => { + it('should call the correct Gitlab APIs when using project settings with override of visibility and topics', async () => { mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); mockGitlabClient.Projects.create.mockResolvedValue({ http_url_to_repo: 'http://mockurl.git', }); - await action.handler(mockContextWithOptions); + await action.handler(mockContextWithSettings); expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ @@ -221,6 +260,48 @@ describe('publish:gitlab', () => { topics: ['topic1', 'topic2'], ci_config_path: '.gitlab-ci.yml', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); + }); + + it('should call the correct Gitlab APIs for branches and protectd branches when branch settings provided', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + id: 123456, + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithBranches); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'private', + }); + expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(2); + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledTimes(2); + + expect(mockGitlabClient.Branches.create).toHaveBeenCalledWith( + 123456, + 'dev', + 'master', + ); + expect(mockGitlabClient.Branches.create).toHaveBeenCalledWith( + 123456, + 'stage', + 'master', + ); + + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledWith( + 123456, + 'dev', + ); + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledWith( + 123456, + 'perf', + ); }); it('should call initRepoAndPush with the correct values', async () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 302d006e05..68205d05e9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -18,7 +18,7 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { Gitlab } from '@gitbeaker/node'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush, printGitlabError } from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; import { examples } from './gitlab.examples'; @@ -49,6 +49,12 @@ export function createPublishGitlabAction(options: { /** @deprecated in favour of settings field */ topics?: string[]; settings?: Record; + branches?: Array<{ + name: string; + protect?: boolean; + create?: boolean; + ref?: string; + }>; }>({ id: 'publish:gitlab', description: @@ -122,6 +128,35 @@ export function createPublishGitlabAction(options: { 'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes', type: 'object', }, + branches: { + title: 'Project branches settings', + type: 'array', + items: { + type: 'object', + required: ['name'], + properties: { + name: { + title: 'Branch name', + type: 'string', + }, + protect: { + title: 'Should branch be protected', + description: `Will mark branch as protected. The default value is 'false'`, + type: 'boolean', + }, + create: { + title: 'Should branch be created', + description: `If branch does not exist, it will be created from provided ref. The default value is 'false'`, + type: 'boolean', + }, + ref: { + title: 'Branch reference', + description: `Branch reference to create branch from. The default value is 'master'`, + type: 'string', + }, + }, + }, + }, }, }, output: { @@ -157,6 +192,7 @@ export function createPublishGitlabAction(options: { setUserAsOwner = false, topics = [], settings = {}, + branches = [], } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -247,6 +283,41 @@ export function createPublishGitlabAction(options: { gitAuthorInfo, }); + if (branches) { + for (const branch of branches) { + const { + name, + protect = false, + create = false, + ref = 'master', + } = branch; + + if (create) { + try { + await client.Branches.create(projectId, name, ref); + } catch (e) { + throw new InputError( + `Branch creation failed for ${name}. ${printGitlabError(e)}`, + ); + } + ctx.logger.info( + `Branch ${name} created for ${projectId} with ref ${ref}`, + ); + } + + if (protect) { + try { + await client.ProtectedBranches.protect(projectId, name); + } catch (e) { + throw new InputError( + `Branch protection failed for ${name}. ${printGitlabError(e)}`, + ); + } + ctx.logger.info(`Branch ${name} protected for ${projectId}`); + } + } + } + ctx.output('commitHash', commitResult?.commitHash); ctx.output('remoteUrl', remoteUrl); ctx.output('repoContentsUrl', repoContentsUrl); From 3e3bf5311e7cef01a5a2609c79c2a410833c3d3b Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 10:18:10 +0200 Subject: [PATCH 03/16] doc: generate api reports for scaffolder plugin Signed-off-by: Ilya Katlinski --- plugins/scaffolder-backend/api-report.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 17e13131cf..46960d4358 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -679,6 +679,15 @@ export function createPublishGitlabAction(options: { gitAuthorEmail?: string | undefined; setUserAsOwner?: boolean | undefined; topics?: string[] | undefined; + settings?: Record | undefined; + branches?: + | { + name: string; + protect?: boolean | undefined; + create?: boolean | undefined; + ref?: string | undefined; + }[] + | undefined; }, JsonObject >; From dea0aafda7f6aba3fe763bc99054af09744a157b Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 10:23:26 +0200 Subject: [PATCH 04/16] doc: update changeset and bumped minor version Signed-off-by: Ilya Katlinski --- .changeset/khaki-tools-tease.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/khaki-tools-tease.md diff --git a/.changeset/khaki-tools-tease.md b/.changeset/khaki-tools-tease.md new file mode 100644 index 0000000000..c066aaf6e0 --- /dev/null +++ b/.changeset/khaki-tools-tease.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Updated publish:gitlab action properties to support project and branches level configuration. +Project level configuration is based on the Gitlab Project Create API available options. Is is available via `settings` property. +Branch level configuration allow to create additional branches and make them protected. It is available via `branches` property. + +Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. From 0f76f34081ae20b1711a72ad8d1aa94ca47e9cbb Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 12:15:56 +0200 Subject: [PATCH 05/16] feat: add publish:gitlab variables configuration support Signed-off-by: Ilya Katlinski --- .changeset/khaki-tools-tease.md | 8 +- plugins/scaffolder-backend/api-report.md | 12 +++ .../builtin/publish/gitlab.examples.ts | 29 +++++++ .../actions/builtin/publish/gitlab.test.ts | 55 ++++++++++++ .../actions/builtin/publish/gitlab.ts | 85 +++++++++++++++++++ 5 files changed, 186 insertions(+), 3 deletions(-) diff --git a/.changeset/khaki-tools-tease.md b/.changeset/khaki-tools-tease.md index c066aaf6e0..a133a881bb 100644 --- a/.changeset/khaki-tools-tease.md +++ b/.changeset/khaki-tools-tease.md @@ -2,8 +2,10 @@ '@backstage/plugin-scaffolder-backend': minor --- -Updated publish:gitlab action properties to support project and branches level configuration. -Project level configuration is based on the Gitlab Project Create API available options. Is is available via `settings` property. -Branch level configuration allow to create additional branches and make them protected. It is available via `branches` property. +Updated publish:gitlab action properties to support additional Gitlab project settings: + +- general project settings provided by gitlab project create API (new `settings` property) +- branch level settings to create additional branches and make them protected (new `branches` property) +- project level environment variables settings (new `variables` property) Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 46960d4358..dae0cd536b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -688,6 +688,18 @@ export function createPublishGitlabAction(options: { ref?: string | undefined; }[] | undefined; + variables?: + | { + key: string; + value: string; + description?: string | undefined; + variable_type?: string | undefined; + protected?: boolean | undefined; + masked?: boolean | undefined; + raw?: boolean | undefined; + environment_scope?: string | undefined; + }[] + | undefined; }, JsonObject >; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index a2f5a20745..52ced84ac8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -116,4 +116,33 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: 'Initializes a git repository with environment variables', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + variables: [ + { + key: 'key1', + value: 'value1', + protected: true, + masked: false, + }, + { + key: 'key2', + value: 'value2', + protected: true, + masked: false, + }, + ], + }, + }, + ], + }), + }, ]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 59d05eb226..4a6019a48e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -51,6 +51,9 @@ const mockGitlabClient = { ProtectedBranches: { protect: jest.fn(), }, + ProjectVariables: { + create: jest.fn(), + }, }; jest.mock('@gitbeaker/node', () => ({ Gitlab: class { @@ -137,6 +140,26 @@ describe('publish:gitlab', () => { output: jest.fn(), createTemporaryDirectory: jest.fn(), }; + const mockContextWithVariables = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + variables: [ + { + key: 'key', + value: 'value', + description: 'description', + protected: true, + masked: true, + }, + ], + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; beforeEach(() => { jest.resetAllMocks(); @@ -304,6 +327,38 @@ describe('publish:gitlab', () => { ); }); + it('should call the correct Gitlab APIs for variables when their configuration is provided', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + id: 123456, + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithVariables); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'private', + }); + + expect(mockGitlabClient.ProjectVariables.create).toHaveBeenCalledWith( + 123456, + { + key: 'key', + value: 'value', + description: 'description', + variable_type: 'env_var', + protected: true, + masked: true, + raw: false, + environment_scope: '*', + }, + ); + }); + it('should call initRepoAndPush with the correct values', async () => { mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 68205d05e9..c715bffcd6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -55,6 +55,16 @@ export function createPublishGitlabAction(options: { create?: boolean; ref?: string; }>; + variables?: Array<{ + key: string; + value: string; + description?: string; + variable_type?: string; + protected?: boolean; + masked?: boolean; + raw?: boolean; + environment_scope?: string; + }>; }>({ id: 'publish:gitlab', description: @@ -157,6 +167,55 @@ export function createPublishGitlabAction(options: { }, }, }, + variables: { + title: 'Project variables', + description: + 'Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable', + type: 'array', + items: { + type: 'object', + required: ['key', 'value'], + properties: { + key: { + title: 'Variable key', + description: + 'The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed', + type: 'string', + }, + value: { + title: 'Variable value', + description: 'The value of a variable', + type: 'string', + }, + description: { + title: 'Variable description', + description: `The description of the variable. The default value is 'null'`, + type: 'string', + }, + variable_type: { + title: 'Variable type', + description: `The type of a variable. The default value is 'env_var'`, + type: 'string', + enum: ['env_var', 'file'], + }, + protected: { + title: 'Variable protection', + description: `Whether the variable is protected. The default value is 'false'`, + type: 'boolean', + }, + raw: { + title: 'Variable raw', + description: `Whether the variable is in raw format. The default value is 'false'`, + type: 'boolean', + }, + environment_scope: { + title: 'Variable environment scope', + description: `The environment_scope of the variable. The default value is '*'`, + type: 'string', + }, + }, + }, + }, }, }, output: { @@ -193,6 +252,7 @@ export function createPublishGitlabAction(options: { topics = [], settings = {}, branches = [], + variables = [], } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -318,6 +378,31 @@ export function createPublishGitlabAction(options: { } } + if (variables) { + for (const variable of variables) { + const variableWithDefaults = Object.assign(variable, { + variable_type: variable.variable_type ?? 'env_var', + protected: variable.protected ?? false, + masked: variable.masked ?? false, + raw: variable.raw ?? false, + environment_scope: variable.environment_scope ?? '*', + }); + + try { + await client.ProjectVariables.create( + projectId, + variableWithDefaults, + ); + } catch (e) { + throw new InputError( + `Environment variable creation failed for ${ + variableWithDefaults.key + }. ${printGitlabError(e)}`, + ); + } + } + } + ctx.output('commitHash', commitResult?.commitHash); ctx.output('remoteUrl', remoteUrl); ctx.output('repoContentsUrl', repoContentsUrl); From 09cdef6eca2f138d196bfe55dcbd0f16f9268965 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 16:42:25 +0200 Subject: [PATCH 06/16] chore: add explicit replacements for deprecated properties Signed-off-by: Ilya Katlinski --- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index c715bffcd6..ee9be04a3d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -38,7 +38,7 @@ export function createPublishGitlabAction(options: { return createTemplateAction<{ repoUrl: string; defaultBranch?: string; - /** @deprecated in favour of settings field */ + /** @deprecated in favour of settings.visibility field */ repoVisibility?: 'private' | 'internal' | 'public'; sourcePath?: string; token?: string; @@ -46,7 +46,7 @@ export function createPublishGitlabAction(options: { gitAuthorName?: string; gitAuthorEmail?: string; setUserAsOwner?: boolean; - /** @deprecated in favour of settings field */ + /** @deprecated in favour of settings.topics field */ topics?: string[]; settings?: Record; branches?: Array<{ @@ -82,7 +82,7 @@ export function createPublishGitlabAction(options: { }, repoVisibility: { title: 'Repository Visibility', - description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings instead)`, + description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`, type: 'string', enum: ['private', 'public', 'internal'], }, @@ -126,7 +126,7 @@ export function createPublishGitlabAction(options: { topics: { title: 'Topic labels', description: - 'Topic labels to apply on the repository. (deprecated, use settings instead)', + 'Topic labels to apply on the repository. (deprecated, use settings.topics instead)', type: 'array', items: { type: 'string', From 9ef04db9f09ff185b5151631eb49a137c8f29489 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 15 Sep 2023 17:30:44 +0200 Subject: [PATCH 07/16] test: fix incosistent test failures with time Signed-off-by: Ilya Katlinski --- .../src/scaffolder/actions/builtin/debug/wait.examples.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts index 595ae7c3b6..fc68b82d1e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts @@ -56,6 +56,7 @@ describe('debug:wait examples', () => { const start = new Date().getTime(); await action.handler(context); const end = new Date().getTime(); - expect(end - start).toBeGreaterThanOrEqual(50); + expect(end - start).toBeGreaterThanOrEqual(45); + expect(end - start).toBeLessThanOrEqual(55); }); }); From bbb2a00fd3a11ad22410298ff5ff8af2df906f70 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Mon, 2 Oct 2023 15:04:12 +0200 Subject: [PATCH 08/16] fix: rename variables to projectVariables for publish:gitlab action Signed-off-by: Ilya Katlinski --- .../actions/builtin/publish/gitlab.examples.ts | 2 +- .../scaffolder/actions/builtin/publish/gitlab.test.ts | 2 +- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index 52ced84ac8..468fa03fba 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -126,7 +126,7 @@ export const examples: TemplateExample[] = [ name: 'Publish to GitLab', input: { repoUrl: 'gitlab.com?repo=project_name&owner=group_name', - variables: [ + projectVariables: [ { key: 'key1', value: 'value1', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 4a6019a48e..c8afc3b07b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -144,7 +144,7 @@ describe('publish:gitlab', () => { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, - variables: [ + projectVariables: [ { key: 'key', value: 'value', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index ee9be04a3d..52c0409870 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -55,7 +55,7 @@ export function createPublishGitlabAction(options: { create?: boolean; ref?: string; }>; - variables?: Array<{ + projectVariables?: Array<{ key: string; value: string; description?: string; @@ -167,7 +167,7 @@ export function createPublishGitlabAction(options: { }, }, }, - variables: { + projectVariables: { title: 'Project variables', description: 'Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable', @@ -252,7 +252,7 @@ export function createPublishGitlabAction(options: { topics = [], settings = {}, branches = [], - variables = [], + projectVariables = [], } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -378,8 +378,8 @@ export function createPublishGitlabAction(options: { } } - if (variables) { - for (const variable of variables) { + if (projectVariables) { + for (const variable of projectVariables) { const variableWithDefaults = Object.assign(variable, { variable_type: variable.variable_type ?? 'env_var', protected: variable.protected ?? false, From 4bed80bb6ef77dd4b63e56d2bf06d8ce79bf4aee Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Mon, 2 Oct 2023 15:05:21 +0200 Subject: [PATCH 09/16] fix: update release notes with styling and project variables description Signed-off-by: Ilya Katlinski --- .changeset/khaki-tools-tease.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/khaki-tools-tease.md b/.changeset/khaki-tools-tease.md index a133a881bb..9b193f9fd8 100644 --- a/.changeset/khaki-tools-tease.md +++ b/.changeset/khaki-tools-tease.md @@ -2,10 +2,10 @@ '@backstage/plugin-scaffolder-backend': minor --- -Updated publish:gitlab action properties to support additional Gitlab project settings: +Updated `publish:gitlab`` action properties to support additional Gitlab project settings: - general project settings provided by gitlab project create API (new `settings` property) - branch level settings to create additional branches and make them protected (new `branches` property) -- project level environment variables settings (new `variables` property) +- project level environment variables settings (new `projectVariables` property) Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. From feb08fcfc6cf421d74c2cd8e6e269a2869fec4ad Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Mon, 2 Oct 2023 15:15:28 +0200 Subject: [PATCH 10/16] chore: update api report with projectVariable changes Signed-off-by: Ilya Katlinski --- plugins/scaffolder-backend/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index dae0cd536b..531fb257f3 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -688,7 +688,7 @@ export function createPublishGitlabAction(options: { ref?: string | undefined; }[] | undefined; - variables?: + projectVariables?: | { key: string; value: string; From c6b3d7430ec71b568a249bc09a8299413fd3815d Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 6 Oct 2023 08:44:47 +0200 Subject: [PATCH 11/16] feat: add typing support for gitlab project settings Signed-off-by: Ilya Katlinski --- .../actions/builtin/publish/gitlab.ts | 105 +++++++++++++++--- .../actions/builtin/publish/gitlab.types.ts | 47 ++++++++ 2 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 52c0409870..32d07eec6b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -22,6 +22,11 @@ import { initRepoAndPush, printGitlabError } from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; import { examples } from './gitlab.examples'; +import { + GitlabBranchSettings, + GitlabProjectSettings, + GitlabProjectVariableSettings, +} from './gitlab.types'; /** * Creates a new action that initializes a git repository of the content in the workspace @@ -48,23 +53,9 @@ export function createPublishGitlabAction(options: { setUserAsOwner?: boolean; /** @deprecated in favour of settings.topics field */ topics?: string[]; - settings?: Record; - branches?: Array<{ - name: string; - protect?: boolean; - create?: boolean; - ref?: string; - }>; - projectVariables?: Array<{ - key: string; - value: string; - description?: string; - variable_type?: string; - protected?: boolean; - masked?: boolean; - raw?: boolean; - environment_scope?: string; - }>; + settings?: GitlabProjectSettings; + branches?: Array; + projectVariables?: Array; }>({ id: 'publish:gitlab', description: @@ -137,6 +128,86 @@ export function createPublishGitlabAction(options: { description: 'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes', type: 'object', + properties: { + name: { + title: 'Project name', + description: + 'The name of the new project. Equals path if not provided.', + type: 'string', + }, + path: { + title: 'Project path', + description: + 'Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).', + type: 'string', + }, + auto_devops_enabled: { + title: 'Auto DevOps enabled', + description: 'Enable Auto DevOps for this project', + type: 'boolean', + }, + ci_config_path: { + title: 'CI config path', + description: 'Custom CI config path for this project', + type: 'string', + }, + description: { + title: 'Project description', + description: 'Short project description', + type: 'string', + }, + namespace_id: { + title: 'Namespace ID', + description: + 'Namespace for the new project (defaults to the current user’s namespace)', + type: 'number', + }, + topics: { + title: 'Topic labels', + description: 'Topic labels to apply on the repository', + type: 'array', + items: { + type: 'string', + }, + }, + visibility: { + title: 'Project visibility', + description: + 'The visibility of the project. Can be private, internal, or public. The default value is private.', + type: 'string', + enum: ['private', 'public', 'internal'], + }, + group_runners_enabled: { + title: 'Group runners enabled', + description: 'Enable group runners for this project', + type: 'boolean', + }, + emails_enabled: { + title: 'Emails enabled', + description: 'Send email notifications', + type: 'boolean', + }, + container_registry_access_level: { + title: 'Container registry access level', + description: + 'Configure the container registry to be enabled or disabled', + type: 'string', + enum: ['disabled', 'private', 'enabled'], + }, + builds_access_level: { + title: 'Builds access level', + description: 'Configure the builds to be enabled or disabled', + type: 'string', + enum: ['disabled', 'private', 'enabled'], + }, + auto_cancel_pending_pipelines: { + title: 'Auto cancel pending pipelines', + description: + 'Enable auto-cancel of pipelines for branches that have newer commits', + type: 'string', + enum: ['disabled', 'enabled'], + }, + }, }, branches: { title: 'Project branches settings', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts new file mode 100644 index 0000000000..8882df8fec --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2021 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. + */ + +export type GitlabProjectSettings = ({ name: string } | { path: string }) & { + auto_devops_enabled?: boolean; + ci_config_path?: string; + description?: string; + namespace_id?: number; + topics?: string[]; + visibility: 'private' | 'internal' | 'public'; + group_runners_enabled?: boolean; + emails_enabled?: boolean; + container_registry_access_level?: 'disabled' | 'private' | 'enabled'; + builds_access_level?: 'disabled' | 'private' | 'enabled'; + auto_cancel_pending_pipelines?: 'disabled' | 'enabled'; +}; + +export type GitlabBranchSettings = { + name: string; + protect?: boolean; + create?: boolean; + ref?: string; +}; + +export type GitlabProjectVariableSettings = { + key: string; + value: string; + description?: string; + variable_type?: string; + protected?: boolean; + masked?: boolean; + raw?: boolean; + environment_scope?: string; +}; From 9fa972edea1def0edc0a484579590ee0664dec7f Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 6 Oct 2023 08:48:45 +0200 Subject: [PATCH 12/16] feat: update types for gitlab project settings Signed-off-by: Ilya Katlinski --- .../src/scaffolder/actions/builtin/publish/gitlab.test.ts | 2 +- .../src/scaffolder/actions/builtin/publish/gitlab.types.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index c723db4a7f..b2f3dc6480 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -103,7 +103,7 @@ describe('publish:gitlab', () => { topics: ['topic'], settings: { ci_config_path: '.gitlab-ci.yml', - visibility: 'internal', + visibility: 'internal' as const, topics: ['topic1', 'topic2'], }, }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts index 8882df8fec..46bf1c4882 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts @@ -14,13 +14,14 @@ * limitations under the License. */ -export type GitlabProjectSettings = ({ name: string } | { path: string }) & { +export type GitlabProjectSettings = { + path?: string; auto_devops_enabled?: boolean; ci_config_path?: string; description?: string; namespace_id?: number; topics?: string[]; - visibility: 'private' | 'internal' | 'public'; + visibility?: 'private' | 'internal' | 'public'; group_runners_enabled?: boolean; emails_enabled?: boolean; container_registry_access_level?: 'disabled' | 'private' | 'enabled'; From 7f51b8777d013380cc0043327c0612d2a75e1522 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 6 Oct 2023 08:50:53 +0200 Subject: [PATCH 13/16] feat: update gitlab examples for project settings Signed-off-by: Ilya Katlinski --- .../src/scaffolder/actions/builtin/publish/gitlab.examples.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index 468fa03fba..b20fcf52e9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -81,8 +81,6 @@ export const examples: TemplateExample[] = [ settings: { ci_config_path: '.gitlab-ci.yml', visibility: 'public', - initialize_with_readme: true, - default_branch: 'main', }, }, }, From 62a64275b32bb094ff33289c65f5f5d32b120c88 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 6 Oct 2023 09:02:25 +0200 Subject: [PATCH 14/16] feat: reduce number of gitlab project settings Signed-off-by: Ilya Katlinski --- .../actions/builtin/publish/gitlab.ts | 42 ------------------- .../actions/builtin/publish/gitlab.types.ts | 6 --- 2 files changed, 48 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 515af53c7b..d0886e85a3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -129,12 +129,6 @@ export function createPublishGitlabAction(options: { 'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes', type: 'object', properties: { - name: { - title: 'Project name', - description: - 'The name of the new project. Equals path if not provided.', - type: 'string', - }, path: { title: 'Project path', description: @@ -156,12 +150,6 @@ export function createPublishGitlabAction(options: { description: 'Short project description', type: 'string', }, - namespace_id: { - title: 'Namespace ID', - description: - 'Namespace for the new project (defaults to the current user’s namespace)', - type: 'number', - }, topics: { title: 'Topic labels', description: 'Topic labels to apply on the repository', @@ -177,36 +165,6 @@ export function createPublishGitlabAction(options: { type: 'string', enum: ['private', 'public', 'internal'], }, - group_runners_enabled: { - title: 'Group runners enabled', - description: 'Enable group runners for this project', - type: 'boolean', - }, - emails_enabled: { - title: 'Emails enabled', - description: 'Send email notifications', - type: 'boolean', - }, - container_registry_access_level: { - title: 'Container registry access level', - description: - 'Configure the container registry to be enabled or disabled', - type: 'string', - enum: ['disabled', 'private', 'enabled'], - }, - builds_access_level: { - title: 'Builds access level', - description: 'Configure the builds to be enabled or disabled', - type: 'string', - enum: ['disabled', 'private', 'enabled'], - }, - auto_cancel_pending_pipelines: { - title: 'Auto cancel pending pipelines', - description: - 'Enable auto-cancel of pipelines for branches that have newer commits', - type: 'string', - enum: ['disabled', 'enabled'], - }, }, }, branches: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts index 46bf1c4882..0a6be3e801 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts @@ -19,14 +19,8 @@ export type GitlabProjectSettings = { auto_devops_enabled?: boolean; ci_config_path?: string; description?: string; - namespace_id?: number; topics?: string[]; visibility?: 'private' | 'internal' | 'public'; - group_runners_enabled?: boolean; - emails_enabled?: boolean; - container_registry_access_level?: 'disabled' | 'private' | 'enabled'; - builds_access_level?: 'disabled' | 'private' | 'enabled'; - auto_cancel_pending_pipelines?: 'disabled' | 'enabled'; }; export type GitlabBranchSettings = { From b847ef3a1d41075b76d3dc0e8b645c265a22f651 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Fri, 6 Oct 2023 09:28:15 +0200 Subject: [PATCH 15/16] feat: update api report Signed-off-by: Ilya Katlinski --- plugins/scaffolder-backend/api-report.md | 11 ++++- .../actions/builtin/publish/gitlab.ts | 32 ++++++++++---- .../actions/builtin/publish/gitlab.types.ts | 42 ------------------- 3 files changed, 34 insertions(+), 51 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 531fb257f3..ba7576b1bb 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -679,7 +679,16 @@ export function createPublishGitlabAction(options: { gitAuthorEmail?: string | undefined; setUserAsOwner?: boolean | undefined; topics?: string[] | undefined; - settings?: Record | undefined; + settings?: + | { + path?: string | undefined; + auto_devops_enabled?: boolean | undefined; + ci_config_path?: string | undefined; + description?: string | undefined; + topics?: string[] | undefined; + visibility?: 'internal' | 'private' | 'public' | undefined; + } + | undefined; branches?: | { name: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index d0886e85a3..4933ad6e69 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -22,11 +22,6 @@ import { initRepoAndPush, printGitlabError } from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; import { examples } from './gitlab.examples'; -import { - GitlabBranchSettings, - GitlabProjectSettings, - GitlabProjectVariableSettings, -} from './gitlab.types'; /** * Creates a new action that initializes a git repository of the content in the workspace @@ -53,9 +48,30 @@ export function createPublishGitlabAction(options: { setUserAsOwner?: boolean; /** @deprecated in favour of settings.topics field */ topics?: string[]; - settings?: GitlabProjectSettings; - branches?: Array; - projectVariables?: Array; + settings?: { + path?: string; + auto_devops_enabled?: boolean; + ci_config_path?: string; + description?: string; + topics?: string[]; + visibility?: 'private' | 'internal' | 'public'; + }; + branches?: Array<{ + name: string; + protect?: boolean; + create?: boolean; + ref?: string; + }>; + projectVariables?: Array<{ + key: string; + value: string; + description?: string; + variable_type?: string; + protected?: boolean; + masked?: boolean; + raw?: boolean; + environment_scope?: string; + }>; }>({ id: 'publish:gitlab', description: diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts deleted file mode 100644 index 0a6be3e801..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.types.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2021 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. - */ - -export type GitlabProjectSettings = { - path?: string; - auto_devops_enabled?: boolean; - ci_config_path?: string; - description?: string; - topics?: string[]; - visibility?: 'private' | 'internal' | 'public'; -}; - -export type GitlabBranchSettings = { - name: string; - protect?: boolean; - create?: boolean; - ref?: string; -}; - -export type GitlabProjectVariableSettings = { - key: string; - value: string; - description?: string; - variable_type?: string; - protected?: boolean; - masked?: boolean; - raw?: boolean; - environment_scope?: string; -}; From 0da78e017fc974f7e4b634b11c4a2ce9b35a54b2 Mon Sep 17 00:00:00 2001 From: Ilya Katlinski Date: Tue, 10 Oct 2023 12:49:11 +0200 Subject: [PATCH 16/16] chore(comment): fix changeset and move gitlab error processing Signed-off-by: Ilya Katlinski --- .changeset/khaki-tools-tease.md | 2 +- .../src/scaffolder/actions/builtin/helpers.ts | 4 ---- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 6 +++++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.changeset/khaki-tools-tease.md b/.changeset/khaki-tools-tease.md index 9b193f9fd8..e4383c9e33 100644 --- a/.changeset/khaki-tools-tease.md +++ b/.changeset/khaki-tools-tease.md @@ -2,7 +2,7 @@ '@backstage/plugin-scaffolder-backend': minor --- -Updated `publish:gitlab`` action properties to support additional Gitlab project settings: +Updated `publish:gitlab` action properties to support additional Gitlab project settings: - general project settings provided by gitlab project create API (new `settings` property) - branch level settings to create additional branches and make them protected (new `branches` property) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 1ea3a13687..5ac92128ca 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -251,7 +251,3 @@ export function getGitCommitMessage( export function entityRefToName(name: string): string { return name.replace(/^.*[:/]/g, ''); } - -export function printGitlabError(error: any): string { - return JSON.stringify({ code: error.code, message: error.description }); -} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 4933ad6e69..6d86841a20 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -18,7 +18,7 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { Gitlab } from '@gitbeaker/node'; -import { initRepoAndPush, printGitlabError } from '../helpers'; +import { initRepoAndPush } from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; import { examples } from './gitlab.examples'; @@ -468,3 +468,7 @@ export function createPublishGitlabAction(options: { }, }); } + +function printGitlabError(error: any): string { + return JSON.stringify({ code: error.code, message: error.description }); +}