diff --git a/.changeset/tame-spies-hunt.md b/.changeset/tame-spies-hunt.md new file mode 100644 index 0000000000..5a45defb7e --- /dev/null +++ b/.changeset/tame-spies-hunt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Add examples for `github:deployKey:create` scaffolder action & improve related tests diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.test.ts new file mode 100644 index 0000000000..c8e2a5f102 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.test.ts @@ -0,0 +1,111 @@ +/* + * 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 { createGithubDeployKeyAction } from './githubDeployKey'; +import yaml from 'yaml'; +import { examples } from './githubDeployKey.examples'; +import { PassThrough } from 'stream'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; + +const mockOctokit = { + rest: { + repos: { + createDeployKey: jest.fn(), + }, + actions: { + getRepoPublicKey: jest.fn(), + createOrUpdateRepoSecret: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +const publicKey = '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU='; + +describe('Usage examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + const integrations = ScmIntegrations.fromConfig(config); + let action: TemplateAction; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + + action = createGithubDeployKeyAction({ + integrations, + }); + }); + + it('Example 1: Create and store a Deploy Key', async () => { + const input = yaml.parse(examples[0].example).steps[0].input; + + mockOctokit.rest.actions.getRepoPublicKey.mockResolvedValue({ + data: { + key: publicKey, + key_id: 'keyid', + }, + }); + + await action.handler({ + ...mockContext, + input, + }); + + expect(mockOctokit.rest.repos.createDeployKey).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + title: 'Push Tags', + key: 'pubkey', + }); + + expect( + mockOctokit.rest.actions.createOrUpdateRepoSecret, + ).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repository', + secret_name: 'PUSH_TAGS_PRIVATE_KEY', + key_id: 'keyid', + encrypted_value: expect.any(String), + }); + + expect(mockContext.output).toHaveBeenCalledWith( + 'privateKeySecretName', + 'PUSH_TAGS_PRIVATE_KEY', + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.ts new file mode 100644 index 0000000000..be8c0ad7bc --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.ts @@ -0,0 +1,37 @@ +/* + * 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: 'Example 1: Create and store a Deploy Key', + example: yaml.stringify({ + steps: [ + { + action: 'github:deployKey:create', + name: 'Create and store a Deploy Key', + input: { + repoUrl: 'github.com?repo=repository&owner=owner', + publicKey: 'pubkey', + privateKey: 'privkey', + deployKeyName: 'Push Tags', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts index 6ad646a89c..1db9746bb4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts @@ -21,6 +21,7 @@ import { parseRepoUrl } from '../publish/util'; import { getOctokitOptions } from './helpers'; import { Octokit } from 'octokit'; import Sodium from 'libsodium-wrappers'; +import { examples } from './githubDeployKey.examples'; /** * Creates an `github:deployKey:create` Scaffolder action that creates a Deploy Key @@ -43,6 +44,7 @@ export function createGithubDeployKeyAction(options: { }>({ id: 'github:deployKey:create', description: 'Creates and stores Deploy Keys', + examples, schema: { input: { type: 'object',