Adds createWhenEmpty option to publish:github:pull-request action

Signed-off-by: Tanner Juedeman <tbjuedeman@gmail.com>
This commit is contained in:
Tanner Juedeman
2025-01-27 15:04:17 -06:00
committed by blam
parent 9c45736f78
commit bb8302b200
5 changed files with 217 additions and 22 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Adds `createWhenEmpty` option to `publish:github:pull-request` action.
@@ -617,13 +617,7 @@ describe('publish:github:pull-request examples', () => {
expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123);
});
it('Create a pull request with all parameters', async () => {
mockDir.setContent({
[workspacePath]: {
source: { 'foo.txt': 'Hello there!' },
irrelevant: { 'bar.txt': 'Nothing to see here' },
},
});
it('Does not create an empty pull request', async () => {
const input = yaml.parse(examples[12].example).steps[0].input;
await action.handler({
@@ -638,8 +632,56 @@ describe('publish:github:pull-request examples', () => {
title: 'Create my new app',
body: 'This PR is really good',
head: 'new-app',
draft: true,
draft: undefined,
createWhenEmpty: false,
changes: [
{
commit: 'Create my new app',
files: {
'file.txt': {
content: Buffer.from('Hello there!').toString('base64'),
encoding: 'base64',
mode: '100644',
},
},
},
],
});
expect(fakeClient.rest.pulls.requestReviewers).not.toHaveBeenCalled();
expect(mockContext.output).toHaveBeenCalledTimes(3);
expect(mockContext.output).toHaveBeenCalledWith('targetBranchName', 'main');
expect(mockContext.output).toHaveBeenCalledWith(
'remoteUrl',
'https://github.com/myorg/myrepo/pull/123',
);
expect(mockContext.output).toHaveBeenCalledWith('pullRequestNumber', 123);
});
it('Create a pull request with all parameters', async () => {
mockDir.setContent({
[workspacePath]: {
source: { 'foo.txt': 'Hello there!' },
irrelevant: { 'bar.txt': 'Nothing to see here' },
},
});
const input = yaml.parse(examples[13].example).steps[0].input;
await action.handler({
...mockContext,
workspacePath,
input,
});
expect(fakeClient.createPullRequest).toHaveBeenCalledWith({
owner: 'owner',
repo: 'repo',
title: 'Create my new app',
body: 'This PR is really good',
head: 'new-app',
base: 'test',
draft: true,
createWhenEmpty: true,
changes: [
{
commit: 'Commit for foo changes',
@@ -23,7 +23,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -40,7 +40,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest with target branch name',
name: 'Create a pull request with target branch name',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -58,7 +58,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest as draft',
name: 'Create a pull request as draft',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -76,7 +76,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest with target path',
name: 'Create a pull request with target path',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -94,7 +94,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest with source path',
name: 'Create a pull request with source path',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -112,7 +112,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -130,7 +130,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest with reviewers',
name: 'Create a pull request with reviewers',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -148,7 +148,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest with team reviewers',
name: 'Create a pull request with team reviewers',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -166,7 +166,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -184,7 +184,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -203,7 +203,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -223,7 +223,7 @@ export const examples: TemplateExample[] = [
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -237,13 +237,31 @@ export const examples: TemplateExample[] = [
],
}),
},
{
description: 'Do not create empty pull request',
example: yaml.stringify({
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
title: 'Create my new app',
description: 'This PR is really good',
createWhenEmpty: false,
},
},
],
}),
},
{
description: 'Create a pull request with all parameters',
example: yaml.stringify({
steps: [
{
action: 'publish:github:pull-request',
name: 'Create a pull reuqest',
name: 'Create a pull request',
input: {
repoUrl: 'github.com?repo=repo&owner=owner',
branchName: 'new-app',
@@ -259,6 +277,7 @@ export const examples: TemplateExample[] = [
commitMessage: 'Commit for foo changes',
gitAuthorName: 'Foo Bar',
gitAuthorEmail: 'foo@bar.example',
createWhenEmpty: true,
},
},
],
@@ -1062,4 +1062,119 @@ describe('createPublishGithubPullRequestAction', () => {
});
});
});
describe('with createWhenEmpty equals true', () => {
let input: GithubPullRequestActionInput;
let ctx: ActionContext<GithubPullRequestActionInput>;
beforeEach(() => {
input = {
repoUrl: 'github.com?owner=myorg&repo=myrepo',
title: 'Create my new app',
branchName: 'new-app',
description: 'This PR is really good',
createWhenEmpty: true,
};
mockDir.setContent({
[workspacePath]: { 'file.txt': 'Hello there!' },
});
ctx = createMockActionContext({ input, workspacePath });
});
it('creates a pull request', async () => {
await instance.handler(ctx);
expect(fakeClient.createPullRequest).toHaveBeenCalledWith({
owner: 'myorg',
repo: 'myrepo',
title: 'Create my new app',
head: 'new-app',
body: 'This PR is really good',
createWhenEmpty: true,
changes: [
{
commit: 'Create my new app',
files: {
'file.txt': {
content: Buffer.from('Hello there!').toString('base64'),
encoding: 'base64',
mode: '100644',
},
},
},
],
});
});
it('creates outputs for the pull request url and number', async () => {
await instance.handler(ctx);
expect(ctx.output).toHaveBeenCalledWith(
'remoteUrl',
'https://github.com/myorg/myrepo/pull/123',
);
expect(ctx.output).toHaveBeenCalledWith('pullRequestNumber', 123);
});
it('throws when creating a pull request fails', async () => {
fakeClient.createPullRequest.mockResolvedValueOnce(null);
await expect(instance.handler(ctx)).rejects.toThrow(
'null response from Github',
);
});
});
describe('with createWhenEmpty equals false', () => {
let input: GithubPullRequestActionInput;
let ctx: ActionContext<GithubPullRequestActionInput>;
beforeEach(() => {
fakeClient.createPullRequest.mockResolvedValueOnce(null);
input = {
repoUrl: 'github.com?owner=myorg&repo=myrepo',
title: 'Create my new app',
branchName: 'new-app',
description: 'This PR is really good',
createWhenEmpty: false,
};
mockDir.setContent({
[workspacePath]: { 'file.txt': 'Hello there!' },
});
ctx = createMockActionContext({ input, workspacePath });
});
it('creates a pull request', async () => {
await instance.handler(ctx);
expect(fakeClient.createPullRequest).toHaveBeenCalledWith({
owner: 'myorg',
repo: 'myrepo',
title: 'Create my new app',
head: 'new-app',
body: 'This PR is really good',
createWhenEmpty: false,
changes: [
{
commit: 'Create my new app',
files: {
'file.txt': {
content: Buffer.from('Hello there!').toString('base64'),
encoding: 'base64',
mode: '100644',
},
},
},
],
});
});
it('does not create outputs for the pull request url and number', async () => {
await instance.handler(ctx);
expect(ctx.output).not.toHaveBeenCalled();
});
});
});
@@ -145,6 +145,7 @@ export const createPublishGithubPullRequestAction = (
gitAuthorName?: string;
gitAuthorEmail?: string;
forceEmptyGitAuthor?: boolean;
createWhenEmpty?: boolean;
}>({
id: 'publish:github:pull-request',
examples,
@@ -251,10 +252,16 @@ export const createPublishGithubPullRequestAction = (
description:
'Forces the author to be empty. This is useful when using a Github App, it permit the commit to be verified on Github',
},
createWhenEmpty: {
type: 'boolean',
title: 'Create When Empty',
description:
'Set whether to create pull request when there are no changes to commit. The default value is true',
},
},
},
output: {
required: ['remoteUrl'],
required: [],
type: 'object',
properties: {
targetBranchName: {
@@ -293,6 +300,7 @@ export const createPublishGithubPullRequestAction = (
gitAuthorEmail,
gitAuthorName,
forceEmptyGitAuthor,
createWhenEmpty,
} = ctx.input;
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
@@ -379,6 +387,7 @@ export const createPublishGithubPullRequestAction = (
draft,
update,
forceFork,
createWhenEmpty,
};
const gitAuthorInfo = {
@@ -417,6 +426,11 @@ export const createPublishGithubPullRequestAction = (
}
const response = await client.createPullRequest(createOptions);
if (createWhenEmpty === false && !response) {
ctx.logger.info('No changes to commit, pull request was not created');
return;
}
if (!response) {
throw new GithubResponseError('null response from Github');
}