mirror of
https://github.com/kiegroup/git-backporting.git
synced 2025-04-24 20:32:14 +00:00
feat(issue-77): handle multiple target branches (#78)
fix: https://github.com/kiegroup/git-backporting/issues/77 This enhancement allow users to backport the same change to multiple branches with one single tool invocation
This commit is contained in:
parent
c19a56a9ad
commit
5fc72e127b
25 changed files with 1774 additions and 234 deletions
|
@ -94,7 +94,7 @@ This tool comes with some inputs that allow users to override the default behavi
|
||||||
|---------------|----------------------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
|---------------|----------------------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
||||||
| Version | -V, --version | - | Current version of the tool | |
|
| Version | -V, --version | - | Current version of the tool | |
|
||||||
| Help | -h, --help | - | Display the help message | |
|
| Help | -h, --help | - | Display the help message | |
|
||||||
| Target Branch | -tb, --target-branch | N | Branch where the changes must be backported to | |
|
| Target Branches | -tb, --target-branch | N | Comma separated list of branches where the changes must be backported to | |
|
||||||
| Pull Request | -pr, --pull-request | N | Original pull request url, the one that must be backported, e.g., https://github.com/kiegroup/git-backporting/pull/1 | |
|
| Pull Request | -pr, --pull-request | N | Original pull request url, the one that must be backported, e.g., https://github.com/kiegroup/git-backporting/pull/1 | |
|
||||||
| Configuration File | -cf, --config-file | N | Configuration file, in JSON format, containing all options to be overridded, note that if provided all other CLI options will be ignored | |
|
| Configuration File | -cf, --config-file | N | Configuration file, in JSON format, containing all options to be overridded, note that if provided all other CLI options will be ignored | |
|
||||||
| Auth | -a, --auth | N | `GITHUB_TOKEN`, `GITLAB_TOKEN` or a `repo` scoped [Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) | "" |
|
| Auth | -a, --auth | N | `GITHUB_TOKEN`, `GITLAB_TOKEN` or a `repo` scoped [Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) | "" |
|
||||||
|
@ -107,7 +107,7 @@ This tool comes with some inputs that allow users to override the default behavi
|
||||||
| Reviewers | --reviewers | N | Backporting pull request comma-separated reviewers list | [] |
|
| Reviewers | --reviewers | N | Backporting pull request comma-separated reviewers list | [] |
|
||||||
| Assignees | --assignes | N | Backporting pull request comma-separated assignees list | [] |
|
| Assignees | --assignes | N | Backporting pull request comma-separated assignees list | [] |
|
||||||
| No Reviewers Inheritance | --no-inherit-reviewers | N | Considered only if reviewers is empty, if true keep reviewers as empty list, otherwise inherit from original pull request | false |
|
| No Reviewers Inheritance | --no-inherit-reviewers | N | Considered only if reviewers is empty, if true keep reviewers as empty list, otherwise inherit from original pull request | false |
|
||||||
| Backport Branch Name | --bp-branch-name | N | Name of the backporting pull request branch, if it exceeds 250 chars it will be truncated | bp-{target-branch}-{sha1}...{shaN} |
|
| Backport Branch Names | --bp-branch-name | N | Comma separated lists of the backporting pull request branch names, if they exceeds 250 chars they will be truncated | bp-{target-branch}-{sha1}...{shaN} |
|
||||||
| Labels | --labels | N | Provide custom labels to be added to the backporting pull request | [] |
|
| Labels | --labels | N | Provide custom labels to be added to the backporting pull request | [] |
|
||||||
| Inherit labels | --inherit-labels | N | If enabled inherit lables from the original pull request | false |
|
| Inherit labels | --inherit-labels | N | If enabled inherit lables from the original pull request | false |
|
||||||
| No squash | --no-squash | N | If provided the backporting will try to backport all pull request commits without squashing | false |
|
| No squash | --no-squash | N | If provided the backporting will try to backport all pull request commits without squashing | false |
|
||||||
|
|
|
@ -5,7 +5,7 @@ inputs:
|
||||||
description: "URL of the pull request to backport, e.g., https://github.com/kiegroup/git-backporting/pull/1"
|
description: "URL of the pull request to backport, e.g., https://github.com/kiegroup/git-backporting/pull/1"
|
||||||
required: false
|
required: false
|
||||||
target-branch:
|
target-branch:
|
||||||
description: "Branch where the pull request must be backported to"
|
description: "Comma separated list of branches where the pull request must be backported to"
|
||||||
required: false
|
required: false
|
||||||
config-file:
|
config-file:
|
||||||
description: "Path to a file containing the json configuration for this tool, the object must match the Args interface"
|
description: "Path to a file containing the json configuration for this tool, the object must match the Args interface"
|
||||||
|
@ -36,7 +36,7 @@ inputs:
|
||||||
description: "Backporting PR body. Default is the original PR body"
|
description: "Backporting PR body. Default is the original PR body"
|
||||||
required: false
|
required: false
|
||||||
bp-branch-name:
|
bp-branch-name:
|
||||||
description: "Backporting PR branch name. Default is auto-generated from commit"
|
description: "Comma separated list of backporting PR branch names. Default is auto-generated from commit and target branches"
|
||||||
required: false
|
required: false
|
||||||
reviewers:
|
reviewers:
|
||||||
description: "Comma separated list of reviewers for the backporting pull request"
|
description: "Comma separated list of reviewers for the backporting pull request"
|
||||||
|
|
103
dist/cli/index.js
vendored
103
dist/cli/index.js
vendored
|
@ -40,8 +40,8 @@ class ArgsParser {
|
||||||
parse() {
|
parse() {
|
||||||
const args = this.readArgs();
|
const args = this.readArgs();
|
||||||
// validate and fill with defaults
|
// validate and fill with defaults
|
||||||
if (!args.pullRequest || !args.targetBranch) {
|
if (!args.pullRequest || !args.targetBranch || args.targetBranch.trim().length == 0) {
|
||||||
throw new Error("Missing option: pull request and target branch must be provided");
|
throw new Error("Missing option: pull request and target branches must be provided");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
pullRequest: args.pullRequest,
|
pullRequest: args.pullRequest,
|
||||||
|
@ -179,7 +179,7 @@ class CLIArgsParser extends args_parser_1.default {
|
||||||
return new commander_1.Command(package_json_1.name)
|
return new commander_1.Command(package_json_1.name)
|
||||||
.version(package_json_1.version)
|
.version(package_json_1.version)
|
||||||
.description(package_json_1.description)
|
.description(package_json_1.description)
|
||||||
.option("-tb, --target-branch <branch>", "branch where changes must be backported to")
|
.option("-tb, --target-branch <branches>", "comma separated list of branches where changes must be backported to")
|
||||||
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1")
|
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1")
|
||||||
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
|
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
|
||||||
.option("-a, --auth <auth>", "git service authentication string, e.g., github token")
|
.option("-a, --auth <auth>", "git service authentication string, e.g., github token")
|
||||||
|
@ -189,7 +189,7 @@ class CLIArgsParser extends args_parser_1.default {
|
||||||
.option("--title <bp-title>", "backport pr title, default original pr title prefixed by target branch")
|
.option("--title <bp-title>", "backport pr title, default original pr title prefixed by target branch")
|
||||||
.option("--body <bp-body>", "backport pr title, default original pr body prefixed by bodyPrefix")
|
.option("--body <bp-body>", "backport pr title, default original pr body prefixed by bodyPrefix")
|
||||||
.option("--body-prefix <bp-body-prefix>", "backport pr body prefix, default `backport <original-pr-link>`")
|
.option("--body-prefix <bp-body-prefix>", "backport pr body prefix, default `backport <original-pr-link>`")
|
||||||
.option("--bp-branch-name <bp-branch-name>", "backport pr branch name, default auto-generated by the commit")
|
.option("--bp-branch-name <bp-branch-names>", "comma separated list of backport pr branch names, default auto-generated by the commit and target branch")
|
||||||
.option("--reviewers <reviewers>", "comma separated list of reviewers for the backporting pull request", args_utils_1.getAsCleanedCommaSeparatedList)
|
.option("--reviewers <reviewers>", "comma separated list of reviewers for the backporting pull request", args_utils_1.getAsCleanedCommaSeparatedList)
|
||||||
.option("--assignees <assignees>", "comma separated list of assignees for the backporting pull request", args_utils_1.getAsCleanedCommaSeparatedList)
|
.option("--assignees <assignees>", "comma separated list of assignees for the backporting pull request", args_utils_1.getAsCleanedCommaSeparatedList)
|
||||||
.option("--no-inherit-reviewers", "if provided and reviewers option is empty then inherit them from original pull request")
|
.option("--no-inherit-reviewers", "if provided and reviewers option is empty then inherit them from original pull request")
|
||||||
|
@ -288,6 +288,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
const args_utils_1 = __nccwpck_require__(8048);
|
||||||
const configs_parser_1 = __importDefault(__nccwpck_require__(5799));
|
const configs_parser_1 = __importDefault(__nccwpck_require__(5799));
|
||||||
const git_client_factory_1 = __importDefault(__nccwpck_require__(8550));
|
const git_client_factory_1 = __importDefault(__nccwpck_require__(8550));
|
||||||
class PullRequestConfigsParser extends configs_parser_1.default {
|
class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
|
@ -305,15 +306,19 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const folder = args.folder ?? this.getDefaultFolder();
|
const folder = args.folder ?? this.getDefaultFolder();
|
||||||
|
const targetBranches = [...new Set((0, args_utils_1.getAsCommaSeparatedList)(args.targetBranch))];
|
||||||
|
const bpBranchNames = [...new Set(args.bpBranchName ? ((0, args_utils_1.getAsCleanedCommaSeparatedList)(args.bpBranchName) ?? []) : [])];
|
||||||
|
if (bpBranchNames.length > 1 && bpBranchNames.length != targetBranches.length) {
|
||||||
|
throw new Error(`The number of backport branch names, if provided, must match the number of target branches or just one, provided ${bpBranchNames.length} branch names instead`);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
dryRun: args.dryRun,
|
dryRun: args.dryRun,
|
||||||
auth: args.auth,
|
auth: args.auth,
|
||||||
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
||||||
targetBranch: args.targetBranch,
|
|
||||||
mergeStrategy: args.strategy,
|
mergeStrategy: args.strategy,
|
||||||
mergeStrategyOption: args.strategyOption,
|
mergeStrategyOption: args.strategyOption,
|
||||||
originalPullRequest: pr,
|
originalPullRequest: pr,
|
||||||
backportPullRequest: this.getDefaultBackportPullRequest(pr, args),
|
backportPullRequests: this.generateBackportPullRequestsData(pr, args, targetBranches, bpBranchNames),
|
||||||
git: {
|
git: {
|
||||||
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||||
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
||||||
|
@ -330,7 +335,7 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
* @param targetBranch target branch where the backport should be applied
|
* @param targetBranch target branch where the backport should be applied
|
||||||
* @returns {GitPullRequest}
|
* @returns {GitPullRequest}
|
||||||
*/
|
*/
|
||||||
getDefaultBackportPullRequest(originalPullRequest, args) {
|
generateBackportPullRequestsData(originalPullRequest, args, targetBranches, bpBranchNames) {
|
||||||
const reviewers = args.reviewers ?? [];
|
const reviewers = args.reviewers ?? [];
|
||||||
if (reviewers.length == 0 && args.inheritReviewers) {
|
if (reviewers.length == 0 && args.inheritReviewers) {
|
||||||
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
||||||
|
@ -345,11 +350,18 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
if (args.inheritLabels) {
|
if (args.inheritLabels) {
|
||||||
labels.push(...originalPullRequest.labels);
|
labels.push(...originalPullRequest.labels);
|
||||||
}
|
}
|
||||||
let backportBranch = args.bpBranchName;
|
return targetBranches.map((tb, idx) => {
|
||||||
|
// if there multiple branch names take the corresponding one, otherwise get the the first one if it exists
|
||||||
|
let backportBranch = bpBranchNames.length > 1 ? bpBranchNames[idx] : bpBranchNames[0];
|
||||||
if (backportBranch === undefined || backportBranch.trim() === "") {
|
if (backportBranch === undefined || backportBranch.trim() === "") {
|
||||||
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
||||||
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
||||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
backportBranch = `bp-${tb}-${concatenatedCommits}`;
|
||||||
|
}
|
||||||
|
else if (bpBranchNames.length == 1 && targetBranches.length > 1) {
|
||||||
|
// multiple targets and single custom backport branch name we need to differentiate branch names
|
||||||
|
// so append "-${tb}" to the provided name
|
||||||
|
backportBranch = backportBranch + `-${tb}`;
|
||||||
}
|
}
|
||||||
if (backportBranch.length > 250) {
|
if (backportBranch.length > 250) {
|
||||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||||
|
@ -359,8 +371,8 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
owner: originalPullRequest.targetRepo.owner,
|
owner: originalPullRequest.targetRepo.owner,
|
||||||
repo: originalPullRequest.targetRepo.project,
|
repo: originalPullRequest.targetRepo.project,
|
||||||
head: backportBranch,
|
head: backportBranch,
|
||||||
base: args.targetBranch,
|
base: tb,
|
||||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
title: args.title ?? `[${tb}] ${originalPullRequest.title}`,
|
||||||
// preserve new line chars
|
// preserve new line chars
|
||||||
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
||||||
reviewers: [...new Set(reviewers)],
|
reviewers: [...new Set(reviewers)],
|
||||||
|
@ -368,6 +380,7 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
labels: [...new Set(labels)],
|
labels: [...new Set(labels)],
|
||||||
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
||||||
};
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = PullRequestConfigsParser;
|
exports["default"] = PullRequestConfigsParser;
|
||||||
|
@ -436,10 +449,12 @@ class GitCLIService {
|
||||||
this.logger.info(`Cloning repository ${from} to ${to}`);
|
this.logger.info(`Cloning repository ${from} to ${to}`);
|
||||||
if (!fs_1.default.existsSync(to)) {
|
if (!fs_1.default.existsSync(to)) {
|
||||||
await (0, simple_git_1.default)().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
await (0, simple_git_1.default)().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
this.logger.info(`Folder ${to} already exist. Won't clone`);
|
||||||
this.logger.warn(`Folder ${to} already exist. Won't clone`);
|
// checkout to the proper branch
|
||||||
}
|
this.logger.info(`Checking out branch ${branch}`);
|
||||||
|
await this.git(to).checkout(branch);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create a new branch starting from the current one and checkout in it
|
* Create a new branch starting from the current one and checkout in it
|
||||||
|
@ -1115,22 +1130,31 @@ class ConsoleLoggerService {
|
||||||
this.logger = new logger_1.default();
|
this.logger = new logger_1.default();
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
setContext(newContext) {
|
||||||
|
this.context = newContext;
|
||||||
|
}
|
||||||
|
clearContext() {
|
||||||
|
this.context = undefined;
|
||||||
|
}
|
||||||
trace(message) {
|
trace(message) {
|
||||||
this.logger.log("TRACE", message);
|
this.logger.log("TRACE", this.fromContext(message));
|
||||||
}
|
}
|
||||||
debug(message) {
|
debug(message) {
|
||||||
if (this.verbose) {
|
if (this.verbose) {
|
||||||
this.logger.log("DEBUG", message);
|
this.logger.log("DEBUG", this.fromContext(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info(message) {
|
info(message) {
|
||||||
this.logger.log("INFO", message);
|
this.logger.log("INFO", this.fromContext(message));
|
||||||
}
|
}
|
||||||
warn(message) {
|
warn(message) {
|
||||||
this.logger.log("WARN", message);
|
this.logger.log("WARN", this.fromContext(message));
|
||||||
}
|
}
|
||||||
error(message) {
|
error(message) {
|
||||||
this.logger.log("ERROR", message);
|
this.logger.log("ERROR", this.fromContext(message));
|
||||||
|
}
|
||||||
|
fromContext(msg) {
|
||||||
|
return this.context ? `[${this.context}] ${msg}` : msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = ConsoleLoggerService;
|
exports["default"] = ConsoleLoggerService;
|
||||||
|
@ -1242,39 +1266,62 @@ class Runner {
|
||||||
// 3. parse configs
|
// 3. parse configs
|
||||||
this.logger.debug("Parsing configs..");
|
this.logger.debug("Parsing configs..");
|
||||||
const configs = await new pr_configs_parser_1.default().parseAndValidate(args);
|
const configs = await new pr_configs_parser_1.default().parseAndValidate(args);
|
||||||
const originalPR = configs.originalPullRequest;
|
const backportPRs = configs.backportPullRequests;
|
||||||
const backportPR = configs.backportPullRequest;
|
|
||||||
// start local git operations
|
// start local git operations
|
||||||
const git = new git_cli_1.default(configs.auth, configs.git);
|
const git = new git_cli_1.default(configs.auth, configs.git);
|
||||||
|
const failures = [];
|
||||||
|
// we need sequential backporting as they will operate on the same folder
|
||||||
|
// avoid cloning the same repo multiple times
|
||||||
|
for (const pr of backportPRs) {
|
||||||
|
try {
|
||||||
|
await this.executeBackport(configs, pr, {
|
||||||
|
gitClientType: gitClientType,
|
||||||
|
gitClientApi: gitApi,
|
||||||
|
gitCli: git,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
this.logger.error(`Something went wrong backporting to ${pr.base}: ${error}`);
|
||||||
|
failures.push(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failures.length > 0) {
|
||||||
|
throw new Error(`Failure occurred during one of the backports: [${failures.join(" ; ")}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async executeBackport(configs, backportPR, git) {
|
||||||
|
this.logger.setContext(backportPR.base);
|
||||||
|
const originalPR = configs.originalPullRequest;
|
||||||
// 4. clone the repository
|
// 4. clone the repository
|
||||||
this.logger.debug("Cloning repo..");
|
this.logger.debug("Cloning repo..");
|
||||||
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
|
await git.gitCli.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, backportPR.base);
|
||||||
// 5. create new branch from target one and checkout
|
// 5. create new branch from target one and checkout
|
||||||
this.logger.debug("Creating local branch..");
|
this.logger.debug("Creating local branch..");
|
||||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
await git.gitCli.createLocalBranch(configs.folder, backportPR.head);
|
||||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||||
configs.originalPullRequest.state === "open") {
|
configs.originalPullRequest.state === "open") {
|
||||||
this.logger.debug("Fetching pull request remote..");
|
this.logger.debug("Fetching pull request remote..");
|
||||||
const prefix = gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
const prefix = git.gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||||
await git.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||||
}
|
}
|
||||||
// 7. apply all changes to the new branch
|
// 7. apply all changes to the new branch
|
||||||
this.logger.debug("Cherry picking commits..");
|
this.logger.debug("Cherry picking commits..");
|
||||||
for (const sha of originalPR.commits) {
|
for (const sha of originalPR.commits) {
|
||||||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
await git.gitCli.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||||
}
|
}
|
||||||
if (!configs.dryRun) {
|
if (!configs.dryRun) {
|
||||||
// 8. push the new branch to origin
|
// 8. push the new branch to origin
|
||||||
await git.push(configs.folder, backportPR.head);
|
await git.gitCli.push(configs.folder, backportPR.head);
|
||||||
// 9. create pull request new branch -> target branch (using octokit)
|
// 9. create pull request new branch -> target branch (using octokit)
|
||||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
const prUrl = await git.gitClientApi.createPullRequest(backportPR);
|
||||||
this.logger.info(`Pull request created: ${prUrl}`);
|
this.logger.info(`Pull request created: ${prUrl}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.logger.warn("Pull request creation and remote push skipped");
|
this.logger.warn("Pull request creation and remote push skipped");
|
||||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||||
}
|
}
|
||||||
|
this.logger.clearContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = Runner;
|
exports["default"] = Runner;
|
||||||
|
|
99
dist/gha/index.js
vendored
99
dist/gha/index.js
vendored
|
@ -40,8 +40,8 @@ class ArgsParser {
|
||||||
parse() {
|
parse() {
|
||||||
const args = this.readArgs();
|
const args = this.readArgs();
|
||||||
// validate and fill with defaults
|
// validate and fill with defaults
|
||||||
if (!args.pullRequest || !args.targetBranch) {
|
if (!args.pullRequest || !args.targetBranch || args.targetBranch.trim().length == 0) {
|
||||||
throw new Error("Missing option: pull request and target branch must be provided");
|
throw new Error("Missing option: pull request and target branches must be provided");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
pullRequest: args.pullRequest,
|
pullRequest: args.pullRequest,
|
||||||
|
@ -258,6 +258,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
const args_utils_1 = __nccwpck_require__(8048);
|
||||||
const configs_parser_1 = __importDefault(__nccwpck_require__(5799));
|
const configs_parser_1 = __importDefault(__nccwpck_require__(5799));
|
||||||
const git_client_factory_1 = __importDefault(__nccwpck_require__(8550));
|
const git_client_factory_1 = __importDefault(__nccwpck_require__(8550));
|
||||||
class PullRequestConfigsParser extends configs_parser_1.default {
|
class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
|
@ -275,15 +276,19 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const folder = args.folder ?? this.getDefaultFolder();
|
const folder = args.folder ?? this.getDefaultFolder();
|
||||||
|
const targetBranches = [...new Set((0, args_utils_1.getAsCommaSeparatedList)(args.targetBranch))];
|
||||||
|
const bpBranchNames = [...new Set(args.bpBranchName ? ((0, args_utils_1.getAsCleanedCommaSeparatedList)(args.bpBranchName) ?? []) : [])];
|
||||||
|
if (bpBranchNames.length > 1 && bpBranchNames.length != targetBranches.length) {
|
||||||
|
throw new Error(`The number of backport branch names, if provided, must match the number of target branches or just one, provided ${bpBranchNames.length} branch names instead`);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
dryRun: args.dryRun,
|
dryRun: args.dryRun,
|
||||||
auth: args.auth,
|
auth: args.auth,
|
||||||
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
||||||
targetBranch: args.targetBranch,
|
|
||||||
mergeStrategy: args.strategy,
|
mergeStrategy: args.strategy,
|
||||||
mergeStrategyOption: args.strategyOption,
|
mergeStrategyOption: args.strategyOption,
|
||||||
originalPullRequest: pr,
|
originalPullRequest: pr,
|
||||||
backportPullRequest: this.getDefaultBackportPullRequest(pr, args),
|
backportPullRequests: this.generateBackportPullRequestsData(pr, args, targetBranches, bpBranchNames),
|
||||||
git: {
|
git: {
|
||||||
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||||
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
||||||
|
@ -300,7 +305,7 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
* @param targetBranch target branch where the backport should be applied
|
* @param targetBranch target branch where the backport should be applied
|
||||||
* @returns {GitPullRequest}
|
* @returns {GitPullRequest}
|
||||||
*/
|
*/
|
||||||
getDefaultBackportPullRequest(originalPullRequest, args) {
|
generateBackportPullRequestsData(originalPullRequest, args, targetBranches, bpBranchNames) {
|
||||||
const reviewers = args.reviewers ?? [];
|
const reviewers = args.reviewers ?? [];
|
||||||
if (reviewers.length == 0 && args.inheritReviewers) {
|
if (reviewers.length == 0 && args.inheritReviewers) {
|
||||||
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
||||||
|
@ -315,11 +320,18 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
if (args.inheritLabels) {
|
if (args.inheritLabels) {
|
||||||
labels.push(...originalPullRequest.labels);
|
labels.push(...originalPullRequest.labels);
|
||||||
}
|
}
|
||||||
let backportBranch = args.bpBranchName;
|
return targetBranches.map((tb, idx) => {
|
||||||
|
// if there multiple branch names take the corresponding one, otherwise get the the first one if it exists
|
||||||
|
let backportBranch = bpBranchNames.length > 1 ? bpBranchNames[idx] : bpBranchNames[0];
|
||||||
if (backportBranch === undefined || backportBranch.trim() === "") {
|
if (backportBranch === undefined || backportBranch.trim() === "") {
|
||||||
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
||||||
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
||||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
backportBranch = `bp-${tb}-${concatenatedCommits}`;
|
||||||
|
}
|
||||||
|
else if (bpBranchNames.length == 1 && targetBranches.length > 1) {
|
||||||
|
// multiple targets and single custom backport branch name we need to differentiate branch names
|
||||||
|
// so append "-${tb}" to the provided name
|
||||||
|
backportBranch = backportBranch + `-${tb}`;
|
||||||
}
|
}
|
||||||
if (backportBranch.length > 250) {
|
if (backportBranch.length > 250) {
|
||||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||||
|
@ -329,8 +341,8 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
owner: originalPullRequest.targetRepo.owner,
|
owner: originalPullRequest.targetRepo.owner,
|
||||||
repo: originalPullRequest.targetRepo.project,
|
repo: originalPullRequest.targetRepo.project,
|
||||||
head: backportBranch,
|
head: backportBranch,
|
||||||
base: args.targetBranch,
|
base: tb,
|
||||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
title: args.title ?? `[${tb}] ${originalPullRequest.title}`,
|
||||||
// preserve new line chars
|
// preserve new line chars
|
||||||
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
||||||
reviewers: [...new Set(reviewers)],
|
reviewers: [...new Set(reviewers)],
|
||||||
|
@ -338,6 +350,7 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
||||||
labels: [...new Set(labels)],
|
labels: [...new Set(labels)],
|
||||||
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
||||||
};
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = PullRequestConfigsParser;
|
exports["default"] = PullRequestConfigsParser;
|
||||||
|
@ -406,10 +419,12 @@ class GitCLIService {
|
||||||
this.logger.info(`Cloning repository ${from} to ${to}`);
|
this.logger.info(`Cloning repository ${from} to ${to}`);
|
||||||
if (!fs_1.default.existsSync(to)) {
|
if (!fs_1.default.existsSync(to)) {
|
||||||
await (0, simple_git_1.default)().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
await (0, simple_git_1.default)().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
this.logger.info(`Folder ${to} already exist. Won't clone`);
|
||||||
this.logger.warn(`Folder ${to} already exist. Won't clone`);
|
// checkout to the proper branch
|
||||||
}
|
this.logger.info(`Checking out branch ${branch}`);
|
||||||
|
await this.git(to).checkout(branch);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create a new branch starting from the current one and checkout in it
|
* Create a new branch starting from the current one and checkout in it
|
||||||
|
@ -1085,22 +1100,31 @@ class ConsoleLoggerService {
|
||||||
this.logger = new logger_1.default();
|
this.logger = new logger_1.default();
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
setContext(newContext) {
|
||||||
|
this.context = newContext;
|
||||||
|
}
|
||||||
|
clearContext() {
|
||||||
|
this.context = undefined;
|
||||||
|
}
|
||||||
trace(message) {
|
trace(message) {
|
||||||
this.logger.log("TRACE", message);
|
this.logger.log("TRACE", this.fromContext(message));
|
||||||
}
|
}
|
||||||
debug(message) {
|
debug(message) {
|
||||||
if (this.verbose) {
|
if (this.verbose) {
|
||||||
this.logger.log("DEBUG", message);
|
this.logger.log("DEBUG", this.fromContext(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info(message) {
|
info(message) {
|
||||||
this.logger.log("INFO", message);
|
this.logger.log("INFO", this.fromContext(message));
|
||||||
}
|
}
|
||||||
warn(message) {
|
warn(message) {
|
||||||
this.logger.log("WARN", message);
|
this.logger.log("WARN", this.fromContext(message));
|
||||||
}
|
}
|
||||||
error(message) {
|
error(message) {
|
||||||
this.logger.log("ERROR", message);
|
this.logger.log("ERROR", this.fromContext(message));
|
||||||
|
}
|
||||||
|
fromContext(msg) {
|
||||||
|
return this.context ? `[${this.context}] ${msg}` : msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = ConsoleLoggerService;
|
exports["default"] = ConsoleLoggerService;
|
||||||
|
@ -1212,39 +1236,62 @@ class Runner {
|
||||||
// 3. parse configs
|
// 3. parse configs
|
||||||
this.logger.debug("Parsing configs..");
|
this.logger.debug("Parsing configs..");
|
||||||
const configs = await new pr_configs_parser_1.default().parseAndValidate(args);
|
const configs = await new pr_configs_parser_1.default().parseAndValidate(args);
|
||||||
const originalPR = configs.originalPullRequest;
|
const backportPRs = configs.backportPullRequests;
|
||||||
const backportPR = configs.backportPullRequest;
|
|
||||||
// start local git operations
|
// start local git operations
|
||||||
const git = new git_cli_1.default(configs.auth, configs.git);
|
const git = new git_cli_1.default(configs.auth, configs.git);
|
||||||
|
const failures = [];
|
||||||
|
// we need sequential backporting as they will operate on the same folder
|
||||||
|
// avoid cloning the same repo multiple times
|
||||||
|
for (const pr of backportPRs) {
|
||||||
|
try {
|
||||||
|
await this.executeBackport(configs, pr, {
|
||||||
|
gitClientType: gitClientType,
|
||||||
|
gitClientApi: gitApi,
|
||||||
|
gitCli: git,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
this.logger.error(`Something went wrong backporting to ${pr.base}: ${error}`);
|
||||||
|
failures.push(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failures.length > 0) {
|
||||||
|
throw new Error(`Failure occurred during one of the backports: [${failures.join(" ; ")}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async executeBackport(configs, backportPR, git) {
|
||||||
|
this.logger.setContext(backportPR.base);
|
||||||
|
const originalPR = configs.originalPullRequest;
|
||||||
// 4. clone the repository
|
// 4. clone the repository
|
||||||
this.logger.debug("Cloning repo..");
|
this.logger.debug("Cloning repo..");
|
||||||
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
|
await git.gitCli.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, backportPR.base);
|
||||||
// 5. create new branch from target one and checkout
|
// 5. create new branch from target one and checkout
|
||||||
this.logger.debug("Creating local branch..");
|
this.logger.debug("Creating local branch..");
|
||||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
await git.gitCli.createLocalBranch(configs.folder, backportPR.head);
|
||||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||||
configs.originalPullRequest.state === "open") {
|
configs.originalPullRequest.state === "open") {
|
||||||
this.logger.debug("Fetching pull request remote..");
|
this.logger.debug("Fetching pull request remote..");
|
||||||
const prefix = gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
const prefix = git.gitClientType === git_types_1.GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||||
await git.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||||
}
|
}
|
||||||
// 7. apply all changes to the new branch
|
// 7. apply all changes to the new branch
|
||||||
this.logger.debug("Cherry picking commits..");
|
this.logger.debug("Cherry picking commits..");
|
||||||
for (const sha of originalPR.commits) {
|
for (const sha of originalPR.commits) {
|
||||||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
await git.gitCli.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||||
}
|
}
|
||||||
if (!configs.dryRun) {
|
if (!configs.dryRun) {
|
||||||
// 8. push the new branch to origin
|
// 8. push the new branch to origin
|
||||||
await git.push(configs.folder, backportPR.head);
|
await git.gitCli.push(configs.folder, backportPR.head);
|
||||||
// 9. create pull request new branch -> target branch (using octokit)
|
// 9. create pull request new branch -> target branch (using octokit)
|
||||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
const prUrl = await git.gitClientApi.createPullRequest(backportPR);
|
||||||
this.logger.info(`Pull request created: ${prUrl}`);
|
this.logger.info(`Pull request created: ${prUrl}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.logger.warn("Pull request creation and remote push skipped");
|
this.logger.warn("Pull request creation and remote push skipped");
|
||||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||||
}
|
}
|
||||||
|
this.logger.clearContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports["default"] = Runner;
|
exports["default"] = Runner;
|
||||||
|
|
|
@ -17,8 +17,8 @@ export default abstract class ArgsParser {
|
||||||
const args = this.readArgs();
|
const args = this.readArgs();
|
||||||
|
|
||||||
// validate and fill with defaults
|
// validate and fill with defaults
|
||||||
if (!args.pullRequest || !args.targetBranch) {
|
if (!args.pullRequest || !args.targetBranch || args.targetBranch.trim().length == 0) {
|
||||||
throw new Error("Missing option: pull request and target branch must be provided");
|
throw new Error("Missing option: pull request and target branches must be provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* Input arguments
|
* Tool's input arguments interface
|
||||||
*/
|
*/
|
||||||
export interface Args {
|
export interface Args {
|
||||||
targetBranch: string, // branch on the target repo where the change should be backported to
|
// NOTE: keep targetBranch as singular and of type string for backward compatibilities
|
||||||
|
targetBranch: string, // comma separated list of branches on the target repo where the change should be backported to
|
||||||
pullRequest: string, // url of the pull request to backport
|
pullRequest: string, // url of the pull request to backport
|
||||||
dryRun?: boolean, // if enabled do not push anything remotely
|
dryRun?: boolean, // if enabled do not push anything remotely
|
||||||
auth?: string, // git service auth, like github token
|
auth?: string, // git service auth, like github token
|
||||||
|
@ -12,7 +13,8 @@ export interface Args {
|
||||||
title?: string, // backport pr title, default original pr title prefixed by target branch
|
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
|
body?: string, // backport pr title, default original pr body prefixed by bodyPrefix
|
||||||
bodyPrefix?: string, // backport pr body prefix, default `backport <original-pr-link>`
|
bodyPrefix?: string, // backport pr body prefix, default `backport <original-pr-link>`
|
||||||
bpBranchName?: string, // backport pr branch name, default computed from commit
|
// NOTE: keep bpBranchName as singular and of type string for backward compatibilities
|
||||||
|
bpBranchName?: string, // comma separated list of backport pr branch names, default computed from commit and target branches
|
||||||
reviewers?: string[], // backport pr reviewers
|
reviewers?: string[], // backport pr reviewers
|
||||||
assignees?: string[], // backport pr assignees
|
assignees?: string[], // backport pr assignees
|
||||||
inheritReviewers?: boolean, // if true and reviewers == [] then inherit reviewers from original pr
|
inheritReviewers?: boolean, // if true and reviewers == [] then inherit reviewers from original pr
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default class CLIArgsParser extends ArgsParser {
|
||||||
return new Command(name)
|
return new Command(name)
|
||||||
.version(version)
|
.version(version)
|
||||||
.description(description)
|
.description(description)
|
||||||
.option("-tb, --target-branch <branch>", "branch where changes must be backported to")
|
.option("-tb, --target-branch <branches>", "comma separated list of branches where changes must be backported to")
|
||||||
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1")
|
.option("-pr, --pull-request <pr-url>", "pull request url, e.g., https://github.com/kiegroup/git-backporting/pull/1")
|
||||||
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
|
.option("-d, --dry-run", "if enabled the tool does not create any pull request nor push anything remotely")
|
||||||
.option("-a, --auth <auth>", "git service authentication string, e.g., github token")
|
.option("-a, --auth <auth>", "git service authentication string, e.g., github token")
|
||||||
|
@ -20,7 +20,7 @@ export default class CLIArgsParser extends ArgsParser {
|
||||||
.option("--title <bp-title>", "backport pr title, default original pr title prefixed by target branch")
|
.option("--title <bp-title>", "backport pr title, default original pr title prefixed by target branch")
|
||||||
.option("--body <bp-body>", "backport pr title, default original pr body prefixed by bodyPrefix")
|
.option("--body <bp-body>", "backport pr title, default original pr body prefixed by bodyPrefix")
|
||||||
.option("--body-prefix <bp-body-prefix>", "backport pr body prefix, default `backport <original-pr-link>`")
|
.option("--body-prefix <bp-body-prefix>", "backport pr body prefix, default `backport <original-pr-link>`")
|
||||||
.option("--bp-branch-name <bp-branch-name>", "backport pr branch name, default auto-generated by the commit")
|
.option("--bp-branch-name <bp-branch-names>", "comma separated list of backport pr branch names, default auto-generated by the commit and target branch")
|
||||||
.option("--reviewers <reviewers>", "comma separated list of reviewers for the backporting pull request", getAsCleanedCommaSeparatedList)
|
.option("--reviewers <reviewers>", "comma separated list of reviewers for the backporting pull request", getAsCleanedCommaSeparatedList)
|
||||||
.option("--assignees <assignees>", "comma separated list of assignees for the backporting pull request", getAsCleanedCommaSeparatedList)
|
.option("--assignees <assignees>", "comma separated list of assignees for the backporting pull request", getAsCleanedCommaSeparatedList)
|
||||||
.option("--no-inherit-reviewers", "if provided and reviewers option is empty then inherit them from original pull request")
|
.option("--no-inherit-reviewers", "if provided and reviewers option is empty then inherit them from original pull request")
|
||||||
|
|
|
@ -15,10 +15,9 @@ export interface Configs {
|
||||||
auth?: string,
|
auth?: string,
|
||||||
git: LocalGit,
|
git: LocalGit,
|
||||||
folder: string,
|
folder: string,
|
||||||
targetBranch: string,
|
|
||||||
mergeStrategy?: string, // cherry-pick merge strategy
|
mergeStrategy?: string, // cherry-pick merge strategy
|
||||||
mergeStrategyOption?: string, // cherry-pick merge strategy option
|
mergeStrategyOption?: string, // cherry-pick merge strategy option
|
||||||
originalPullRequest: GitPullRequest,
|
originalPullRequest: GitPullRequest,
|
||||||
backportPullRequest: BackportPullRequest,
|
backportPullRequests: BackportPullRequest[],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { getAsCleanedCommaSeparatedList, getAsCommaSeparatedList } from "@bp/service/args/args-utils";
|
||||||
import { Args } from "@bp/service/args/args.types";
|
import { Args } from "@bp/service/args/args.types";
|
||||||
import ConfigsParser from "@bp/service/configs/configs-parser";
|
import ConfigsParser from "@bp/service/configs/configs-parser";
|
||||||
import { Configs } from "@bp/service/configs/configs.types";
|
import { Configs } from "@bp/service/configs/configs.types";
|
||||||
|
@ -25,15 +26,21 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
||||||
|
|
||||||
const folder: string = args.folder ?? this.getDefaultFolder();
|
const folder: string = args.folder ?? this.getDefaultFolder();
|
||||||
|
|
||||||
|
const targetBranches: string[] = [...new Set(getAsCommaSeparatedList(args.targetBranch)!)];
|
||||||
|
const bpBranchNames: string[] = [...new Set(args.bpBranchName ? (getAsCleanedCommaSeparatedList(args.bpBranchName) ?? []) : [])];
|
||||||
|
|
||||||
|
if (bpBranchNames.length > 1 && bpBranchNames.length != targetBranches.length) {
|
||||||
|
throw new Error(`The number of backport branch names, if provided, must match the number of target branches or just one, provided ${bpBranchNames.length} branch names instead`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dryRun: args.dryRun!,
|
dryRun: args.dryRun!,
|
||||||
auth: args.auth,
|
auth: args.auth,
|
||||||
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
folder: `${folder.startsWith("/") ? "" : process.cwd() + "/"}${args.folder ?? this.getDefaultFolder()}`,
|
||||||
targetBranch: args.targetBranch,
|
|
||||||
mergeStrategy: args.strategy,
|
mergeStrategy: args.strategy,
|
||||||
mergeStrategyOption: args.strategyOption,
|
mergeStrategyOption: args.strategyOption,
|
||||||
originalPullRequest: pr,
|
originalPullRequest: pr,
|
||||||
backportPullRequest: this.getDefaultBackportPullRequest(pr, args),
|
backportPullRequests: this.generateBackportPullRequestsData(pr, args, targetBranches, bpBranchNames),
|
||||||
git: {
|
git: {
|
||||||
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
user: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||||
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
email: args.gitEmail ?? this.gitClient.getDefaultGitEmail(),
|
||||||
|
@ -52,7 +59,13 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
||||||
* @param targetBranch target branch where the backport should be applied
|
* @param targetBranch target branch where the backport should be applied
|
||||||
* @returns {GitPullRequest}
|
* @returns {GitPullRequest}
|
||||||
*/
|
*/
|
||||||
private getDefaultBackportPullRequest(originalPullRequest: GitPullRequest, args: Args): BackportPullRequest {
|
private generateBackportPullRequestsData(
|
||||||
|
originalPullRequest: GitPullRequest,
|
||||||
|
args: Args,
|
||||||
|
targetBranches: string[],
|
||||||
|
bpBranchNames: string[]
|
||||||
|
): BackportPullRequest[] {
|
||||||
|
|
||||||
const reviewers = args.reviewers ?? [];
|
const reviewers = args.reviewers ?? [];
|
||||||
if (reviewers.length == 0 && args.inheritReviewers) {
|
if (reviewers.length == 0 && args.inheritReviewers) {
|
||||||
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
||||||
|
@ -70,11 +83,18 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
||||||
labels.push(...originalPullRequest.labels);
|
labels.push(...originalPullRequest.labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
let backportBranch = args.bpBranchName;
|
return targetBranches.map((tb, idx) => {
|
||||||
|
|
||||||
|
// if there multiple branch names take the corresponding one, otherwise get the the first one if it exists
|
||||||
|
let backportBranch = bpBranchNames.length > 1 ? bpBranchNames[idx] : bpBranchNames[0];
|
||||||
if (backportBranch === undefined || backportBranch.trim() === "") {
|
if (backportBranch === undefined || backportBranch.trim() === "") {
|
||||||
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
// for each commit takes the first 7 chars that are enough to uniquely identify them in most of the projects
|
||||||
const concatenatedCommits: string = originalPullRequest.commits!.map(c => c.slice(0, 7)).join("-");
|
const concatenatedCommits: string = originalPullRequest.commits!.map(c => c.slice(0, 7)).join("-");
|
||||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
backportBranch = `bp-${tb}-${concatenatedCommits}`;
|
||||||
|
} else if (bpBranchNames.length == 1 && targetBranches.length > 1) {
|
||||||
|
// multiple targets and single custom backport branch name we need to differentiate branch names
|
||||||
|
// so append "-${tb}" to the provided name
|
||||||
|
backportBranch = backportBranch + `-${tb}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backportBranch.length > 250) {
|
if (backportBranch.length > 250) {
|
||||||
|
@ -86,8 +106,8 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
||||||
owner: originalPullRequest.targetRepo.owner,
|
owner: originalPullRequest.targetRepo.owner,
|
||||||
repo: originalPullRequest.targetRepo.project,
|
repo: originalPullRequest.targetRepo.project,
|
||||||
head: backportBranch,
|
head: backportBranch,
|
||||||
base: args.targetBranch,
|
base: tb,
|
||||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
title: args.title ?? `[${tb}] ${originalPullRequest.title}`,
|
||||||
// preserve new line chars
|
// preserve new line chars
|
||||||
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
body: body.replace(/\\n/g, "\n").replace(/\\r/g, "\r"),
|
||||||
reviewers: [...new Set(reviewers)],
|
reviewers: [...new Set(reviewers)],
|
||||||
|
@ -95,5 +115,6 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
||||||
labels: [...new Set(labels)],
|
labels: [...new Set(labels)],
|
||||||
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
comments: args.comments?.map(c => c.replace(/\\n/g, "\n").replace(/\\r/g, "\r")) ?? [],
|
||||||
};
|
};
|
||||||
|
}) as BackportPullRequest[];
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -63,9 +63,13 @@ export default class GitCLIService {
|
||||||
this.logger.info(`Cloning repository ${from} to ${to}`);
|
this.logger.info(`Cloning repository ${from} to ${to}`);
|
||||||
if (!fs.existsSync(to)) {
|
if (!fs.existsSync(to)) {
|
||||||
await simpleGit().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
await simpleGit().clone(this.remoteWithAuth(from), to, ["--quiet", "--shallow-submodules", "--no-tags", "--branch", branch]);
|
||||||
} else {
|
return;
|
||||||
this.logger.warn(`Folder ${to} already exist. Won't clone`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.logger.info(`Folder ${to} already exist. Won't clone`);
|
||||||
|
// checkout to the proper branch
|
||||||
|
this.logger.info(`Checking out branch ${branch}`);
|
||||||
|
await this.git(to).checkout(branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,32 +5,44 @@ export default class ConsoleLoggerService implements LoggerService {
|
||||||
|
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
private readonly verbose: boolean;
|
private readonly verbose: boolean;
|
||||||
|
private context?: string;
|
||||||
|
|
||||||
constructor(verbose = true) {
|
constructor(verbose = true) {
|
||||||
this.logger = new Logger();
|
this.logger = new Logger();
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setContext(newContext: string) {
|
||||||
|
this.context = newContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearContext() {
|
||||||
|
this.context = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
trace(message: string): void {
|
trace(message: string): void {
|
||||||
this.logger.log("TRACE", message);
|
this.logger.log("TRACE", this.fromContext(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(message: string): void {
|
debug(message: string): void {
|
||||||
if (this.verbose) {
|
if (this.verbose) {
|
||||||
this.logger.log("DEBUG", message);
|
this.logger.log("DEBUG", this.fromContext(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info(message: string): void {
|
info(message: string): void {
|
||||||
this.logger.log("INFO", message);
|
this.logger.log("INFO", this.fromContext(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
warn(message: string): void {
|
warn(message: string): void {
|
||||||
this.logger.log("WARN", message);
|
this.logger.log("WARN", this.fromContext(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
error(message: string): void {
|
error(message: string): void {
|
||||||
this.logger.log("ERROR", message);
|
this.logger.log("ERROR", this.fromContext(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fromContext(msg: string): string {
|
||||||
|
return this.context ? `[${this.context}] ${msg}` : msg;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,6 +3,10 @@
|
||||||
*/
|
*/
|
||||||
export default interface LoggerService {
|
export default interface LoggerService {
|
||||||
|
|
||||||
|
setContext(newContext: string): void;
|
||||||
|
|
||||||
|
clearContext(): void;
|
||||||
|
|
||||||
trace(message: string): void;
|
trace(message: string): void;
|
||||||
|
|
||||||
debug(message: string): void;
|
debug(message: string): void;
|
||||||
|
|
|
@ -10,6 +10,12 @@ import LoggerService from "@bp/service/logger/logger-service";
|
||||||
import LoggerServiceFactory from "@bp/service/logger/logger-service-factory";
|
import LoggerServiceFactory from "@bp/service/logger/logger-service-factory";
|
||||||
import { inferGitClient, inferGitApiUrl } from "@bp/service/git/git-util";
|
import { inferGitClient, inferGitApiUrl } from "@bp/service/git/git-util";
|
||||||
|
|
||||||
|
interface Git {
|
||||||
|
gitClientType: GitClientType;
|
||||||
|
gitClientApi: GitClient;
|
||||||
|
gitCli: GitCLIService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main runner implementation, it implements the core logic flow
|
* Main runner implementation, it implements the core logic flow
|
||||||
*/
|
*/
|
||||||
|
@ -62,47 +68,73 @@ export default class Runner {
|
||||||
// 3. parse configs
|
// 3. parse configs
|
||||||
this.logger.debug("Parsing configs..");
|
this.logger.debug("Parsing configs..");
|
||||||
const configs: Configs = await new PullRequestConfigsParser().parseAndValidate(args);
|
const configs: Configs = await new PullRequestConfigsParser().parseAndValidate(args);
|
||||||
const originalPR: GitPullRequest = configs.originalPullRequest;
|
const backportPRs: BackportPullRequest[] = configs.backportPullRequests;
|
||||||
const backportPR: BackportPullRequest = configs.backportPullRequest;
|
|
||||||
|
|
||||||
// start local git operations
|
// start local git operations
|
||||||
const git: GitCLIService = new GitCLIService(configs.auth, configs.git);
|
const git: GitCLIService = new GitCLIService(configs.auth, configs.git);
|
||||||
|
|
||||||
|
const failures: string[] = [];
|
||||||
|
// we need sequential backporting as they will operate on the same folder
|
||||||
|
// avoid cloning the same repo multiple times
|
||||||
|
for(const pr of backportPRs) {
|
||||||
|
try {
|
||||||
|
await this.executeBackport(configs, pr, {
|
||||||
|
gitClientType: gitClientType,
|
||||||
|
gitClientApi: gitApi,
|
||||||
|
gitCli: git,
|
||||||
|
});
|
||||||
|
} catch(error) {
|
||||||
|
this.logger.error(`Something went wrong backporting to ${pr.base}: ${error}`);
|
||||||
|
failures.push(error as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failures.length > 0) {
|
||||||
|
throw new Error(`Failure occurred during one of the backports: [${failures.join(" ; ")}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeBackport(configs: Configs, backportPR: BackportPullRequest, git: Git): Promise<void> {
|
||||||
|
this.logger.setContext(backportPR.base);
|
||||||
|
|
||||||
|
const originalPR: GitPullRequest = configs.originalPullRequest;
|
||||||
|
|
||||||
// 4. clone the repository
|
// 4. clone the repository
|
||||||
this.logger.debug("Cloning repo..");
|
this.logger.debug("Cloning repo..");
|
||||||
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
|
await git.gitCli.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, backportPR.base);
|
||||||
|
|
||||||
// 5. create new branch from target one and checkout
|
// 5. create new branch from target one and checkout
|
||||||
this.logger.debug("Creating local branch..");
|
this.logger.debug("Creating local branch..");
|
||||||
|
|
||||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
await git.gitCli.createLocalBranch(configs.folder, backportPR.head);
|
||||||
|
|
||||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||||
configs.originalPullRequest.state === "open") {
|
configs.originalPullRequest.state === "open") {
|
||||||
this.logger.debug("Fetching pull request remote..");
|
this.logger.debug("Fetching pull request remote..");
|
||||||
const prefix = gitClientType === GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
const prefix = git.gitClientType === GitClientType.GITHUB ? "pull" : "merge-requests"; // default is for gitlab
|
||||||
await git.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
await git.gitCli.fetch(configs.folder, `${prefix}/${configs.originalPullRequest.number}/head:pr/${configs.originalPullRequest.number}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. apply all changes to the new branch
|
// 7. apply all changes to the new branch
|
||||||
this.logger.debug("Cherry picking commits..");
|
this.logger.debug("Cherry picking commits..");
|
||||||
for (const sha of originalPR.commits!) {
|
for (const sha of originalPR.commits!) {
|
||||||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
await git.gitCli.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!configs.dryRun) {
|
if (!configs.dryRun) {
|
||||||
// 8. push the new branch to origin
|
// 8. push the new branch to origin
|
||||||
await git.push(configs.folder, backportPR.head);
|
await git.gitCli.push(configs.folder, backportPR.head);
|
||||||
|
|
||||||
// 9. create pull request new branch -> target branch (using octokit)
|
// 9. create pull request new branch -> target branch (using octokit)
|
||||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
const prUrl = await git.gitClientApi.createPullRequest(backportPR);
|
||||||
this.logger.info(`Pull request created: ${prUrl}`);
|
this.logger.info(`Pull request created: ${prUrl}`);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn("Pull request creation and remote push skipped");
|
this.logger.warn("Pull request creation and remote push skipped");
|
||||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
this.logger.clearContext();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -433,4 +433,63 @@ describe("cli args parser", () => {
|
||||||
expect(args.squash).toEqual(true);
|
expect(args.squash).toEqual(true);
|
||||||
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("valid execution with multiple branches", () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
"target, old",
|
||||||
|
"-pr",
|
||||||
|
"https://localhost/whatever/pulls/1"
|
||||||
|
]);
|
||||||
|
|
||||||
|
const args: Args = parser.parse();
|
||||||
|
expect(args.dryRun).toEqual(false);
|
||||||
|
expect(args.auth).toEqual(undefined);
|
||||||
|
expect(args.gitUser).toEqual(undefined);
|
||||||
|
expect(args.gitEmail).toEqual(undefined);
|
||||||
|
expect(args.folder).toEqual(undefined);
|
||||||
|
expect(args.targetBranch).toEqual("target, old");
|
||||||
|
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);
|
||||||
|
expect(args.reviewers).toEqual([]);
|
||||||
|
expect(args.assignees).toEqual([]);
|
||||||
|
expect(args.inheritReviewers).toEqual(true);
|
||||||
|
expect(args.labels).toEqual([]);
|
||||||
|
expect(args.inheritLabels).toEqual(false);
|
||||||
|
expect(args.squash).toEqual(true);
|
||||||
|
expect(args.strategy).toEqual(undefined);
|
||||||
|
expect(args.strategyOption).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid execution with empty target branch", () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
" ",
|
||||||
|
"-pr",
|
||||||
|
"https://localhost/whatever/pulls/1"
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid execution with missing mandatory target branch", () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-pr",
|
||||||
|
"https://localhost/whatever/pulls/1"
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid execution with missin mandatory pull request", () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
"target",
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -262,4 +262,56 @@ describe("gha args parser", () => {
|
||||||
expect(args.squash).toEqual(true);
|
expect(args.squash).toEqual(true);
|
||||||
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("valid execution with multiple branches", () => {
|
||||||
|
spyGetInput({
|
||||||
|
"target-branch": "target,old",
|
||||||
|
"pull-request": "https://localhost/whatever/pulls/1"
|
||||||
|
});
|
||||||
|
|
||||||
|
const args: Args = parser.parse();
|
||||||
|
expect(args.dryRun).toEqual(false);
|
||||||
|
expect(args.auth).toEqual(undefined);
|
||||||
|
expect(args.gitUser).toEqual(undefined);
|
||||||
|
expect(args.gitEmail).toEqual(undefined);
|
||||||
|
expect(args.folder).toEqual(undefined);
|
||||||
|
expect(args.targetBranch).toEqual("target,old");
|
||||||
|
expect(args.pullRequest).toEqual("https://localhost/whatever/pulls/1");
|
||||||
|
expect(args.title).toEqual(undefined);
|
||||||
|
expect(args.body).toEqual(undefined);
|
||||||
|
expect(args.reviewers).toEqual([]);
|
||||||
|
expect(args.assignees).toEqual([]);
|
||||||
|
expect(args.inheritReviewers).toEqual(true);
|
||||||
|
expect(args.labels).toEqual([]);
|
||||||
|
expect(args.inheritLabels).toEqual(false);
|
||||||
|
expect(args.squash).toEqual(true);
|
||||||
|
expect(args.strategy).toEqual(undefined);
|
||||||
|
expect(args.strategyOption).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("invalid execution with empty target branch", () => {
|
||||||
|
spyGetInput({
|
||||||
|
"target-branch": " ",
|
||||||
|
"pull-request": "https://localhost/whatever/pulls/1"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid execution with missing mandatory target branch", () => {
|
||||||
|
spyGetInput({
|
||||||
|
"pull-request": "https://localhost/whatever/pulls/1"
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invalid execution with missin mandatory pull request", () => {
|
||||||
|
spyGetInput({
|
||||||
|
"target-branch": "target,old",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => parser.parse()).toThrowError("Missing option: pull request and target branches must be provided");
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -0,0 +1,422 @@
|
||||||
|
import { Args } from "@bp/service/args/args.types";
|
||||||
|
import { Configs } from "@bp/service/configs/configs.types";
|
||||||
|
import PullRequestConfigsParser from "@bp/service/configs/pullrequest/pr-configs-parser";
|
||||||
|
import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||||
|
import { GitClientType } from "@bp/service/git/git.types";
|
||||||
|
import { mockGitHubClient } from "../../../support/mock/git-client-mock-support";
|
||||||
|
import { resetProcessArgs } from "../../../support/utils";
|
||||||
|
import { MERGED_PR_FIXTURE, REPO, TARGET_OWNER, MULT_COMMITS_PR_FIXTURE } from "../../../support/mock/github-data";
|
||||||
|
import GitHubMapper from "@bp/service/git/github/github-mapper";
|
||||||
|
import GitHubClient from "@bp/service/git/github/github-client";
|
||||||
|
|
||||||
|
jest.spyOn(GitHubMapper.prototype, "mapPullRequest");
|
||||||
|
jest.spyOn(GitHubClient.prototype, "getPullRequest");
|
||||||
|
|
||||||
|
describe("github pull request config parser", () => {
|
||||||
|
|
||||||
|
const mergedPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MERGED_PR_FIXTURE.number}`;
|
||||||
|
const multipleCommitsPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MULT_COMMITS_PR_FIXTURE.number}`;
|
||||||
|
|
||||||
|
let configParser: PullRequestConfigsParser;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
GitClientFactory.reset();
|
||||||
|
GitClientFactory.getOrCreate(GitClientType.GITHUB, "whatever", "http://localhost/api/v3");
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// reset process.env variables
|
||||||
|
resetProcessArgs();
|
||||||
|
|
||||||
|
// mock octokit
|
||||||
|
mockGitHubClient("http://localhost/api/v3");
|
||||||
|
|
||||||
|
// create a fresh new instance every time
|
||||||
|
configParser = new PullRequestConfigsParser();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 2368, true);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v1-28f63db",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v2-28f63db",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v3-28f63db",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports ignore duplicates", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 2368, true);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v1-28f63db",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v2-28f63db",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v3-28f63db",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with custom branch name", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom-branch",
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 2368, true);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch-v1",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch-v2",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch-v3",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with multiple custom branch names", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom-branch1, custom-branch2, custom-branch3",
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 2368, true);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch1",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch2",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-branch3",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with incorrect number of bp branch names", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom-branch1, custom-branch2",
|
||||||
|
};
|
||||||
|
|
||||||
|
await expect(() => configParser.parseAndValidate(args)).rejects.toThrow("The number of backport branch names, if provided, must match the number of target branches or just one, provided 2 branch names instead");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports and multiple commits", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: multipleCommitsPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "GitHub",
|
||||||
|
gitEmail: "noreply@github.com",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: [],
|
||||||
|
inheritReviewers: true,
|
||||||
|
squash: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 8632, false);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), ["0404fb922ab75c3a8aecad5c97d9af388df04695", "11da4e38aa3e577ffde6d546f1c52e53b04d3151"]);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.git).toEqual({
|
||||||
|
user: "GitHub",
|
||||||
|
email: "noreply@github.com"
|
||||||
|
});
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v1-0404fb9-11da4e3",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/8632\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v2-0404fb9-11da4e3",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/8632\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v3-0404fb9-11da4e3",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/8632\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -5,7 +5,7 @@ import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||||
import { GitClientType } from "@bp/service/git/git.types";
|
import { GitClientType } from "@bp/service/git/git.types";
|
||||||
import { mockGitHubClient } from "../../../support/mock/git-client-mock-support";
|
import { mockGitHubClient } from "../../../support/mock/git-client-mock-support";
|
||||||
import { addProcessArgs, createTestFile, removeTestFile, resetProcessArgs } from "../../../support/utils";
|
import { addProcessArgs, createTestFile, removeTestFile, resetProcessArgs } from "../../../support/utils";
|
||||||
import { mergedPullRequestFixture, openPullRequestFixture, notMergedPullRequestFixture, repo, targetOwner, multipleCommitsPullRequestFixture } from "../../../support/mock/github-data";
|
import { MERGED_PR_FIXTURE, OPEN_PR_FIXTURE, NOT_MERGED_PR_FIXTURE, REPO, TARGET_OWNER, MULT_COMMITS_PR_FIXTURE } from "../../../support/mock/github-data";
|
||||||
import CLIArgsParser from "@bp/service/args/cli/cli-args-parser";
|
import CLIArgsParser from "@bp/service/args/cli/cli-args-parser";
|
||||||
import GitHubMapper from "@bp/service/git/github/github-mapper";
|
import GitHubMapper from "@bp/service/git/github/github-mapper";
|
||||||
import GitHubClient from "@bp/service/git/github/github-client";
|
import GitHubClient from "@bp/service/git/github/github-client";
|
||||||
|
@ -13,14 +13,14 @@ import GitHubClient from "@bp/service/git/github/github-client";
|
||||||
const GITHUB_MERGED_PR_SIMPLE_CONFIG_FILE_CONTENT_PATHNAME = "./github-pr-configs-parser-simple-pr-merged.json";
|
const GITHUB_MERGED_PR_SIMPLE_CONFIG_FILE_CONTENT_PATHNAME = "./github-pr-configs-parser-simple-pr-merged.json";
|
||||||
const GITHUB_MERGED_PR_SIMPLE_CONFIG_FILE_CONTENT = {
|
const GITHUB_MERGED_PR_SIMPLE_CONFIG_FILE_CONTENT = {
|
||||||
"targetBranch": "prod",
|
"targetBranch": "prod",
|
||||||
"pullRequest": `https://github.com/${targetOwner}/${repo}/pull/${mergedPullRequestFixture.number}`,
|
"pullRequest": `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MERGED_PR_FIXTURE.number}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const GITHUB_MERGED_PR_COMPLEX_CONFIG_FILE_CONTENT_PATHNAME = "./github-pr-configs-parser-complex-pr-merged.json";
|
const GITHUB_MERGED_PR_COMPLEX_CONFIG_FILE_CONTENT_PATHNAME = "./github-pr-configs-parser-complex-pr-merged.json";
|
||||||
const GITHUB_MERGED_PR_COMPLEX_CONFIG_FILE_CONTENT = {
|
const GITHUB_MERGED_PR_COMPLEX_CONFIG_FILE_CONTENT = {
|
||||||
"dryRun": false,
|
"dryRun": false,
|
||||||
"auth": "my-auth-token",
|
"auth": "my-auth-token",
|
||||||
"pullRequest": `https://github.com/${targetOwner}/${repo}/pull/${mergedPullRequestFixture.number}`,
|
"pullRequest": `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MERGED_PR_FIXTURE.number}`,
|
||||||
"targetBranch": "prod",
|
"targetBranch": "prod",
|
||||||
"gitUser": "Me",
|
"gitUser": "Me",
|
||||||
"gitEmail": "me@email.com",
|
"gitEmail": "me@email.com",
|
||||||
|
@ -39,10 +39,10 @@ jest.spyOn(GitHubClient.prototype, "getPullRequest");
|
||||||
|
|
||||||
describe("github pull request config parser", () => {
|
describe("github pull request config parser", () => {
|
||||||
|
|
||||||
const mergedPRUrl = `https://github.com/${targetOwner}/${repo}/pull/${mergedPullRequestFixture.number}`;
|
const mergedPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MERGED_PR_FIXTURE.number}`;
|
||||||
const openPRUrl = `https://github.com/${targetOwner}/${repo}/pull/${openPullRequestFixture.number}`;
|
const openPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${OPEN_PR_FIXTURE.number}`;
|
||||||
const notMergedPRUrl = `https://github.com/${targetOwner}/${repo}/pull/${notMergedPullRequestFixture.number}`;
|
const notMergedPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${NOT_MERGED_PR_FIXTURE.number}`;
|
||||||
const multipleCommitsPRUrl = `https://github.com/${targetOwner}/${repo}/pull/${multipleCommitsPullRequestFixture.number}`;
|
const multipleCommitsPRUrl = `https://github.com/${TARGET_OWNER}/${REPO}/pull/${MULT_COMMITS_PR_FIXTURE.number}`;
|
||||||
|
|
||||||
let argsParser: CLIArgsParser;
|
let argsParser: CLIArgsParser;
|
||||||
let configParser: PullRequestConfigsParser;
|
let configParser: PullRequestConfigsParser;
|
||||||
|
@ -100,7 +100,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "noreply@github.com"
|
email: "noreply@github.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -128,7 +127,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -160,7 +160,6 @@ describe("github pull request config parser", () => {
|
||||||
|
|
||||||
expect(configs.dryRun).toEqual(true);
|
expect(configs.dryRun).toEqual(true);
|
||||||
expect(configs.auth).toEqual("whatever");
|
expect(configs.auth).toEqual("whatever");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual("/tmp/test");
|
expect(configs.folder).toEqual("/tmp/test");
|
||||||
expect(configs.git).toEqual({
|
expect(configs.git).toEqual({
|
||||||
user: "GitHub",
|
user: "GitHub",
|
||||||
|
@ -190,7 +189,6 @@ describe("github pull request config parser", () => {
|
||||||
|
|
||||||
expect(configs.dryRun).toEqual(true);
|
expect(configs.dryRun).toEqual(true);
|
||||||
expect(configs.auth).toEqual("whatever");
|
expect(configs.auth).toEqual("whatever");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.git).toEqual({
|
expect(configs.git).toEqual({
|
||||||
user: "GitHub",
|
user: "GitHub",
|
||||||
email: "noreply@github.com"
|
email: "noreply@github.com"
|
||||||
|
@ -271,7 +269,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -300,7 +297,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "custom-branch",
|
head: "custom-branch",
|
||||||
|
@ -314,6 +312,48 @@ describe("github pull request config parser", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("override backport with empty bp branch name", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "prod",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: [],
|
||||||
|
inheritReviewers: true,
|
||||||
|
bpBranchName: " "
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubClient.prototype.getPullRequest).toBeCalledWith("owner", "reponame", 2368, true);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitHubMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-prod-28f63db",
|
||||||
|
base: "prod",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("override backport pr reviewers and assignees", async () => {
|
test("override backport pr reviewers and assignees", async () => {
|
||||||
const args: Args = {
|
const args: Args = {
|
||||||
dryRun: false,
|
dryRun: false,
|
||||||
|
@ -343,7 +383,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -372,7 +411,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -415,7 +455,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -444,7 +483,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -489,7 +529,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -518,7 +557,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -552,7 +592,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "noreply@github.com"
|
email: "noreply@github.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual(undefined);
|
expect(configs.auth).toEqual(undefined);
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -580,7 +619,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -614,7 +654,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("my-auth-token");
|
expect(configs.auth).toEqual("my-auth-token");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -643,7 +682,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
@ -684,7 +724,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "noreply@github.com"
|
email: "noreply@github.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 8632,
|
number: 8632,
|
||||||
|
@ -712,7 +751,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["0404fb922ab75c3a8aecad5c97d9af388df04695", "11da4e38aa3e577ffde6d546f1c52e53b04d3151"]
|
commits: ["0404fb922ab75c3a8aecad5c97d9af388df04695", "11da4e38aa3e577ffde6d546f1c52e53b04d3151"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-0404fb9-11da4e3",
|
head: "bp-prod-0404fb9-11da4e3",
|
||||||
|
@ -758,7 +798,6 @@ describe("github pull request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 2368,
|
number: 2368,
|
||||||
|
@ -787,7 +826,8 @@ describe("github pull request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "owner",
|
owner: "owner",
|
||||||
repo: "reponame",
|
repo: "reponame",
|
||||||
head: "bp-prod-28f63db",
|
head: "bp-prod-28f63db",
|
||||||
|
|
|
@ -0,0 +1,349 @@
|
||||||
|
import { Args } from "@bp/service/args/args.types";
|
||||||
|
import { Configs } from "@bp/service/configs/configs.types";
|
||||||
|
import PullRequestConfigsParser from "@bp/service/configs/pullrequest/pr-configs-parser";
|
||||||
|
import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||||
|
import { GitClientType } from "@bp/service/git/git.types";
|
||||||
|
import { getAxiosMocked } from "../../../support/mock/git-client-mock-support";
|
||||||
|
import { MERGED_SQUASHED_MR } from "../../../support/mock/gitlab-data";
|
||||||
|
import GitLabClient from "@bp/service/git/gitlab/gitlab-client";
|
||||||
|
import GitLabMapper from "@bp/service/git/gitlab/gitlab-mapper";
|
||||||
|
|
||||||
|
jest.spyOn(GitLabMapper.prototype, "mapPullRequest");
|
||||||
|
jest.spyOn(GitLabClient.prototype, "getPullRequest");
|
||||||
|
|
||||||
|
jest.mock("axios", () => {
|
||||||
|
return {
|
||||||
|
create: jest.fn(() => ({
|
||||||
|
get: getAxiosMocked,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("gitlab merge request config parser", () => {
|
||||||
|
|
||||||
|
const mergedPRUrl = `https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/${MERGED_SQUASHED_MR.iid}`;
|
||||||
|
|
||||||
|
let configParser: PullRequestConfigsParser;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
GitClientFactory.reset();
|
||||||
|
GitClientFactory.getOrCreate(GitClientType.GITLAB, "whatever", "my.gitlab.host.com");
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
configParser = new PullRequestConfigsParser();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledWith("superuser", "backporting-example", 1, true);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v1-ebb1eca",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v2-ebb1eca",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v3-ebb1eca",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports ignore duplicates", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3, v1",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledWith("superuser", "backporting-example", 1, true);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v1-ebb1eca",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v2-ebb1eca",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "bp-v3-ebb1eca",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with custom branch name", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom-branch"
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledWith("superuser", "backporting-example", 1, true);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom-branch-v1",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom-branch-v2",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom-branch-v3",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with multiple custom branch names", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom1, custom2, custom3"
|
||||||
|
};
|
||||||
|
|
||||||
|
const configs: Configs = await configParser.parseAndValidate(args);
|
||||||
|
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabClient.prototype.getPullRequest).toBeCalledWith("superuser", "backporting-example", 1, true);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledTimes(1);
|
||||||
|
expect(GitLabMapper.prototype.mapPullRequest).toBeCalledWith(expect.anything(), []);
|
||||||
|
|
||||||
|
expect(configs.dryRun).toEqual(false);
|
||||||
|
expect(configs.auth).toEqual("");
|
||||||
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
|
expect(configs.backportPullRequests.length).toEqual(3);
|
||||||
|
expect(configs.backportPullRequests).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom1",
|
||||||
|
base: "v1",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom2",
|
||||||
|
base: "v2",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
owner: "superuser",
|
||||||
|
repo: "backporting-example",
|
||||||
|
head: "custom3",
|
||||||
|
base: "v3",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body Prefix -New Body",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("multiple backports with incorrect number of bp branch names", async () => {
|
||||||
|
const args: Args = {
|
||||||
|
dryRun: false,
|
||||||
|
auth: "",
|
||||||
|
pullRequest: mergedPRUrl,
|
||||||
|
targetBranch: "v1, v2, v3",
|
||||||
|
gitUser: "Me",
|
||||||
|
gitEmail: "me@email.com",
|
||||||
|
title: "New Title",
|
||||||
|
body: "New Body",
|
||||||
|
bodyPrefix: "New Body Prefix -",
|
||||||
|
reviewers: [],
|
||||||
|
assignees: ["user3", "user4"],
|
||||||
|
inheritReviewers: false,
|
||||||
|
labels: [],
|
||||||
|
inheritLabels: false,
|
||||||
|
comments: [],
|
||||||
|
bpBranchName: "custom-branch1, custom-branch2, custom-branch2, custom-branch3, custom-branch4",
|
||||||
|
};
|
||||||
|
|
||||||
|
await expect(() => configParser.parseAndValidate(args)).rejects.toThrow("The number of backport branch names, if provided, must match the number of target branches or just one, provided 4 branch names instead");
|
||||||
|
});
|
||||||
|
});
|
|
@ -100,7 +100,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "noreply@gitlab.com"
|
email: "noreply@gitlab.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual(undefined);
|
expect(configs.auth).toEqual(undefined);
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -128,7 +127,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -166,7 +166,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
|
|
||||||
expect(configs.dryRun).toEqual(true);
|
expect(configs.dryRun).toEqual(true);
|
||||||
expect(configs.auth).toEqual("whatever");
|
expect(configs.auth).toEqual("whatever");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual("/tmp/test");
|
expect(configs.folder).toEqual("/tmp/test");
|
||||||
expect(configs.git).toEqual({
|
expect(configs.git).toEqual({
|
||||||
user: "Gitlab",
|
user: "Gitlab",
|
||||||
|
@ -196,7 +195,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
|
|
||||||
expect(configs.dryRun).toEqual(true);
|
expect(configs.dryRun).toEqual(true);
|
||||||
expect(configs.auth).toEqual("whatever");
|
expect(configs.auth).toEqual("whatever");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.git).toEqual({
|
expect(configs.git).toEqual({
|
||||||
user: "Gitlab",
|
user: "Gitlab",
|
||||||
email: "noreply@gitlab.com"
|
email: "noreply@gitlab.com"
|
||||||
|
@ -276,7 +274,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -304,7 +301,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -347,7 +345,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -375,7 +372,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -418,7 +416,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -446,7 +443,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -491,7 +489,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -519,7 +516,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -552,7 +550,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "noreply@gitlab.com"
|
email: "noreply@gitlab.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual(undefined);
|
expect(configs.auth).toEqual(undefined);
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -580,7 +577,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -613,7 +611,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("my-token");
|
expect(configs.auth).toEqual("my-token");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -641,7 +638,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
@ -678,7 +676,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
|
|
||||||
expect(configs.dryRun).toEqual(true);
|
expect(configs.dryRun).toEqual(true);
|
||||||
expect(configs.auth).toEqual("whatever");
|
expect(configs.auth).toEqual("whatever");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.git).toEqual({
|
expect(configs.git).toEqual({
|
||||||
user: "Gitlab",
|
user: "Gitlab",
|
||||||
email: "noreply@gitlab.com"
|
email: "noreply@gitlab.com"
|
||||||
|
@ -710,7 +707,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 2,
|
nCommits: 2,
|
||||||
commits: ["e4dd336a4a20f394df6665994df382fb1d193a11", "974519f65c9e0ed65277cd71026657a09fca05e7"]
|
commits: ["e4dd336a4a20f394df6665994df382fb1d193a11", "974519f65c9e0ed65277cd71026657a09fca05e7"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-e4dd336-974519f",
|
head: "bp-prod-e4dd336-974519f",
|
||||||
|
@ -756,7 +754,6 @@ describe("gitlab merge request config parser", () => {
|
||||||
email: "me@email.com"
|
email: "me@email.com"
|
||||||
});
|
});
|
||||||
expect(configs.auth).toEqual("");
|
expect(configs.auth).toEqual("");
|
||||||
expect(configs.targetBranch).toEqual("prod");
|
|
||||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||||
expect(configs.originalPullRequest).toEqual({
|
expect(configs.originalPullRequest).toEqual({
|
||||||
number: 1,
|
number: 1,
|
||||||
|
@ -784,7 +781,8 @@ describe("gitlab merge request config parser", () => {
|
||||||
nCommits: 1,
|
nCommits: 1,
|
||||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||||
});
|
});
|
||||||
expect(configs.backportPullRequest).toEqual({
|
expect(configs.backportPullRequests.length).toEqual(1);
|
||||||
|
expect(configs.backportPullRequests[0]).toEqual({
|
||||||
owner: "superuser",
|
owner: "superuser",
|
||||||
repo: "backporting-example",
|
repo: "backporting-example",
|
||||||
head: "bp-prod-ebb1eca",
|
head: "bp-prod-ebb1eca",
|
||||||
|
|
|
@ -114,4 +114,13 @@ describe("git cli service", () => {
|
||||||
const output = spawnSync("git", ["cherry", "-v"], { cwd }).stdout.toString();
|
const output = spawnSync("git", ["cherry", "-v"], { cwd }).stdout.toString();
|
||||||
expect(output.includes(expressionToTest)).toBe(false);
|
expect(output.includes(expressionToTest)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("git clone on already created repo", async () => {
|
||||||
|
await git.clone("remote", cwd, "tbranch");
|
||||||
|
|
||||||
|
// use rev-parse to double check the current branch is the expected one
|
||||||
|
const post = spawnSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd }).stdout.toString().trim();
|
||||||
|
expect(post).toEqual("tbranch");
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import GitClientFactory from "@bp/service/git/git-client-factory";
|
import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||||
import { GitPullRequest, GitClientType } from "@bp/service/git/git.types";
|
import { GitPullRequest, GitClientType } from "@bp/service/git/git.types";
|
||||||
import GitHubClient from "@bp/service/git/github/github-client";
|
import GitHubClient from "@bp/service/git/github/github-client";
|
||||||
import { mergedPullRequestFixture, repo, targetOwner } from "../../../support/mock/github-data";
|
import { MERGED_PR_FIXTURE, REPO, TARGET_OWNER } from "../../../support/mock/github-data";
|
||||||
import { mockGitHubClient } from "../../../support/mock/git-client-mock-support";
|
import { mockGitHubClient } from "../../../support/mock/git-client-mock-support";
|
||||||
|
|
||||||
describe("github service", () => {
|
describe("github service", () => {
|
||||||
|
@ -22,7 +22,7 @@ describe("github service", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("get pull request: success", async () => {
|
test("get pull request: success", async () => {
|
||||||
const res: GitPullRequest = await gitClient.getPullRequest(targetOwner, repo, mergedPullRequestFixture.number);
|
const res: GitPullRequest = await gitClient.getPullRequest(TARGET_OWNER, REPO, MERGED_PR_FIXTURE.number);
|
||||||
expect(res.sourceRepo).toEqual({
|
expect(res.sourceRepo).toEqual({
|
||||||
owner: "fork",
|
owner: "fork",
|
||||||
project: "reponame",
|
project: "reponame",
|
||||||
|
|
|
@ -6,7 +6,7 @@ import CLIArgsParser from "@bp/service/args/cli/cli-args-parser";
|
||||||
import { addProcessArgs, createTestFile, removeTestFile, resetProcessArgs } from "../../support/utils";
|
import { addProcessArgs, createTestFile, removeTestFile, resetProcessArgs } from "../../support/utils";
|
||||||
import { mockGitHubClient } from "../../support/mock/git-client-mock-support";
|
import { mockGitHubClient } from "../../support/mock/git-client-mock-support";
|
||||||
import GitClientFactory from "@bp/service/git/git-client-factory";
|
import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||||
import { GitClientType } from "@bp/service/git/git.types";
|
import { BackportPullRequest, GitClientType } from "@bp/service/git/git.types";
|
||||||
|
|
||||||
const GITHUB_MERGED_PR_W_OVERRIDES_CONFIG_FILE_CONTENT_PATHNAME = "./cli-github-runner-pr-merged-with-overrides.json";
|
const GITHUB_MERGED_PR_W_OVERRIDES_CONFIG_FILE_CONTENT_PATHNAME = "./cli-github-runner-pr-merged-with-overrides.json";
|
||||||
const GITHUB_MERGED_PR_W_OVERRIDES_CONFIG_FILE_CONTENT = {
|
const GITHUB_MERGED_PR_W_OVERRIDES_CONFIG_FILE_CONTENT = {
|
||||||
|
@ -236,6 +236,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("same owner", async () => {
|
test("same owner", async () => {
|
||||||
|
@ -281,6 +282,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("closed and not merged pull request", async () => {
|
test("closed and not merged pull request", async () => {
|
||||||
|
@ -338,6 +340,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("override backporting pr data", async () => {
|
test("override backporting pr data", async () => {
|
||||||
|
@ -396,6 +399,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set empty reviewers", async () => {
|
test("set empty reviewers", async () => {
|
||||||
|
@ -453,6 +457,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set custom labels with inheritance", async () => {
|
test("set custom labels with inheritance", async () => {
|
||||||
|
@ -502,6 +507,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set custom labels without inheritance", async () => {
|
test("set custom labels without inheritance", async () => {
|
||||||
|
@ -550,6 +556,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("using config file with overrides", async () => {
|
test("using config file with overrides", async () => {
|
||||||
|
@ -594,6 +601,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// to check: https://github.com/kiegroup/git-backporting/issues/52
|
// to check: https://github.com/kiegroup/git-backporting/issues/52
|
||||||
|
@ -641,6 +649,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("multiple commits pr", async () => {
|
test("multiple commits pr", async () => {
|
||||||
|
@ -688,6 +697,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("too long bp branch name", async () => {
|
test("too long bp branch name", async () => {
|
||||||
|
@ -741,6 +751,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("multiple commits pr with different strategy", async () => {
|
test("multiple commits pr with different strategy", async () => {
|
||||||
|
@ -792,6 +803,7 @@ describe("cli runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("additional pr comments", async () => {
|
test("additional pr comments", async () => {
|
||||||
|
@ -841,5 +853,255 @@ describe("cli runner", () => {
|
||||||
comments: ["first comment", "second comment"],
|
comments: ["first comment", "second comment"],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with multiple target branches", async () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
"v1, v2, v3",
|
||||||
|
"-pr",
|
||||||
|
"https://github.com/owner/reponame/pull/2368",
|
||||||
|
"-f",
|
||||||
|
"/tmp/folder"
|
||||||
|
]);
|
||||||
|
|
||||||
|
await runner.execute();
|
||||||
|
|
||||||
|
const cwd = "/tmp/folder";
|
||||||
|
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v1");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v2");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v1-28f63db");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v2-28f63db");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v3-28f63db");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v1-28f63db");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v2-28f63db");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v3-28f63db");
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(3);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v1-28f63db",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v2-28f63db",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v3-28f63db",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with multiple target branches and multiple bp names", async () => {
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
"v1, v2, v3",
|
||||||
|
"-pr",
|
||||||
|
"https://github.com/owner/reponame/pull/2368",
|
||||||
|
"-f",
|
||||||
|
"/tmp/folder",
|
||||||
|
"--bp-branch-name",
|
||||||
|
"custom1, custom1, custom2, custom3",
|
||||||
|
]);
|
||||||
|
|
||||||
|
await runner.execute();
|
||||||
|
|
||||||
|
const cwd = "/tmp/folder";
|
||||||
|
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v1");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v2");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom1");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom2");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom1");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom2");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom3");
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(3);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom1",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom2",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom3",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with multiple target branches and one failure", async () => {
|
||||||
|
jest.spyOn(GitHubClient.prototype, "createPullRequest").mockImplementation((_backport: BackportPullRequest) => {
|
||||||
|
|
||||||
|
throw new Error("Mocked error");
|
||||||
|
});
|
||||||
|
|
||||||
|
addProcessArgs([
|
||||||
|
"-tb",
|
||||||
|
"v1, v2, v3",
|
||||||
|
"-pr",
|
||||||
|
"https://github.com/owner/reponame/pull/2368",
|
||||||
|
"-f",
|
||||||
|
"/tmp/folder",
|
||||||
|
"--bp-branch-name",
|
||||||
|
"custom-failure-head",
|
||||||
|
]);
|
||||||
|
|
||||||
|
await expect(() => runner.execute()).rejects.toThrowError("Failure occurred during one of the backports: [Error: Mocked error ; Error: Mocked error ; Error: Mocked error]");
|
||||||
|
|
||||||
|
const cwd = "/tmp/folder";
|
||||||
|
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v1");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v2");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-failure-head-v1");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-failure-head-v2");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-failure-head-v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-failure-head-v1");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-failure-head-v2");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-failure-head-v3");
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(3);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-failure-head-v1",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-failure-head-v2",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-failure-head-v3",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toThrowError();
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -128,6 +128,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("closed and not merged pull request", async () => {
|
test("closed and not merged pull request", async () => {
|
||||||
|
@ -181,6 +182,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("override backporting pr data", async () => {
|
test("override backporting pr data", async () => {
|
||||||
|
@ -231,6 +233,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set empty reviewers", async () => {
|
test("set empty reviewers", async () => {
|
||||||
|
@ -282,6 +285,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set custom labels with inheritance", async () => {
|
test("set custom labels with inheritance", async () => {
|
||||||
|
@ -328,6 +332,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("set custom labels without inheritance", async () => {
|
test("set custom labels without inheritance", async () => {
|
||||||
|
@ -374,6 +379,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("using config file with overrides", async () => {
|
test("using config file with overrides", async () => {
|
||||||
|
@ -417,6 +423,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// to check: https://github.com/kiegroup/git-backporting/issues/52
|
// to check: https://github.com/kiegroup/git-backporting/issues/52
|
||||||
|
@ -462,6 +469,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("multiple commits pr", async () => {
|
test("multiple commits pr", async () => {
|
||||||
|
@ -507,6 +515,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("using github api url and different strategy", async () => {
|
test("using github api url and different strategy", async () => {
|
||||||
|
@ -553,6 +562,7 @@ describe("gha runner", () => {
|
||||||
comments: [],
|
comments: [],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("additional pr comments", async () => {
|
test("additional pr comments", async () => {
|
||||||
|
@ -598,5 +608,161 @@ describe("gha runner", () => {
|
||||||
comments: ["first comment", "second comment"],
|
comments: ["first comment", "second comment"],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with multiple target branches", async () => {
|
||||||
|
spyGetInput({
|
||||||
|
"target-branch": "v1, v2, v3",
|
||||||
|
"pull-request": "https://github.com/owner/reponame/pull/2368",
|
||||||
|
"folder": "/tmp/folder",
|
||||||
|
});
|
||||||
|
|
||||||
|
await runner.execute();
|
||||||
|
|
||||||
|
const cwd = "/tmp/folder";
|
||||||
|
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v1");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v2");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v1-28f63db");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v2-28f63db");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-v3-28f63db");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v1-28f63db");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v2-28f63db");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-v3-28f63db");
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(3);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v1-28f63db",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v2-28f63db",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "bp-v3-28f63db",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with multiple target branches and single custom bp branch", async () => {
|
||||||
|
spyGetInput({
|
||||||
|
"target-branch": "v1, v2, v3",
|
||||||
|
"pull-request": "https://github.com/owner/reponame/pull/2368",
|
||||||
|
"folder": "/tmp/folder",
|
||||||
|
"bp-branch-name": "custom"
|
||||||
|
});
|
||||||
|
|
||||||
|
await runner.execute();
|
||||||
|
|
||||||
|
const cwd = "/tmp/folder";
|
||||||
|
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||||
|
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v1");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v2");
|
||||||
|
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-v1");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-v2");
|
||||||
|
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "custom-v3");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||||
|
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledTimes(3);
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-v1");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-v2");
|
||||||
|
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "custom-v3");
|
||||||
|
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(3);
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-v1",
|
||||||
|
base: "v1",
|
||||||
|
title: "[v1] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-v2",
|
||||||
|
base: "v2",
|
||||||
|
title: "[v2] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||||
|
owner: "owner",
|
||||||
|
repo: "reponame",
|
||||||
|
head: "custom-v3",
|
||||||
|
base: "v3",
|
||||||
|
title: "[v3] PR Title",
|
||||||
|
body: "**Backport:** https://github.com/owner/reponame/pull/2368\r\n\r\nPlease review and merge",
|
||||||
|
reviewers: ["gh-user", "that-s-a-user"],
|
||||||
|
assignees: [],
|
||||||
|
labels: [],
|
||||||
|
comments: [],
|
||||||
|
});
|
||||||
|
expect(GitHubClient.prototype.createPullRequest).toReturnTimes(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,8 +1,12 @@
|
||||||
import LoggerServiceFactory from "@bp/service/logger/logger-service-factory";
|
import LoggerServiceFactory from "@bp/service/logger/logger-service-factory";
|
||||||
import { Moctokit } from "@kie/mock-github";
|
import { Moctokit } from "@kie/mock-github";
|
||||||
import { targetOwner, repo, mergedPullRequestFixture, openPullRequestFixture, notMergedPullRequestFixture, notFoundPullRequestNumber, multipleCommitsPullRequestFixture, multipleCommitsPullRequestCommits } from "./github-data";
|
import { TARGET_OWNER, REPO, MERGED_PR_FIXTURE, OPEN_PR_FIXTURE, NOT_MERGED_PR_FIXTURE, NOT_FOUND_PR_NUMBER, MULT_COMMITS_PR_FIXTURE, MULT_COMMITS_PR_COMMITS, NEW_PR_URL, NEW_PR_NUMBER } from "./github-data";
|
||||||
import { CLOSED_NOT_MERGED_MR, MERGED_SQUASHED_MR, OPEN_MR, OPEN_PR_COMMITS, PROJECT_EXAMPLE, SUPERUSER} from "./gitlab-data";
|
import { CLOSED_NOT_MERGED_MR, MERGED_SQUASHED_MR, OPEN_MR, OPEN_PR_COMMITS, PROJECT_EXAMPLE, SUPERUSER} from "./gitlab-data";
|
||||||
|
|
||||||
|
// high number, for each test we are not expecting
|
||||||
|
// to send more than 3 reqs per api endpoint
|
||||||
|
const REPEAT = 20;
|
||||||
|
|
||||||
const logger = LoggerServiceFactory.getLogger();
|
const logger = LoggerServiceFactory.getLogger();
|
||||||
|
|
||||||
// AXIOS
|
// AXIOS
|
||||||
|
@ -94,76 +98,82 @@ export const mockGitHubClient = (apiUrl = "https://api.github.com"): Moctokit =>
|
||||||
// valid requests
|
// valid requests
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.get({
|
.get({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: mergedPullRequestFixture.number
|
pull_number: MERGED_PR_FIXTURE.number
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: mergedPullRequestFixture
|
data: MERGED_PR_FIXTURE
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.get({
|
.get({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: multipleCommitsPullRequestFixture.number
|
pull_number: MULT_COMMITS_PR_FIXTURE.number
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: multipleCommitsPullRequestFixture
|
data: MULT_COMMITS_PR_FIXTURE
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.get({
|
.get({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: openPullRequestFixture.number
|
pull_number: OPEN_PR_FIXTURE.number
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: openPullRequestFixture
|
data: OPEN_PR_FIXTURE
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.get({
|
.get({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: notMergedPullRequestFixture.number
|
pull_number: NOT_MERGED_PR_FIXTURE.number
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: notMergedPullRequestFixture
|
data: NOT_MERGED_PR_FIXTURE
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.listCommits({
|
.listCommits({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: multipleCommitsPullRequestFixture.number
|
pull_number: MULT_COMMITS_PR_FIXTURE.number
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: multipleCommitsPullRequestCommits
|
data: MULT_COMMITS_PR_COMMITS
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.create()
|
.create()
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 201,
|
status: 201,
|
||||||
data: mergedPullRequestFixture
|
data: {
|
||||||
|
number: NEW_PR_NUMBER,
|
||||||
|
html_url: NEW_PR_URL,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.requestReviewers()
|
.requestReviewers()
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 201,
|
status: 201,
|
||||||
data: mergedPullRequestFixture
|
data: MERGED_PR_FIXTURE
|
||||||
});
|
});
|
||||||
|
|
||||||
mock.rest.issues
|
mock.rest.issues
|
||||||
.addAssignees()
|
.addAssignees()
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 201,
|
status: 201,
|
||||||
data: {}
|
data: {}
|
||||||
});
|
});
|
||||||
|
@ -171,6 +181,7 @@ export const mockGitHubClient = (apiUrl = "https://api.github.com"): Moctokit =>
|
||||||
mock.rest.issues
|
mock.rest.issues
|
||||||
.addLabels()
|
.addLabels()
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 200,
|
status: 200,
|
||||||
data: {}
|
data: {}
|
||||||
});
|
});
|
||||||
|
@ -178,6 +189,7 @@ export const mockGitHubClient = (apiUrl = "https://api.github.com"): Moctokit =>
|
||||||
mock.rest.issues
|
mock.rest.issues
|
||||||
.createComment()
|
.createComment()
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 201,
|
status: 201,
|
||||||
data: {}
|
data: {}
|
||||||
});
|
});
|
||||||
|
@ -185,11 +197,12 @@ export const mockGitHubClient = (apiUrl = "https://api.github.com"): Moctokit =>
|
||||||
// invalid requests
|
// invalid requests
|
||||||
mock.rest.pulls
|
mock.rest.pulls
|
||||||
.get({
|
.get({
|
||||||
owner: targetOwner,
|
owner: TARGET_OWNER,
|
||||||
repo: repo,
|
repo: REPO,
|
||||||
pull_number: notFoundPullRequestNumber
|
pull_number: NOT_FOUND_PR_NUMBER
|
||||||
})
|
})
|
||||||
.reply({
|
.reply({
|
||||||
|
repeat: REPEAT,
|
||||||
status: 404,
|
status: 404,
|
||||||
data: {
|
data: {
|
||||||
message: "Not found"
|
message: "Not found"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
export const targetOwner = "owner";
|
export const TARGET_OWNER = "owner";
|
||||||
export const sourceOwner = "fork";
|
export const SOURCE_OWNER = "fork";
|
||||||
export const repo = "reponame";
|
export const REPO = "reponame";
|
||||||
export const notFoundPullRequestNumber = 1;
|
export const NOT_FOUND_PR_NUMBER = 1;
|
||||||
|
export const NEW_PR_URL = "new_pr_url";
|
||||||
|
export const NEW_PR_NUMBER = 9999;
|
||||||
|
|
||||||
export const mergedPullRequestFixture = {
|
export const MERGED_PR_FIXTURE = {
|
||||||
"url": "https://api.github.com/repos/owner/reponame/pulls/2368",
|
"url": "https://api.github.com/repos/owner/reponame/pulls/2368",
|
||||||
"id": 1137188271,
|
"id": 1137188271,
|
||||||
"node_id": "PR_kwDOABTq6s5DyB2v",
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
@ -474,7 +476,7 @@ export const mergedPullRequestFixture = {
|
||||||
"changed_files": 2
|
"changed_files": 2
|
||||||
};
|
};
|
||||||
|
|
||||||
export const openPullRequestFixture = {
|
export const OPEN_PR_FIXTURE = {
|
||||||
"url": "https://api.github.com/repos/owner/reponame/pulls/4444",
|
"url": "https://api.github.com/repos/owner/reponame/pulls/4444",
|
||||||
"id": 1137188271,
|
"id": 1137188271,
|
||||||
"node_id": "PR_kwDOABTq6s5DyB2v",
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
@ -898,7 +900,7 @@ export const openPullRequestFixture = {
|
||||||
"changed_files": 2
|
"changed_files": 2
|
||||||
};
|
};
|
||||||
|
|
||||||
export const notMergedPullRequestFixture = {
|
export const NOT_MERGED_PR_FIXTURE = {
|
||||||
"url": "https://api.github.com/repos/owner/reponame/pulls/6666",
|
"url": "https://api.github.com/repos/owner/reponame/pulls/6666",
|
||||||
"id": 1137188271,
|
"id": 1137188271,
|
||||||
"node_id": "PR_kwDOABTq6s5DyB2v",
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
@ -1341,7 +1343,7 @@ export const notMergedPullRequestFixture = {
|
||||||
"changed_files": 2
|
"changed_files": 2
|
||||||
};
|
};
|
||||||
|
|
||||||
export const multipleCommitsPullRequestFixture = {
|
export const MULT_COMMITS_PR_FIXTURE = {
|
||||||
"url": "https://api.github.com/repos/owner/reponame/pulls/8632",
|
"url": "https://api.github.com/repos/owner/reponame/pulls/8632",
|
||||||
"id": 1137188271,
|
"id": 1137188271,
|
||||||
"node_id": "PR_kwDOABTq6s5DyB2v",
|
"node_id": "PR_kwDOABTq6s5DyB2v",
|
||||||
|
@ -1804,7 +1806,7 @@ export const multipleCommitsPullRequestFixture = {
|
||||||
"changed_files": 2
|
"changed_files": 2
|
||||||
};
|
};
|
||||||
|
|
||||||
export const multipleCommitsPullRequestCommits = [
|
export const MULT_COMMITS_PR_COMMITS = [
|
||||||
{
|
{
|
||||||
"sha": "0404fb922ab75c3a8aecad5c97d9af388df04695",
|
"sha": "0404fb922ab75c3a8aecad5c97d9af388df04695",
|
||||||
"node_id": "C_kwDOImgs99oAKDA0MDRmYjkyMmFiNzVjM2E4YWVjYWQ1Yzk3ZDlhZjM4OGRmMDQ2OTU",
|
"node_id": "C_kwDOImgs99oAKDA0MDRmYjkyMmFiNzVjM2E4YWVjYWQ1Yzk3ZDlhZjM4OGRmMDQ2OTU",
|
||||||
|
|
Loading…
Add table
Reference in a new issue