diff --git a/.changeset/dirty-doors-wave.md b/.changeset/dirty-doors-wave.md new file mode 100644 index 0000000000..aad6e8f414 --- /dev/null +++ b/.changeset/dirty-doors-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add examples for `github:issues:label` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts new file mode 100644 index 0000000000..9d74d53c6d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { PassThrough } from 'stream'; +import { createGithubIssuesLabelAction } from './githubIssuesLabel'; +import yaml from 'yaml'; +import { examples } from './githubIssuesLabel.examples'; +import { getOctokitOptions } from './helpers'; + +jest.mock('./helpers', () => { + return { + getOctokitOptions: jest.fn(), + }; +}); + +const mockOctokit = { + rest: { + issues: { + addLabels: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('github:issues:label examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const getOctokitOptionsMock = getOctokitOptions as jest.Mock; + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubIssuesLabelAction({ + integrations, + githubCredentialsProvider, + }); + }); + + afterEach(jest.resetAllMocks); + + it('should call the githubApi for adding labels without token', async () => { + await action.handler({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }); + + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['bug'], + }); + + expect(getOctokitOptionsMock.mock.calls[0][0].token).toBeUndefined(); + }); + + it('should call the githubApi for adding labels with token', async () => { + await action.handler({ + ...mockContext, + input: yaml.parse(examples[1].example).steps[0].input, + }); + + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['bug', 'documentation'], + }); + + expect(getOctokitOptionsMock.mock.calls[0][0].token).toEqual( + 'gph_YourGitHubToken', + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts new file mode 100644 index 0000000000..e0f631df7b --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts @@ -0,0 +1,54 @@ +/* + * 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: 'Add labels to pull request or issue', + example: yaml.stringify({ + steps: [ + { + action: 'github:issues:label', + name: 'Add labels to pull request or issue', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + number: '1', + labels: ['bug'], + }, + }, + ], + }), + }, + { + description: 'Add labels to pull request or issue with specific token', + example: yaml.stringify({ + steps: [ + { + action: 'github:issues:label', + name: 'Add labels to pull request or issue with token', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + number: '1', + labels: ['bug', 'documentation'], + token: 'gph_YourGitHubToken', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts index a1a0274304..3da16e677a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts @@ -24,6 +24,13 @@ import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { PassThrough } from 'stream'; +import { getOctokitOptions } from './helpers'; + +jest.mock('./helpers', () => { + return { + getOctokitOptions: jest.fn(), + }; +}); const mockOctokit = { rest: { @@ -50,6 +57,7 @@ describe('github:issues:label', () => { }, }); + const getOctokitOptionsMock = getOctokitOptions as jest.Mock; const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; @@ -85,5 +93,22 @@ describe('github:issues:label', () => { issue_number: '1', labels: ['label1', 'label2'], }); + expect(getOctokitOptionsMock.mock.calls[0][0].token).toBeUndefined(); + }); + + it('should call the githubApi for adding labels with token', async () => { + await action.handler({ + ...mockContext, + input: { ...mockContext.input, token: 'gph_YourGitHubToken' }, + }); + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['label1', 'label2'], + }); + expect(getOctokitOptionsMock.mock.calls[0][0].token).toEqual( + 'gph_YourGitHubToken', + ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts index 2dad0aa33a..73a65ffb14 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts @@ -23,6 +23,7 @@ import { assertError, InputError } from '@backstage/errors'; import { Octokit } from 'octokit'; import { getOctokitOptions } from './helpers'; import { parseRepoUrl } from '../publish/util'; +import { examples } from './githubIssuesLabel.examples'; /** * Adds labels to a pull request or issue on GitHub @@ -42,6 +43,7 @@ export function createGithubIssuesLabelAction(options: { }>({ id: 'github:issues:label', description: 'Adds labels to a pull request or issue on GitHub.', + examples, schema: { input: { type: 'object',