From 6cf48c609835299360bcc0c60f66a9bf85a7f20e Mon Sep 17 00:00:00 2001 From: Andrew Ellis Date: Thu, 29 Jul 2021 15:28:07 -0600 Subject: [PATCH] feat(plugin-scaffolder-backend): add defaultCommitMessage config option Signed-off-by: Andrew Ellis --- .changeset/soft-news-float.md | 5 ++ app-config.yaml | 2 + plugins/scaffolder-backend/config.d.ts | 4 ++ .../src/scaffolder/actions/builtin/helpers.ts | 4 +- .../actions/builtin/publish/azure.test.ts | 38 +++++++++++ .../actions/builtin/publish/azure.ts | 3 + .../actions/builtin/publish/bitbucket.test.ts | 68 +++++++++++++++++++ .../actions/builtin/publish/bitbucket.ts | 3 + .../actions/builtin/publish/github.test.ts | 45 ++++++++++++ .../actions/builtin/publish/github.ts | 3 + .../actions/builtin/publish/gitlab.test.ts | 46 +++++++++++++ .../actions/builtin/publish/gitlab.ts | 3 + 12 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 .changeset/soft-news-float.md diff --git a/.changeset/soft-news-float.md b/.changeset/soft-news-float.md new file mode 100644 index 0000000000..ae79c63a06 --- /dev/null +++ b/.changeset/soft-news-float.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +Add the `scaffolder.defaultCommitMessage`, which defaults to `Initial commit`, so it can be customized. diff --git a/app-config.yaml b/app-config.yaml index 074e28c086..f2df97b7b2 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -256,6 +256,8 @@ scaffolder: # defaultAuthor: # name: Scaffolder # email: scaffolder@backstage.io + # Use to customize the default commit message when new components are created + # defaultCommitMessage: 'Initial commit' github: token: ${GITHUB_TOKEN} visibility: public # or 'internal' or 'private' diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index 795fe5b112..126c55e166 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -24,6 +24,10 @@ export interface Config { name?: string; email?: string; }; + /** + * The commit message used when new components are created. + */ + defaultCommitMessage?: string; github?: { [key: string]: string; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index e2459a8ca7..7a10046fd0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -62,6 +62,7 @@ export async function initRepoAndPush({ auth, logger, defaultBranch = 'master', + commitMessage = 'Initial commit', gitAuthorInfo, }: { dir: string; @@ -69,6 +70,7 @@ export async function initRepoAndPush({ auth: { username: string; password: string }; logger: Logger; defaultBranch?: string; + commitMessage?: string; gitAuthorInfo?: { name?: string; email?: string }; }): Promise { const git = Git.fromAuth({ @@ -100,7 +102,7 @@ export async function initRepoAndPush({ await git.commit({ dir, - message: 'Initial commit', + message: commitMessage, author: authorInfo, committer: authorInfo, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index 30995dee38..a242863ac7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -233,6 +233,44 @@ describe('publish:azure', () => { }); }); + it('should call initRepoAndPush with the configured defaultCommitMessage', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + azure: [ + { host: 'dev.azure.com', token: 'tokenlols' }, + { host: 'myazurehostnotoken.com' }, + ], + }, + scaffolder: { + defaultCommitMessage: 'Test commit message', + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishAzureAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGitClient.createRepository.mockImplementation(() => ({ + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + })); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + auth: { username: 'notempty', password: 'tokenlols' }, + logger: mockContext.logger, + defaultBranch: 'master', + commitMessage: 'Test commit message', + gitAuthorInfo: { email: undefined, name: undefined }, + }); + }); + it('should call output with the remoteUrl and the repoContentsUrl', async () => { mockGitClient.createRepository.mockImplementation(() => ({ remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index c58dd69424..f5c7879fa9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -139,6 +139,9 @@ export function createPublishAzureAction(options: { password: integrationConfig.config.token, }, logger: ctx.logger, + commitMessage: config.getOptionalString( + 'scaffolder.defaultCommitMessage', + ), gitAuthorInfo, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 9fe245935b..ebdd28260c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -407,6 +407,74 @@ describe('publish:bitbucket', () => { }); }); + it('should call initAndPush with the configured defaultCommitMessage', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + bitbucket: [ + { + host: 'bitbucket.org', + token: 'tokenlols', + }, + { + host: 'hosted.bitbucket.com', + token: 'thing', + apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', + }, + { + host: 'notoken.bitbucket.com', + }, + ], + }, + scaffolder: { + defaultCommitMessage: 'Test commit message', + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishBitbucketAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + server.use( + rest.post( + 'https://api.bitbucket.org/2.0/repositories/owner/repo', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + links: { + html: { + href: 'https://bitbucket.org/owner/repo', + }, + clone: [ + { + name: 'https', + href: 'https://bitbucket.org/owner/cloneurl', + }, + ], + }, + }), + ), + ), + ); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://bitbucket.org/owner/cloneurl', + auth: { username: 'x-token-auth', password: 'tokenlols' }, + logger: mockContext.logger, + defaultBranch: 'master', + commitMessage: 'Test commit message', + gitAuthorInfo: { email: undefined, name: undefined }, + }); + }); + it('should call outputs with the correct urls', async () => { server.use( rest.post( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index ffd2e4d6a7..41d71c9ab5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -304,6 +304,9 @@ export function createPublishBitbucketAction(options: { }, defaultBranch, logger: ctx.logger, + commitMessage: config.getOptionalString( + 'scaffolder.defaultCommitMessage', + ), gitAuthorInfo, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index f0725d6e8e..173e44848b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -260,6 +260,51 @@ describe('publish:github', () => { }); }); + it('should call initRepoAndPush with the configured defaultCommitMessage', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + scaffolder: { + defaultCommitMessage: 'Test commit message', + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishGithubAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'Test commit message', + gitAuthorInfo: { email: undefined, name: undefined }, + }); + }); + it('should add access for the team when it starts with the owner', async () => { mockGithubClient.users.getByUsername.mockResolvedValue({ data: { type: 'User' }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 05301bda85..640ae5dfe5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -264,6 +264,9 @@ export function createPublishGithubAction(options: { password: token, }, logger: ctx.logger, + commitMessage: config.getOptionalString( + 'scaffolder.defaultCommitMessage', + ), gitAuthorInfo, }); 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 5150205a08..d76f838797 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 @@ -219,6 +219,52 @@ describe('publish:gitlab', () => { }); }); + it('should call initRepoAndPush with the configured defaultCommitMessage', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + { + host: 'hosted.gitlab.com', + apiBaseUrl: 'https://api.hosted.gitlab.com', + }, + ], + }, + scaffolder: { + defaultCommitMessage: 'Test commit message', + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishGitlabAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'http://mockurl.git', + auth: { username: 'oauth2', password: 'tokenlols' }, + logger: mockContext.logger, + defaultBranch: 'master', + commitMessage: 'Test commit message', + gitAuthorInfo: { email: undefined, name: undefined }, + }); + }); + it('should call output with the remoteUrl and repoContentsUrl', async () => { mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); mockGitlabClient.Projects.create.mockResolvedValue({ 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 b99d40b1f7..fbd2dcaaae 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -137,6 +137,9 @@ export function createPublishGitlabAction(options: { password: integrationConfig.config.token, }, logger: ctx.logger, + commitMessage: config.getOptionalString( + 'scaffolder.defaultCommitMessage', + ), gitAuthorInfo, });