feat(issue-17): override backporting pr data (#29)

This commit is contained in:
Andrea Lamparelli 2023-06-20 22:29:52 +02:00 committed by GitHub
parent 1732481b37
commit 941beda208
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 279 additions and 30 deletions

View file

@ -51,8 +51,13 @@ This toold comes with some inputs that allow users to override the default behav
| Pull Request | -pr, --pull-request | Y | Original pull request url, the one that must be backported, e.g., https://github.com/lampajr/backporting/pull/1 | |
| Auth | -a, --auth | N | `GITHUB_TOKEN` or a `repo` scoped [Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) | "" |
| Folder | -f, --folder | N | Local folder where the repo will be checked out, e.g., /tmp/folder | {cwd}/bp |
| Title | --title | N | Backporting pull request title | "{original-pr-title}" |
| Body | --body | N | Backporting pull request body | "{original-pr-body}" |
| Body Prefix | --body-prefix | N | Prefix to the backporting pull request body | "Backport: {original-pr-link}" |
| Backport Branch Name | --bp-branch-name | N | Name of the backporting pull request branch | bp-{target-branch}-{sha} |
| Dry Run | -d, --dry-run | N | If enabled the tool does not push nor create anything remotely, use this to skip PR creation | false |
## GitHub Action
This action can be used in any GitHub workflow, below you can find a simple example of manually triggered workflow backporting a specific pull request (provided as input).
@ -135,13 +140,11 @@ For a complete description of all inputs see [Inputs section](#inputs).
**BPer** is in development mode, this means that it has many limitations right now. I'll try to summarize the most importan ones:
- No way to override backporting pull request fields like body, reviewers and so on.
- You can backport pull requests only.
- It only works for [GitHub](https://github.com/).
- Integrated in GitHub Actions CI/CD only.
Based on these limitations, the next **Future Works** could be the following:
- Give users the possibility to override/customize the backporting pull request.
- Provide a way to backport single commit too (or a set of them), even if no original pull request is present.
- Integrate this tool with other git management services (like GitLab and Bitbucket) to make it as generic as possible.
- Provide some reusable GitHub workflows.

View file

@ -15,6 +15,18 @@ inputs:
target-branch:
description: "Branch where the pull request must be backported to."
required: true
title:
description: "Backporting PR title. Default is the original PR title prefixed by the target branch."
required: false
body:
description: "Backporting PR body. Default is the original PR body prefixed by `backport: <original-pr-link>`."
required: false
body-prefix:
description: "Backporting PR body prefix. Default is `backport: <original-pr-link>`"
required: false
bp-branch-name:
description: "Backporting PR branch name. Default is auto-generated from commit."
required: false
runs:
using: node16

27
dist/cli/index.js vendored
View file

@ -39,7 +39,11 @@ class CLIArgsParser {
.requiredOption("-pr, --pull-request <pr url>", "pull request url, e.g., https://github.com/lampajr/backporting/pull/1.")
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely", false)
.option("-a, --auth <auth>", "git service authentication string, e.g., github token.", "")
.option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder.", undefined);
.option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder.", undefined)
.option("--title <folder>", "backport pr title, default original pr title prefixed by target branch.", undefined)
.option("--body <folder>", "backport pr title, default original pr body prefixed by bodyPrefix.", undefined)
.option("--body-prefix <folder>", "backport pr body prefix, default `backport <original-pr-link>`.", undefined)
.option("--bp-branch-name <folder>", "backport pr branch name, default auto-generated by the commit.", undefined);
}
parse() {
const opts = this.getCommand()
@ -50,7 +54,11 @@ class CLIArgsParser {
auth: opts.auth,
pullRequest: opts.pullRequest,
targetBranch: opts.targetBranch,
folder: opts.folder
folder: opts.folder,
title: opts.title,
body: opts.body,
bodyPrefix: opts.bodyPrefix,
bpBranchName: opts.bpBranchName,
};
}
}
@ -122,32 +130,35 @@ class PullRequestConfigsParser extends configs_parser_1.default {
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
targetBranch: args.targetBranch,
originalPullRequest: pr,
backportPullRequest: this.getDefaultBackportPullRequest(pr, args.targetBranch)
backportPullRequest: this.getDefaultBackportPullRequest(pr, args)
};
}
getDefaultFolder() {
return "bp";
}
/**
* Create a default backport pull request starting from the target branch and
* Create a backport pull request starting from the target branch and
* the original pr to be backported
* @param originalPullRequest original pull request
* @param targetBranch target branch where the backport should be applied
* @returns {GitPullRequest}
*/
getDefaultBackportPullRequest(originalPullRequest, targetBranch) {
getDefaultBackportPullRequest(originalPullRequest, args) {
const reviewers = [];
reviewers.push(originalPullRequest.author);
if (originalPullRequest.mergedBy) {
reviewers.push(originalPullRequest.mergedBy);
}
const bodyPrefix = args.bodyPrefix ?? `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n`;
const body = args.body ?? `${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`;
return {
author: originalPullRequest.author,
title: `[${targetBranch}] ${originalPullRequest.title}`,
body: `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`,
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
body: `${bodyPrefix}${body}`,
reviewers: [...new Set(reviewers)],
targetRepo: originalPullRequest.targetRepo,
sourceRepo: originalPullRequest.targetRepo,
branchName: args.bpBranchName,
nCommits: 0,
commits: [] // TODO needed?
};
@ -649,7 +660,7 @@ class Runner {
// 4. clone the repository
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
// 5. create new branch from target one and checkout
const backportBranch = `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
const backportBranch = backportPR.branchName ?? `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
await git.createLocalBranch(configs.folder, backportBranch);
// 6. fetch pull request remote if source owner != target owner or pull request still open
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||

21
dist/gha/index.js vendored
View file

@ -36,7 +36,11 @@ class GHAArgsParser {
auth: (0, core_1.getInput)("auth") ? (0, core_1.getInput)("auth") : "",
pullRequest: (0, core_1.getInput)("pull-request"),
targetBranch: (0, core_1.getInput)("target-branch"),
folder: (0, core_1.getInput)("folder") !== "" ? (0, core_1.getInput)("folder") : undefined
folder: (0, core_1.getInput)("folder") !== "" ? (0, core_1.getInput)("folder") : undefined,
title: (0, core_1.getInput)("title"),
body: (0, core_1.getInput)("body"),
bodyPrefix: (0, core_1.getInput)("body-prefix"),
bpBranchName: (0, core_1.getInput)("bp-branch-name"),
};
}
}
@ -108,32 +112,35 @@ class PullRequestConfigsParser extends configs_parser_1.default {
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
targetBranch: args.targetBranch,
originalPullRequest: pr,
backportPullRequest: this.getDefaultBackportPullRequest(pr, args.targetBranch)
backportPullRequest: this.getDefaultBackportPullRequest(pr, args)
};
}
getDefaultFolder() {
return "bp";
}
/**
* Create a default backport pull request starting from the target branch and
* Create a backport pull request starting from the target branch and
* the original pr to be backported
* @param originalPullRequest original pull request
* @param targetBranch target branch where the backport should be applied
* @returns {GitPullRequest}
*/
getDefaultBackportPullRequest(originalPullRequest, targetBranch) {
getDefaultBackportPullRequest(originalPullRequest, args) {
const reviewers = [];
reviewers.push(originalPullRequest.author);
if (originalPullRequest.mergedBy) {
reviewers.push(originalPullRequest.mergedBy);
}
const bodyPrefix = args.bodyPrefix ?? `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n`;
const body = args.body ?? `${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`;
return {
author: originalPullRequest.author,
title: `[${targetBranch}] ${originalPullRequest.title}`,
body: `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`,
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
body: `${bodyPrefix}${body}`,
reviewers: [...new Set(reviewers)],
targetRepo: originalPullRequest.targetRepo,
sourceRepo: originalPullRequest.targetRepo,
branchName: args.bpBranchName,
nCommits: 0,
commits: [] // TODO needed?
};
@ -635,7 +642,7 @@ class Runner {
// 4. clone the repository
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
// 5. create new branch from target one and checkout
const backportBranch = `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
const backportBranch = backportPR.branchName ?? `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
await git.createLocalBranch(configs.folder, backportBranch);
// 6. fetch pull request remote if source owner != target owner or pull request still open
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||

View file

@ -8,4 +8,8 @@ export interface Args {
pullRequest: string, // url of the pull request to backport
folder?: string, // local folder where the repositories should be cloned
author?: string, // backport pr author, default taken from pr
title?: string, // backport pr title, default original pr title prefixed by target branch
body?: string, // backport pr title, default original pr body prefixed by bodyPrefix
bodyPrefix?: string, // backport pr body prefix, default `backport <original-pr-link>`
bpBranchName?: string, // backport pr branch name, default computed from commit
}

View file

@ -14,7 +14,11 @@ export default class CLIArgsParser implements ArgsParser {
.requiredOption("-pr, --pull-request <pr url>", "pull request url, e.g., https://github.com/lampajr/backporting/pull/1.")
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely", false)
.option("-a, --auth <auth>", "git service authentication string, e.g., github token.", "")
.option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder.", undefined);
.option("-f, --folder <folder>", "local folder where the repo will be checked out, e.g., /tmp/folder.", undefined)
.option("--title <folder>", "backport pr title, default original pr title prefixed by target branch.", undefined)
.option("--body <folder>", "backport pr title, default original pr body prefixed by bodyPrefix.", undefined)
.option("--body-prefix <folder>", "backport pr body prefix, default `backport <original-pr-link>`.", undefined)
.option("--bp-branch-name <folder>", "backport pr branch name, default auto-generated by the commit.", undefined);
}
parse(): Args {
@ -27,7 +31,11 @@ export default class CLIArgsParser implements ArgsParser {
auth: opts.auth,
pullRequest: opts.pullRequest,
targetBranch: opts.targetBranch,
folder: opts.folder
folder: opts.folder,
title: opts.title,
body: opts.body,
bodyPrefix: opts.bodyPrefix,
bpBranchName: opts.bpBranchName,
};
}

View file

@ -10,7 +10,11 @@ export default class GHAArgsParser implements ArgsParser {
auth: getInput("auth") ? getInput("auth") : "",
pullRequest: getInput("pull-request"),
targetBranch: getInput("target-branch"),
folder: getInput("folder") !== "" ? getInput("folder") : undefined
folder: getInput("folder") !== "" ? getInput("folder") : undefined,
title: getInput("title"),
body: getInput("body"),
bodyPrefix: getInput("body-prefix"),
bpBranchName: getInput("bp-branch-name"),
};
}

View file

@ -25,7 +25,7 @@ export default class PullRequestConfigsParser extends ConfigsParser {
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
targetBranch: args.targetBranch,
originalPullRequest: pr,
backportPullRequest: this.getDefaultBackportPullRequest(pr, args.targetBranch)
backportPullRequest: this.getDefaultBackportPullRequest(pr, args)
};
}
@ -34,26 +34,30 @@ export default class PullRequestConfigsParser extends ConfigsParser {
}
/**
* Create a default backport pull request starting from the target branch and
* Create a backport pull request starting from the target branch and
* the original pr to be backported
* @param originalPullRequest original pull request
* @param targetBranch target branch where the backport should be applied
* @returns {GitPullRequest}
*/
private getDefaultBackportPullRequest(originalPullRequest: GitPullRequest, targetBranch: string): GitPullRequest {
private getDefaultBackportPullRequest(originalPullRequest: GitPullRequest, args: Args): GitPullRequest {
const reviewers = [];
reviewers.push(originalPullRequest.author);
if (originalPullRequest.mergedBy) {
reviewers.push(originalPullRequest.mergedBy);
}
const bodyPrefix = args.bodyPrefix ?? `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n`;
const body = args.body ?? `${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`;
return {
author: originalPullRequest.author,
title: `[${targetBranch}] ${originalPullRequest.title}`,
body: `**Backport:** ${originalPullRequest.htmlUrl}\r\n\r\n${originalPullRequest.body}\r\n\r\nPowered by [BPer](https://github.com/lampajr/backporting).`,
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
body: `${bodyPrefix}${body}`,
reviewers: [...new Set(reviewers)],
targetRepo: originalPullRequest.targetRepo,
sourceRepo: originalPullRequest.targetRepo,
branchName: args.bpBranchName,
nCommits: 0, // TODO: needed?
commits: [] // TODO needed?
};

View file

@ -12,7 +12,8 @@ export interface GitPullRequest {
targetRepo: GitRepository,
sourceRepo: GitRepository,
nCommits: number, // number of commits in the pr
commits: string[] // merge commit or last one
commits: string[], // merge commit or last one
branchName?: string,
}
export interface GitRepository {
@ -28,7 +29,8 @@ export interface BackportPullRequest {
base: string, // name of the target branch
title: string, // pr title
body: string, // pr body
reviewers: string[] // pr list of reviewers
reviewers: string[], // pr list of reviewers
branchName?: string,
}
export enum GitServiceType {

View file

@ -86,7 +86,7 @@ export default class Runner {
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
// 5. create new branch from target one and checkout
const backportBranch = `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
const backportBranch = backportPR.branchName ?? `bp-${configs.targetBranch}-${originalPR.commits.join("-")}`;
await git.createLocalBranch(configs.folder, backportBranch);
// 6. fetch pull request remote if source owner != target owner or pull request still open

View file

@ -28,6 +28,10 @@ describe("cli args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual(undefined);
expect(args.body).toEqual(undefined);
expect(args.bodyPrefix).toEqual(undefined);
expect(args.bpBranchName).toEqual(undefined);
});
test("valid execution [default, long]", () => {
@ -45,6 +49,10 @@ describe("cli args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual(undefined);
expect(args.body).toEqual(undefined);
expect(args.bodyPrefix).toEqual(undefined);
expect(args.bpBranchName).toEqual(undefined);
});
test("valid execution [override, short]", () => {
@ -65,6 +73,10 @@ describe("cli args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual(undefined);
expect(args.body).toEqual(undefined);
expect(args.bodyPrefix).toEqual(undefined);
expect(args.bpBranchName).toEqual(undefined);
});
test("valid execution [override, long]", () => {
@ -75,7 +87,15 @@ describe("cli args parser", () => {
"--target-branch",
"target",
"--pull-request",
"https://localhost/whatever/pulls/1"
"https://localhost/whatever/pulls/1",
"--title",
"New Title",
"--body",
"New Body",
"--body-prefix",
"New Body Prefix",
"--bp-branch-name",
"bp_branch_name",
]);
const args: Args = parser.parse();
@ -85,6 +105,10 @@ describe("cli args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual("New Title");
expect(args.body).toEqual("New Body");
expect(args.bodyPrefix).toEqual("New Body Prefix");
expect(args.bpBranchName).toEqual("bp_branch_name");
});
});

View file

@ -28,6 +28,10 @@ describe("gha args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual(undefined);
expect(args.body).toEqual(undefined);
expect(args.bodyPrefix).toEqual(undefined);
expect(args.bpBranchName).toEqual(undefined);
});
test("valid execution [override]", () => {
@ -35,7 +39,11 @@ describe("gha args parser", () => {
"dry-run": "true",
"auth": "bearer-token",
"target-branch": "target",
"pull-request": "https://localhost/whatever/pulls/1"
"pull-request": "https://localhost/whatever/pulls/1",
"title": "New Title",
"body": "New Body",
"body-prefix": "New Body Prefix",
"bp-branch-name": "bp_branch_name",
});
const args: Args = parser.parse();
@ -45,6 +53,10 @@ describe("gha args parser", () => {
expect(args.folder).toEqual(undefined);
expect(args.targetBranch).toEqual("target");
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
expect(args.title).toEqual("New Title");
expect(args.body).toEqual("New Body");
expect(args.bodyPrefix).toEqual("New Body Prefix");
expect(args.bpBranchName).toEqual("bp_branch_name");
});
});

View file

@ -84,6 +84,7 @@ describe("pull request config parser", () => {
project: "reponame",
cloneUrl: "https://github.com/owner/reponame.git"
},
bpBranchName: undefined,
nCommits: 0,
commits: []
});
@ -158,6 +159,7 @@ describe("pull request config parser", () => {
project: "reponame",
cloneUrl: "https://github.com/fork/reponame.git"
},
bpBranchName: undefined,
nCommits: 2,
// taken from head.sha
commits: ["91748965051fae1330ad58d15cf694e103267c87"]
@ -174,4 +176,70 @@ describe("pull request config parser", () => {
expect(async () => await parser.parseAndValidate(args)).rejects.toThrow("Provided pull request is closed and not merged!");
});
test("override backport pr data", async () => {
const args: Args = {
dryRun: false,
auth: "",
pullRequest: mergedPRUrl,
targetBranch: "prod",
title: "New Title",
body: "New Body",
bodyPrefix: "New Body Prefix -",
};
const configs: Configs = await parser.parseAndValidate(args);
expect(configs.dryRun).toEqual(false);
expect(configs.author).toEqual("gh-user");
expect(configs.auth).toEqual("");
expect(configs.targetBranch).toEqual("prod");
expect(configs.folder).toEqual(process.cwd() + "/bp");
expect(configs.originalPullRequest).toEqual({
number: 2368,
author: "gh-user",
url: "https://api.github.com/repos/owner/reponame/pulls/2368",
htmlUrl: "https://github.com/owner/reponame/pull/2368",
state: "closed",
merged: true,
mergedBy: "that-s-a-user",
title: "PR Title",
body: "Please review and merge",
reviewers: ["requested-gh-user", "gh-user"],
targetRepo: {
owner: "owner",
project: "reponame",
cloneUrl: "https://github.com/owner/reponame.git"
},
sourceRepo: {
owner: "fork",
project: "reponame",
cloneUrl: "https://github.com/fork/reponame.git"
},
bpBranchName: undefined,
nCommits: 2,
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
});
expect(configs.backportPullRequest).toEqual({
author: "gh-user",
url: undefined,
htmlUrl: undefined,
title: "New Title",
body: "New Body Prefix -New Body",
reviewers: ["gh-user", "that-s-a-user"],
targetRepo: {
owner: "owner",
project: "reponame",
cloneUrl: "https://github.com/owner/reponame.git"
},
sourceRepo: {
owner: "owner",
project: "reponame",
cloneUrl: "https://github.com/owner/reponame.git"
},
bpBranchName: undefined,
nCommits: 0,
commits: []
});
});
});

View file

@ -282,4 +282,52 @@ describe("cli runner", () => {
}
);
});
test("override backporting pr data", async () => {
addProcessArgs([
"-tb",
"target",
"-pr",
"https://github.com/owner/reponame/pull/2368",
"--title",
"New Title",
"--body",
"New Body",
"--body-prefix",
"New Body Prefix - ",
"--bp-branch-name",
"bp_branch_name",
]);
await runner.execute();
const cwd = process.cwd() + "/bp";
expect(GitCLIService.prototype.clone).toBeCalledTimes(1);
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "target");
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(1);
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp_branch_name");
expect(GitCLIService.prototype.fetch).toBeCalledTimes(1);
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(1);
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc");
expect(GitCLIService.prototype.push).toBeCalledTimes(1);
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp_branch_name");
expect(GitHubService.prototype.createPullRequest).toBeCalledTimes(1);
expect(GitHubService.prototype.createPullRequest).toBeCalledWith({
owner: "owner",
repo: "reponame",
head: "bp_branch_name",
base: "target",
title: "New Title",
body: "New Body Prefix - New Body",
reviewers: ["gh-user", "that-s-a-user"]
}
);
});
});

View file

@ -138,4 +138,46 @@ describe("gha runner", () => {
}
);
});
test("override backporting pr data", async () => {
spyGetInput({
"target-branch": "target",
"pull-request": "https://github.com/owner/reponame/pull/2368",
"title": "New Title",
"body": "New Body",
"body-prefix": "New Body Prefix - ",
"bp-branch-name": "bp_branch_name",
});
await runner.execute();
const cwd = process.cwd() + "/bp";
expect(GitCLIService.prototype.clone).toBeCalledTimes(1);
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "target");
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(1);
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp_branch_name");
expect(GitCLIService.prototype.fetch).toBeCalledTimes(1);
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(1);
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc");
expect(GitCLIService.prototype.push).toBeCalledTimes(1);
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp_branch_name");
expect(GitHubService.prototype.createPullRequest).toBeCalledTimes(1);
expect(GitHubService.prototype.createPullRequest).toBeCalledWith({
owner: "owner",
repo: "reponame",
head: "bp_branch_name",
base: "target",
title: "New Title",
body: "New Body Prefix - New Body",
reviewers: ["gh-user", "that-s-a-user"]
}
);
});
});