Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull request author placeholder #84

Merged
merged 6 commits into from
Jul 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ The following placeholders are available and are replaced with:
Placeholder | Replaced with
------------|------------
`issue_refs` | GitHub issue references to all issues mentioned in the original pull request description seperated by a space, e.g. `#123 #456 zeebe-io/backport-action#789`
`pull_author` | The username of the original pull request's author, e.g. `korthout`
`pull_number` | The number of the original pull request that is backported, e.g. `123`
`target_branch`| The branchname to which the pull request is backported, e.g. `release-0.23`

Expand Down
51 changes: 31 additions & 20 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

28 changes: 9 additions & 19 deletions src/backport.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as core from "@actions/core";
import dedent from "dedent";

import { CreatePullRequestResponse, RequestReviewersResponse } from "./github";
import {
CreatePullRequestResponse,
RequestReviewersResponse,
PullRequest,
} from "./github";
import { GithubApi } from "./github";
import * as exec from "./exec";
import * as utils from "./utils";
Expand Down Expand Up @@ -134,12 +138,7 @@ export class Backport {
}

console.info(`Create PR for ${branchname}`);
const { title, body } = this.composePRContent(
target,
mainpr.title,
pull_number,
mainpr.body
);
const { title, body } = this.composePRContent(target, mainpr);
const new_pr_response = await this.github.createPR({
owner,
repo,
Expand Down Expand Up @@ -208,18 +207,9 @@ export class Backport {
}
}

private composePRContent(
target: string,
issue_title: string,
issue_number: number,
original_body: string
): PRContent {
const title = `[Backport ${target}] ${issue_title}`;
const issues = utils.getMentionedIssueRefs(original_body);
const body = this.config.pull.description
.replace("${pull_number}", issue_number.toString())
.replace("${target_branch}", target)
.replace("${issue_refs}", issues.join(" "));
private composePRContent(target: string, main: PullRequest): PRContent {
const title = `[Backport ${target}] ${main.title}`;
const body = utils.composeBody(this.config.pull.description, main, target);
return { title, body };
}

Expand Down
3 changes: 3 additions & 0 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ export type PullRequest = {
base: {
sha: string;
};
user: {
login: string;
};
labels: {
name: string;
}[];
Expand Down
91 changes: 89 additions & 2 deletions src/test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dedent from "dedent";
import { getMentionedIssueRefs } from "../utils";
import { getMentionedIssueRefs, composeBody } from "../utils";

describe("get mentioned issues", () => {
describe("returns an empty list", () => {
Expand Down Expand Up @@ -128,8 +128,95 @@ describe("get mentioned issues", () => {
]);
});
});
});

describe("compose body", () => {
const main_default = {
number: 123,
body: "foo-body",
user: { login: "foo-author" },
};
const target = "foo-target";

describe("returns same value as provided template", () => {
it("for an empty template", () => {
expect(composeBody("", main_default, target)).toEqual("");
});

it("for a template without placeholders", () => {
const template = text({});
expect(composeBody(template, main_default, target)).toEqual(template);
});

it("for a template with unknown placeholders", () => {
const template = text({
start: "${abc}",
middle: "${def}",
end: "${ghi}",
part: "${jkl}",
});
expect(composeBody(template, main_default, target)).toEqual(template);
});
});

describe("returns evaluated templated", () => {
it("for a template with target_branch placeholder", () => {
const template = "Backport of some-title to `${target_branch}`";
expect(composeBody(template, main_default, target)).toEqual(
"Backport of some-title to `foo-target`"
);
});

it("for a template with pull_number placeholder", () => {
const template = "Backport of #${pull_number} to some-target";
expect(composeBody(template, main_default, target)).toEqual(
"Backport of #123 to some-target"
);
});

describe("for a template with issue_refs placeholder", () => {
const template = "Backport that refers to: ${issue_refs}";

it("and body has no referred issues", () => {
expect(composeBody(template, main_default, target)).toEqual(
"Backport that refers to: "
);
});

// todo deal with urls to unrelated repos
it("and body has a referred issue", () => {
expect(
composeBody(
template,
{
...main_default,
body: "Body mentions #123 and that's it.",
},
target
)
).toEqual("Backport that refers to: #123");
});

it("and body has some referred issues", () => {
expect(
composeBody(
template,
{
...main_default,
body: "This body refers to #123 and foo/bar#456",
},
target
)
).toEqual("Backport that refers to: #123 foo/bar#456");
});
});

it("for a template with pull_author placeholder", () => {
const template = "Backport of pull made by @${pull_author}";
expect(composeBody(template, main_default, target)).toEqual(
"Backport of pull made by @foo-author"
);
});
});
});

function text({
Expand Down
49 changes: 38 additions & 11 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
/**
* @param template The backport description template
* @param main The main pull request that is backported
* @param target The target branchname
* @returns Description that can be used as the backport pull request body
*/
export function composeBody(
template: string,
main: PullRequest,
target: string
): string {
const issues = getMentionedIssueRefs(main.body);
return template
.replace("${pull_author}", main.user.login)
.replace("${pull_number}", main.number.toString())
.replace("${target_branch}", target)
.replace("${issue_refs}", issues.join(" "));
}

type PullRequest = {
number: number;
body: string;
user: {
login: string;
};
};

/**
* @param body Text in which to search for mentioned issues
* @returns All found mentioned issues as GitHub issue references
*/
export function getMentionedIssueRefs(body: string): string[] {
const issueUrls =
body.match(patterns.url.global)?.map((url) => toRef(url)) ?? [];
const issueRefs = body.match(patterns.ref) ?? [];
return issueUrls.concat(issueRefs).map((ref) => ref.trim());
}

const patterns = {
// matches urls to github issues at start, middle, end of line as individual word
// may be lead and trailed by whitespace which should be trimmed
Expand All @@ -17,17 +55,6 @@ const patterns = {
ref: /(?:^| )((?<org>[^\n #\/]+)\/(?<repo>[^\n #\/]+))?#(?<number>[0-9]+)(?: |$)/gm,
};

/**
* @param body Text in which to search for mentioned issues
* @returns All found mentioned issues as GitHub issue references
*/
export function getMentionedIssueRefs(body: string): string[] {
const issueUrls =
body.match(patterns.url.global)?.map((url) => toRef(url)) ?? [];
const issueRefs = body.match(patterns.ref) ?? [];
return issueUrls.concat(issueRefs).map((ref) => ref.trim());
}

const toRef = (url: string) => {
// matchAll is not yet available to directly access the captured groups of all matches
// so this maps the urls to GitHub refs by matching again without the global flag
Expand Down