mirror of
https://code.forgejo.org/actions/git-backporting.git
synced 2025-02-22 10:35:43 -05:00
Merge pull request #71 from lampajr/issue-70_post_comments
feat(issue-70): additional pr comments
This commit is contained in:
commit
a402fa4525
26 changed files with 644 additions and 308 deletions
|
@ -113,6 +113,7 @@ This tool comes with some inputs that allow users to override the default behavi
|
|||
| No squash | --no-squash | N | If provided the backporting will try to backport all pull request commits without squashing | false |
|
||||
| Strategy | --strategy | N | Cherry pick merging strategy, see [git-merge](https://git-scm.com/docs/git-merge#_merge_strategies) doc for all possible values | "recursive" |
|
||||
| Strategy Option | --strategy-option | N | Cherry pick merging strategy option, see [git-merge](https://git-scm.com/docs/git-merge#_merge_strategies) doc for all possible values | "theirs" |
|
||||
| Additional comments | --comments | N | Semicolon separated list of additional comments to be posted to the backported pull request | [] |
|
||||
| Dry Run | -d, --dry-run | N | If enabled the tool does not push nor create anything remotely, use this to skip PR creation | false |
|
||||
|
||||
> **NOTE**: `pull request` and `target branch` are *mandatory*, they must be provided as CLI options or as part of the configuration file (if used).
|
||||
|
|
|
@ -67,6 +67,9 @@ inputs:
|
|||
description: "Cherry-pick merge strategy option"
|
||||
required: false
|
||||
default: "theirs"
|
||||
comments:
|
||||
description: "Semicolon separated list of additional comments to be posted to the backported pull request"
|
||||
required: false
|
||||
|
||||
runs:
|
||||
using: node16
|
||||
|
|
78
dist/cli/index.js
vendored
78
dist/cli/index.js
vendored
|
@ -63,6 +63,7 @@ class ArgsParser {
|
|||
squash: this.getOrDefault(args.squash, true),
|
||||
strategy: this.getOrDefault(args.strategy),
|
||||
strategyOption: this.getOrDefault(args.strategyOption),
|
||||
comments: this.getOrDefault(args.comments)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +101,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getAsBooleanOrDefault = exports.getAsCommaSeparatedList = exports.getAsCleanedCommaSeparatedList = exports.getOrUndefined = exports.readConfigFile = exports.parseArgs = void 0;
|
||||
exports.getAsBooleanOrDefault = exports.getAsSemicolonSeparatedList = exports.getAsCommaSeparatedList = exports.getAsCleanedCommaSeparatedList = exports.getOrUndefined = exports.readConfigFile = exports.parseArgs = void 0;
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
/**
|
||||
* Parse the input configuation string as json object and
|
||||
|
@ -145,6 +146,12 @@ function getAsCommaSeparatedList(value) {
|
|||
return trimmed !== "" ? trimmed.split(",").map(v => v.trim()) : undefined;
|
||||
}
|
||||
exports.getAsCommaSeparatedList = getAsCommaSeparatedList;
|
||||
function getAsSemicolonSeparatedList(value) {
|
||||
// trim the value
|
||||
const trimmed = value.trim();
|
||||
return trimmed !== "" ? trimmed.split(";").map(v => v.trim()) : undefined;
|
||||
}
|
||||
exports.getAsSemicolonSeparatedList = getAsSemicolonSeparatedList;
|
||||
function getAsBooleanOrDefault(value) {
|
||||
const trimmed = value.trim();
|
||||
return trimmed !== "" ? trimmed.toLowerCase() === "true" : undefined;
|
||||
|
@ -191,6 +198,7 @@ class CLIArgsParser extends args_parser_1.default {
|
|||
.option("--no-squash", "if provided the tool will backport all commits as part of the pull request")
|
||||
.option("--strategy <strategy>", "cherry-pick merge strategy, default to 'recursive'", undefined)
|
||||
.option("--strategy-option <strategy-option>", "cherry-pick merge strategy option, default to 'theirs'")
|
||||
.option("--comments <comments>", "semicolon separated list of additional comments to be posted to the backported pull request", args_utils_1.getAsSemicolonSeparatedList)
|
||||
.option("-cf, --config-file <config-file>", "configuration file containing all valid options, the json must match Args interface");
|
||||
}
|
||||
readArgs() {
|
||||
|
@ -223,6 +231,7 @@ class CLIArgsParser extends args_parser_1.default {
|
|||
squash: opts.squash,
|
||||
strategy: opts.strategy,
|
||||
strategyOption: opts.strategyOption,
|
||||
comments: opts.comments,
|
||||
};
|
||||
}
|
||||
return args;
|
||||
|
@ -336,16 +345,27 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
|||
if (args.inheritLabels) {
|
||||
labels.push(...originalPullRequest.labels);
|
||||
}
|
||||
let backportBranch = args.bpBranchName;
|
||||
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
|
||||
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
return {
|
||||
author: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||
owner: originalPullRequest.targetRepo.owner,
|
||||
repo: originalPullRequest.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: args.targetBranch,
|
||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
||||
body: `${bodyPrefix}${body}`,
|
||||
reviewers: [...new Set(reviewers)],
|
||||
assignees: [...new Set(args.assignees)],
|
||||
labels: [...new Set(labels)],
|
||||
targetRepo: originalPullRequest.targetRepo,
|
||||
sourceRepo: originalPullRequest.targetRepo,
|
||||
branchName: args.bpBranchName,
|
||||
comments: args.comments ?? [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -710,6 +730,16 @@ class GitHubClient {
|
|||
assignees: backport.assignees,
|
||||
}).catch(error => this.logger.error(`Error setting assignees: ${error}`)));
|
||||
}
|
||||
if (backport.comments.length > 0) {
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(this.octokit.issues.createComment({
|
||||
owner: backport.owner,
|
||||
repo: backport.repo,
|
||||
issue_number: data.number,
|
||||
body: c,
|
||||
}).catch(error => this.logger.error(`Error posting comment: ${error}`)));
|
||||
});
|
||||
}
|
||||
await Promise.all(promises);
|
||||
return data.html_url;
|
||||
}
|
||||
|
@ -906,6 +936,15 @@ class GitLabClient {
|
|||
labels: backport.labels.join(","),
|
||||
}).catch(error => this.logger.warn("Failure trying to update labels. " + error)));
|
||||
}
|
||||
// comments
|
||||
if (backport.comments.length > 0) {
|
||||
this.logger.info("Posting comments: " + backport.comments);
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(this.client.post(`/projects/${projectId}/merge_requests/${mr.iid}/notes`, {
|
||||
body: c,
|
||||
}).catch(error => this.logger.warn("Failure trying to post comment. " + error)));
|
||||
});
|
||||
}
|
||||
// reviewers
|
||||
const reviewerIds = await Promise.all(backport.reviewers.map(async (r) => {
|
||||
this.logger.debug("Retrieving user: " + r);
|
||||
|
@ -1211,17 +1250,7 @@ class Runner {
|
|||
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
|
||||
// 5. create new branch from target one and checkout
|
||||
this.logger.debug("Creating local branch..");
|
||||
let backportBranch = backportPR.branchName;
|
||||
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
|
||||
const concatenatedCommits = originalPR.commits.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${configs.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
await git.createLocalBranch(configs.folder, backportBranch);
|
||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
configs.originalPullRequest.state === "open") {
|
||||
|
@ -1234,27 +1263,16 @@ class Runner {
|
|||
for (const sha of originalPR.commits) {
|
||||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||
}
|
||||
const backport = {
|
||||
owner: originalPR.targetRepo.owner,
|
||||
repo: originalPR.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: configs.targetBranch,
|
||||
title: backportPR.title,
|
||||
body: backportPR.body,
|
||||
reviewers: backportPR.reviewers,
|
||||
assignees: backportPR.assignees,
|
||||
labels: backportPR.labels,
|
||||
};
|
||||
if (!configs.dryRun) {
|
||||
// 8. push the new branch to origin
|
||||
await git.push(configs.folder, backportBranch);
|
||||
await git.push(configs.folder, backportPR.head);
|
||||
// 9. create pull request new branch -> target branch (using octokit)
|
||||
const prUrl = await gitApi.createPullRequest(backport);
|
||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
||||
this.logger.info(`Pull request created: ${prUrl}`);
|
||||
}
|
||||
else {
|
||||
this.logger.warn("Pull request creation and remote push skipped");
|
||||
this.logger.info(`${JSON.stringify(backport, null, 2)}`);
|
||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
77
dist/gha/index.js
vendored
77
dist/gha/index.js
vendored
|
@ -63,6 +63,7 @@ class ArgsParser {
|
|||
squash: this.getOrDefault(args.squash, true),
|
||||
strategy: this.getOrDefault(args.strategy),
|
||||
strategyOption: this.getOrDefault(args.strategyOption),
|
||||
comments: this.getOrDefault(args.comments)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +101,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getAsBooleanOrDefault = exports.getAsCommaSeparatedList = exports.getAsCleanedCommaSeparatedList = exports.getOrUndefined = exports.readConfigFile = exports.parseArgs = void 0;
|
||||
exports.getAsBooleanOrDefault = exports.getAsSemicolonSeparatedList = exports.getAsCommaSeparatedList = exports.getAsCleanedCommaSeparatedList = exports.getOrUndefined = exports.readConfigFile = exports.parseArgs = void 0;
|
||||
const fs = __importStar(__nccwpck_require__(7147));
|
||||
/**
|
||||
* Parse the input configuation string as json object and
|
||||
|
@ -145,6 +146,12 @@ function getAsCommaSeparatedList(value) {
|
|||
return trimmed !== "" ? trimmed.split(",").map(v => v.trim()) : undefined;
|
||||
}
|
||||
exports.getAsCommaSeparatedList = getAsCommaSeparatedList;
|
||||
function getAsSemicolonSeparatedList(value) {
|
||||
// trim the value
|
||||
const trimmed = value.trim();
|
||||
return trimmed !== "" ? trimmed.split(";").map(v => v.trim()) : undefined;
|
||||
}
|
||||
exports.getAsSemicolonSeparatedList = getAsSemicolonSeparatedList;
|
||||
function getAsBooleanOrDefault(value) {
|
||||
const trimmed = value.trim();
|
||||
return trimmed !== "" ? trimmed.toLowerCase() === "true" : undefined;
|
||||
|
@ -194,6 +201,7 @@ class GHAArgsParser extends args_parser_1.default {
|
|||
squash: !(0, args_utils_1.getAsBooleanOrDefault)((0, core_1.getInput)("no-squash")),
|
||||
strategy: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("strategy")),
|
||||
strategyOption: (0, args_utils_1.getOrUndefined)((0, core_1.getInput)("strategy-option")),
|
||||
comments: (0, args_utils_1.getAsSemicolonSeparatedList)((0, core_1.getInput)("comments")),
|
||||
};
|
||||
}
|
||||
return args;
|
||||
|
@ -307,16 +315,27 @@ class PullRequestConfigsParser extends configs_parser_1.default {
|
|||
if (args.inheritLabels) {
|
||||
labels.push(...originalPullRequest.labels);
|
||||
}
|
||||
let backportBranch = args.bpBranchName;
|
||||
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
|
||||
const concatenatedCommits = originalPullRequest.commits.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
return {
|
||||
author: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||
owner: originalPullRequest.targetRepo.owner,
|
||||
repo: originalPullRequest.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: args.targetBranch,
|
||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
||||
body: `${bodyPrefix}${body}`,
|
||||
reviewers: [...new Set(reviewers)],
|
||||
assignees: [...new Set(args.assignees)],
|
||||
labels: [...new Set(labels)],
|
||||
targetRepo: originalPullRequest.targetRepo,
|
||||
sourceRepo: originalPullRequest.targetRepo,
|
||||
branchName: args.bpBranchName,
|
||||
comments: args.comments ?? [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -681,6 +700,16 @@ class GitHubClient {
|
|||
assignees: backport.assignees,
|
||||
}).catch(error => this.logger.error(`Error setting assignees: ${error}`)));
|
||||
}
|
||||
if (backport.comments.length > 0) {
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(this.octokit.issues.createComment({
|
||||
owner: backport.owner,
|
||||
repo: backport.repo,
|
||||
issue_number: data.number,
|
||||
body: c,
|
||||
}).catch(error => this.logger.error(`Error posting comment: ${error}`)));
|
||||
});
|
||||
}
|
||||
await Promise.all(promises);
|
||||
return data.html_url;
|
||||
}
|
||||
|
@ -877,6 +906,15 @@ class GitLabClient {
|
|||
labels: backport.labels.join(","),
|
||||
}).catch(error => this.logger.warn("Failure trying to update labels. " + error)));
|
||||
}
|
||||
// comments
|
||||
if (backport.comments.length > 0) {
|
||||
this.logger.info("Posting comments: " + backport.comments);
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(this.client.post(`/projects/${projectId}/merge_requests/${mr.iid}/notes`, {
|
||||
body: c,
|
||||
}).catch(error => this.logger.warn("Failure trying to post comment. " + error)));
|
||||
});
|
||||
}
|
||||
// reviewers
|
||||
const reviewerIds = await Promise.all(backport.reviewers.map(async (r) => {
|
||||
this.logger.debug("Retrieving user: " + r);
|
||||
|
@ -1182,17 +1220,7 @@ class Runner {
|
|||
await git.clone(configs.originalPullRequest.targetRepo.cloneUrl, configs.folder, configs.targetBranch);
|
||||
// 5. create new branch from target one and checkout
|
||||
this.logger.debug("Creating local branch..");
|
||||
let backportBranch = backportPR.branchName;
|
||||
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
|
||||
const concatenatedCommits = originalPR.commits.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${configs.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
await git.createLocalBranch(configs.folder, backportBranch);
|
||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
configs.originalPullRequest.state === "open") {
|
||||
|
@ -1205,27 +1233,16 @@ class Runner {
|
|||
for (const sha of originalPR.commits) {
|
||||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||
}
|
||||
const backport = {
|
||||
owner: originalPR.targetRepo.owner,
|
||||
repo: originalPR.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: configs.targetBranch,
|
||||
title: backportPR.title,
|
||||
body: backportPR.body,
|
||||
reviewers: backportPR.reviewers,
|
||||
assignees: backportPR.assignees,
|
||||
labels: backportPR.labels,
|
||||
};
|
||||
if (!configs.dryRun) {
|
||||
// 8. push the new branch to origin
|
||||
await git.push(configs.folder, backportBranch);
|
||||
await git.push(configs.folder, backportPR.head);
|
||||
// 9. create pull request new branch -> target branch (using octokit)
|
||||
const prUrl = await gitApi.createPullRequest(backport);
|
||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
||||
this.logger.info(`Pull request created: ${prUrl}`);
|
||||
}
|
||||
else {
|
||||
this.logger.warn("Pull request creation and remote push skipped");
|
||||
this.logger.info(`${JSON.stringify(backport, null, 2)}`);
|
||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ export default abstract class ArgsParser {
|
|||
squash: this.getOrDefault(args.squash, true),
|
||||
strategy: this.getOrDefault(args.strategy),
|
||||
strategyOption: this.getOrDefault(args.strategyOption),
|
||||
comments: this.getOrDefault(args.comments)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -44,6 +44,12 @@ export function getAsCommaSeparatedList(value: string): string[] | undefined {
|
|||
return trimmed !== "" ? trimmed.split(",").map(v => v.trim()) : undefined;
|
||||
}
|
||||
|
||||
export function getAsSemicolonSeparatedList(value: string): string[] | undefined {
|
||||
// trim the value
|
||||
const trimmed: string = value.trim();
|
||||
return trimmed !== "" ? trimmed.split(";").map(v => v.trim()) : undefined;
|
||||
}
|
||||
|
||||
export function getAsBooleanOrDefault(value: string): boolean | undefined {
|
||||
const trimmed = value.trim();
|
||||
return trimmed !== "" ? trimmed.toLowerCase() === "true" : undefined;
|
||||
|
|
|
@ -21,4 +21,5 @@ export interface Args {
|
|||
squash?: boolean, // if false use squashed/merged commit otherwise backport all commits as part of the pr
|
||||
strategy?: string, // cherry-pick merge strategy
|
||||
strategyOption?: string, // cherry-pick merge strategy option
|
||||
comments?: string[], // additional comments to be posted
|
||||
}
|
|
@ -2,7 +2,7 @@ import ArgsParser from "@bp/service/args/args-parser";
|
|||
import { Args } from "@bp/service/args/args.types";
|
||||
import { Command } from "commander";
|
||||
import { name, version, description } from "@bp/../package.json";
|
||||
import { getAsCleanedCommaSeparatedList, getAsCommaSeparatedList, readConfigFile } from "@bp/service/args/args-utils";
|
||||
import { getAsCleanedCommaSeparatedList, getAsCommaSeparatedList, getAsSemicolonSeparatedList, readConfigFile } from "@bp/service/args/args-utils";
|
||||
|
||||
export default class CLIArgsParser extends ArgsParser {
|
||||
|
||||
|
@ -29,6 +29,7 @@ export default class CLIArgsParser extends ArgsParser {
|
|||
.option("--no-squash", "if provided the tool will backport all commits as part of the pull request")
|
||||
.option("--strategy <strategy>", "cherry-pick merge strategy, default to 'recursive'", undefined)
|
||||
.option("--strategy-option <strategy-option>", "cherry-pick merge strategy option, default to 'theirs'")
|
||||
.option("--comments <comments>", "semicolon separated list of additional comments to be posted to the backported pull request", getAsSemicolonSeparatedList)
|
||||
.option("-cf, --config-file <config-file>", "configuration file containing all valid options, the json must match Args interface");
|
||||
}
|
||||
|
||||
|
@ -62,6 +63,7 @@ export default class CLIArgsParser extends ArgsParser {
|
|||
squash: opts.squash,
|
||||
strategy: opts.strategy,
|
||||
strategyOption: opts.strategyOption,
|
||||
comments: opts.comments,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ArgsParser from "@bp/service/args/args-parser";
|
||||
import { Args } from "@bp/service/args/args.types";
|
||||
import { getInput } from "@actions/core";
|
||||
import { getAsBooleanOrDefault, getAsCleanedCommaSeparatedList, getAsCommaSeparatedList, getOrUndefined, readConfigFile } from "@bp/service/args/args-utils";
|
||||
import { getAsBooleanOrDefault, getAsCleanedCommaSeparatedList, getAsCommaSeparatedList, getAsSemicolonSeparatedList, getOrUndefined, readConfigFile } from "@bp/service/args/args-utils";
|
||||
|
||||
export default class GHAArgsParser extends ArgsParser {
|
||||
|
||||
|
@ -32,6 +32,7 @@ export default class GHAArgsParser extends ArgsParser {
|
|||
squash: !getAsBooleanOrDefault(getInput("no-squash")),
|
||||
strategy: getOrUndefined(getInput("strategy")),
|
||||
strategyOption: getOrUndefined(getInput("strategy-option")),
|
||||
comments: getAsSemicolonSeparatedList(getInput("comments")),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
import { GitPullRequest } from "@bp/service/git/git.types";
|
||||
import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
|
||||
|
||||
export interface LocalGit {
|
||||
user: string, // local git user
|
||||
|
@ -19,6 +19,6 @@ export interface Configs {
|
|||
mergeStrategy?: string, // cherry-pick merge strategy
|
||||
mergeStrategyOption?: string, // cherry-pick merge strategy option
|
||||
originalPullRequest: GitPullRequest,
|
||||
backportPullRequest: GitPullRequest,
|
||||
backportPullRequest: BackportPullRequest,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import ConfigsParser from "@bp/service/configs/configs-parser";
|
|||
import { Configs } from "@bp/service/configs/configs.types";
|
||||
import GitClient from "@bp/service/git/git-client";
|
||||
import GitClientFactory from "@bp/service/git/git-client-factory";
|
||||
import { GitPullRequest } from "@bp/service/git/git.types";
|
||||
import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
|
||||
|
||||
export default class PullRequestConfigsParser extends ConfigsParser {
|
||||
|
||||
|
@ -52,7 +52,7 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
|||
* @param targetBranch target branch where the backport should be applied
|
||||
* @returns {GitPullRequest}
|
||||
*/
|
||||
private getDefaultBackportPullRequest(originalPullRequest: GitPullRequest, args: Args): GitPullRequest {
|
||||
private getDefaultBackportPullRequest(originalPullRequest: GitPullRequest, args: Args): BackportPullRequest {
|
||||
const reviewers = args.reviewers ?? [];
|
||||
if (reviewers.length == 0 && args.inheritReviewers) {
|
||||
// inherit only if args.reviewers is empty and args.inheritReviewers set to true
|
||||
|
@ -70,16 +70,29 @@ export default class PullRequestConfigsParser extends ConfigsParser {
|
|||
labels.push(...originalPullRequest.labels);
|
||||
}
|
||||
|
||||
let backportBranch = args.bpBranchName;
|
||||
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
|
||||
const concatenatedCommits: string = originalPullRequest.commits!.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${args.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
|
||||
return {
|
||||
author: args.gitUser ?? this.gitClient.getDefaultGitUser(),
|
||||
owner: originalPullRequest.targetRepo.owner,
|
||||
repo: originalPullRequest.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: args.targetBranch,
|
||||
title: args.title ?? `[${args.targetBranch}] ${originalPullRequest.title}`,
|
||||
body: `${bodyPrefix}${body}`,
|
||||
reviewers: [...new Set(reviewers)],
|
||||
assignees: [...new Set(args.assignees)],
|
||||
labels: [...new Set(labels)],
|
||||
targetRepo: originalPullRequest.targetRepo,
|
||||
sourceRepo: originalPullRequest.targetRepo,
|
||||
branchName: args.bpBranchName,
|
||||
comments: args.comments ?? [],
|
||||
};
|
||||
}
|
||||
}
|
|
@ -38,4 +38,5 @@ import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types";
|
|||
* @returns {Promise<string>} the pull request url
|
||||
*/
|
||||
createPullRequest(backport: BackportPullRequest): Promise<string>;
|
||||
|
||||
}
|
|
@ -13,8 +13,8 @@ export interface GitPullRequest {
|
|||
labels: string[],
|
||||
targetRepo: GitRepository,
|
||||
sourceRepo: GitRepository,
|
||||
nCommits?: number, // number of commits in the pr
|
||||
commits?: string[], // merge commit or last one
|
||||
nCommits: number, // number of commits in the pr
|
||||
commits: string[], // merge commit or last one
|
||||
branchName?: string,
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,8 @@ export interface BackportPullRequest {
|
|||
reviewers: string[], // pr list of reviewers
|
||||
assignees: string[], // pr list of assignees
|
||||
labels: string[], // pr list of assigned labels
|
||||
branchName?: string,
|
||||
comments: string[], // pr list of additional comments
|
||||
// branchName?: string,
|
||||
}
|
||||
|
||||
export enum GitClientType {
|
||||
|
|
|
@ -117,6 +117,19 @@ export default class GitHubClient implements GitClient {
|
|||
);
|
||||
}
|
||||
|
||||
if (backport.comments.length > 0) {
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(
|
||||
this.octokit.issues.createComment({
|
||||
owner: backport.owner,
|
||||
repo: backport.repo,
|
||||
issue_number: (data as PullRequest).number,
|
||||
body: c,
|
||||
}).catch(error => this.logger.error(`Error posting comment: ${error}`))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
return data.html_url;
|
||||
|
|
|
@ -96,6 +96,18 @@ export default class GitLabClient implements GitClient {
|
|||
);
|
||||
}
|
||||
|
||||
// comments
|
||||
if (backport.comments.length > 0) {
|
||||
this.logger.info("Posting comments: " + backport.comments);
|
||||
backport.comments.forEach(c => {
|
||||
promises.push(
|
||||
this.client.post(`/projects/${projectId}/merge_requests/${mr.iid}/notes`, {
|
||||
body: c,
|
||||
}).catch(error => this.logger.warn("Failure trying to post comment. " + error))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// reviewers
|
||||
const reviewerIds = await Promise.all(backport.reviewers.map(async r => {
|
||||
this.logger.debug("Retrieving user: " + r);
|
||||
|
@ -141,7 +153,6 @@ export default class GitLabClient implements GitClient {
|
|||
return mr.web_url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a gitlab user given its username
|
||||
* @param username
|
||||
|
|
|
@ -63,7 +63,7 @@ export default class Runner {
|
|||
this.logger.debug("Parsing configs..");
|
||||
const configs: Configs = await new PullRequestConfigsParser().parseAndValidate(args);
|
||||
const originalPR: GitPullRequest = configs.originalPullRequest;
|
||||
const backportPR: GitPullRequest = configs.backportPullRequest;
|
||||
const backportPR: BackportPullRequest = configs.backportPullRequest;
|
||||
|
||||
// start local git operations
|
||||
const git: GitCLIService = new GitCLIService(configs.auth, configs.git);
|
||||
|
@ -74,19 +74,8 @@ export default class Runner {
|
|||
|
||||
// 5. create new branch from target one and checkout
|
||||
this.logger.debug("Creating local branch..");
|
||||
let backportBranch = backportPR.branchName;
|
||||
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
|
||||
const concatenatedCommits: string = originalPR.commits!.map(c => c.slice(0, 7)).join("-");
|
||||
backportBranch = `bp-${configs.targetBranch}-${concatenatedCommits}`;
|
||||
}
|
||||
|
||||
if (backportBranch.length > 250) {
|
||||
this.logger.warn(`Backport branch (length=${backportBranch.length}) exceeded the max length of 250 chars, branch name truncated!`);
|
||||
backportBranch = backportBranch.slice(0, 250);
|
||||
}
|
||||
|
||||
await git.createLocalBranch(configs.folder, backportBranch);
|
||||
await git.createLocalBranch(configs.folder, backportPR.head);
|
||||
|
||||
// 6. fetch pull request remote if source owner != target owner or pull request still open
|
||||
if (configs.originalPullRequest.sourceRepo.owner !== configs.originalPullRequest.targetRepo.owner ||
|
||||
|
@ -102,29 +91,17 @@ export default class Runner {
|
|||
await git.cherryPick(configs.folder, sha, configs.mergeStrategy, configs.mergeStrategyOption);
|
||||
}
|
||||
|
||||
const backport: BackportPullRequest = {
|
||||
owner: originalPR.targetRepo.owner,
|
||||
repo: originalPR.targetRepo.project,
|
||||
head: backportBranch,
|
||||
base: configs.targetBranch,
|
||||
title: backportPR.title,
|
||||
body: backportPR.body,
|
||||
reviewers: backportPR.reviewers,
|
||||
assignees: backportPR.assignees,
|
||||
labels: backportPR.labels,
|
||||
};
|
||||
|
||||
if (!configs.dryRun) {
|
||||
// 8. push the new branch to origin
|
||||
await git.push(configs.folder, backportBranch);
|
||||
await git.push(configs.folder, backportPR.head);
|
||||
|
||||
// 9. create pull request new branch -> target branch (using octokit)
|
||||
const prUrl = await gitApi.createPullRequest(backport);
|
||||
const prUrl = await gitApi.createPullRequest(backportPR);
|
||||
this.logger.info(`Pull request created: ${prUrl}`);
|
||||
|
||||
} else {
|
||||
this.logger.warn("Pull request creation and remote push skipped");
|
||||
this.logger.info(`${JSON.stringify(backport, null, 2)}`);
|
||||
this.logger.info(`${JSON.stringify(backportPR, null, 2)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -402,4 +402,35 @@ describe("cli args parser", () => {
|
|||
expect(args.strategy).toEqual("ort");
|
||||
expect(args.strategyOption).toEqual("ours");
|
||||
});
|
||||
|
||||
test("additional pr comments", () => {
|
||||
addProcessArgs([
|
||||
"--target-branch",
|
||||
"target",
|
||||
"--pull-request",
|
||||
"https://localhost/whatever/pulls/1",
|
||||
"--comments",
|
||||
"first comment;second comment",
|
||||
]);
|
||||
|
||||
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");
|
||||
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);
|
||||
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
||||
});
|
||||
});
|
|
@ -236,4 +236,30 @@ describe("gha args parser", () => {
|
|||
expect(args.strategy).toEqual("ort");
|
||||
expect(args.strategyOption).toEqual("ours");
|
||||
});
|
||||
|
||||
test("additional pr comments", () => {
|
||||
spyGetInput({
|
||||
"target-branch": "target",
|
||||
"pull-request": "https://localhost/whatever/pulls/1",
|
||||
"comments": "first comment;second comment",
|
||||
});
|
||||
|
||||
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");
|
||||
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);
|
||||
expectArrayEqual(args.comments!,["first comment", "second comment"]);
|
||||
});
|
||||
});
|
|
@ -129,25 +129,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "GitHub",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "[prod] 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: [],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -264,6 +255,7 @@ describe("github pull request config parser", () => {
|
|||
reviewers: [],
|
||||
assignees: [],
|
||||
inheritReviewers: true,
|
||||
bpBranchName: "custom-branch"
|
||||
};
|
||||
|
||||
const configs: Configs = await configParser.parseAndValidate(args);
|
||||
|
@ -309,25 +301,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "custom-branch",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -390,25 +373,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -471,25 +445,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -554,25 +519,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["custom-label", "original-label"],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -625,25 +581,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "GitHub",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "[prod] 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: [],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -697,25 +644,16 @@ describe("github pull request config parser", () => {
|
|||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["cherry-pick :cherries:", "original-label"],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -775,25 +713,91 @@ describe("github pull request config parser", () => {
|
|||
commits: ["0404fb922ab75c3a8aecad5c97d9af388df04695", "11da4e38aa3e577ffde6d546f1c52e53b04d3151"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "GitHub",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-0404fb9-11da4e3",
|
||||
base: "prod",
|
||||
title: "[prod] 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: [],
|
||||
});
|
||||
});
|
||||
|
||||
test("override backport pr with additional comments", 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: ["user3", "user4"],
|
||||
inheritReviewers: false,
|
||||
labels: [],
|
||||
inheritLabels: false,
|
||||
comments: ["First comment", "Second comment"],
|
||||
};
|
||||
|
||||
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.git).toEqual({
|
||||
user: "Me",
|
||||
email: "me@email.com"
|
||||
});
|
||||
expect(configs.auth).toEqual("");
|
||||
expect(configs.targetBranch).toEqual("prod");
|
||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||
expect(configs.originalPullRequest).toEqual({
|
||||
number: 2368,
|
||||
author: "gh-user",
|
||||
url: "https://api.github.com/repos/owner/reponame/pulls/2368",
|
||||
htmlUrl: "https://github.com/owner/reponame/pull/2368",
|
||||
state: "closed",
|
||||
merged: true,
|
||||
mergedBy: "that-s-a-user",
|
||||
title: "PR Title",
|
||||
body: "Please review and merge",
|
||||
reviewers: ["requested-gh-user", "gh-user"],
|
||||
assignees: [],
|
||||
labels: ["original-label"],
|
||||
targetRepo: {
|
||||
owner: "owner",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "owner",
|
||||
owner: "fork",
|
||||
project: "reponame",
|
||||
cloneUrl: "https://github.com/owner/reponame.git"
|
||||
cloneUrl: "https://github.com/fork/reponame.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
nCommits: 2,
|
||||
commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"],
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-prod-28f63db",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: ["First comment", "Second comment"],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -129,25 +129,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Gitlab",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "[prod] Update test.txt",
|
||||
body: "**Backport:** https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/1\r\n\r\nThis is the body",
|
||||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -314,25 +305,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -394,25 +376,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -474,25 +447,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -556,25 +520,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["custom-label", "gitlab-original-label"],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -626,25 +581,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Gitlab",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "[prod] Update test.txt",
|
||||
body: "**Backport:** https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/1\r\n\r\nThis is the body",
|
||||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -696,25 +642,16 @@ describe("gitlab merge request config parser", () => {
|
|||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
author: "Me",
|
||||
url: undefined,
|
||||
htmlUrl: undefined,
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["cherry-pick :cherries:", "gitlab-original-label"],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
bpBranchName: undefined,
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -773,5 +710,91 @@ describe("gitlab merge request config parser", () => {
|
|||
nCommits: 2,
|
||||
commits: ["e4dd336a4a20f394df6665994df382fb1d193a11", "974519f65c9e0ed65277cd71026657a09fca05e7"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-e4dd336-974519f",
|
||||
base: "prod",
|
||||
title: "[prod] Update test.txt opened",
|
||||
body: "**Backport:** https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/2\r\n\r\nStill opened mr body",
|
||||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
});
|
||||
});
|
||||
|
||||
test("override backport pr with additional comments", 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: ["user3", "user4"],
|
||||
inheritReviewers: false,
|
||||
labels: [],
|
||||
inheritLabels: false,
|
||||
comments: ["First comment", "Second comment"],
|
||||
};
|
||||
|
||||
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.git).toEqual({
|
||||
user: "Me",
|
||||
email: "me@email.com"
|
||||
});
|
||||
expect(configs.auth).toEqual("");
|
||||
expect(configs.targetBranch).toEqual("prod");
|
||||
expect(configs.folder).toEqual(process.cwd() + "/bp");
|
||||
expect(configs.originalPullRequest).toEqual({
|
||||
number: 1,
|
||||
author: "superuser",
|
||||
url: "https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/1",
|
||||
htmlUrl: "https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/1",
|
||||
state: "merged",
|
||||
merged: true,
|
||||
mergedBy: "superuser",
|
||||
title: "Update test.txt",
|
||||
body: "This is the body",
|
||||
reviewers: ["superuser1", "superuser2"],
|
||||
assignees: ["superuser"],
|
||||
labels: ["gitlab-original-label"],
|
||||
targetRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
sourceRepo: {
|
||||
owner: "superuser",
|
||||
project: "backporting-example",
|
||||
cloneUrl: "https://my.gitlab.host.com/superuser/backporting-example.git"
|
||||
},
|
||||
nCommits: 1,
|
||||
commits: ["ebb1eca696c42fd067658bd9b5267709f78ef38e"]
|
||||
});
|
||||
expect(configs.backportPullRequest).toEqual({
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
head: "bp-prod-ebb1eca",
|
||||
base: "prod",
|
||||
title: "New Title",
|
||||
body: "New Body Prefix -New Body",
|
||||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: ["First comment", "Second comment"],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -89,6 +89,7 @@ describe("github service", () => {
|
|||
reviewers: [],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -119,6 +120,7 @@ describe("github service", () => {
|
|||
reviewers: ["superuser", "invalid"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -154,6 +156,7 @@ describe("github service", () => {
|
|||
reviewers: [],
|
||||
assignees: ["superuser", "invalid"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -189,6 +192,7 @@ describe("github service", () => {
|
|||
reviewers: ["superuser", "invalid"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -224,6 +228,7 @@ describe("github service", () => {
|
|||
reviewers: [],
|
||||
assignees: ["superuser", "invalid"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -259,6 +264,7 @@ describe("github service", () => {
|
|||
reviewers: [],
|
||||
assignees: [],
|
||||
labels: ["label1", "label2"],
|
||||
comments: [],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
|
@ -280,4 +286,41 @@ describe("github service", () => {
|
|||
labels: "label1,label2",
|
||||
});
|
||||
});
|
||||
|
||||
test("create backport pull request with post comments", async () => {
|
||||
const backport: BackportPullRequest = {
|
||||
title: "Backport Title",
|
||||
body: "Backport Body",
|
||||
owner: "superuser",
|
||||
repo: "backporting-example",
|
||||
base: "old/branch",
|
||||
head: "bp-branch-2",
|
||||
reviewers: [],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: ["this is first comment", "this is second comment"],
|
||||
};
|
||||
|
||||
const url: string = await gitClient.createPullRequest(backport);
|
||||
expect(url).toStrictEqual("https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/" + SECOND_NEW_GITLAB_MR_ID);
|
||||
|
||||
// check axios invocation
|
||||
expect(axiosInstanceSpy.post).toBeCalledTimes(3); // also comments
|
||||
expect(axiosInstanceSpy.post).toBeCalledWith("/projects/superuser%2Fbackporting-example/merge_requests", expect.objectContaining({
|
||||
source_branch: "bp-branch-2",
|
||||
target_branch: "old/branch",
|
||||
title: "Backport Title",
|
||||
description: "Backport Body",
|
||||
reviewer_ids: [],
|
||||
assignee_ids: [],
|
||||
}));
|
||||
expect(axiosInstanceSpy.get).toBeCalledTimes(0);
|
||||
|
||||
expect(axiosInstanceSpy.post).toBeCalledWith("/projects/superuser%2Fbackporting-example/merge_requests/" + SECOND_NEW_GITLAB_MR_ID + "/notes", {
|
||||
body: "this is first comment",
|
||||
});
|
||||
expect(axiosInstanceSpy.post).toBeCalledWith("/projects/superuser%2Fbackporting-example/merge_requests/" + SECOND_NEW_GITLAB_MR_ID + "/notes", {
|
||||
body: "this is second comment",
|
||||
});
|
||||
});
|
||||
});
|
|
@ -233,6 +233,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -277,6 +278,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -333,6 +335,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -390,6 +393,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -446,6 +450,7 @@ describe("cli runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -494,11 +499,12 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("set custom lables without inheritance", async () => {
|
||||
test("set custom labels without inheritance", async () => {
|
||||
addProcessArgs([
|
||||
"-tb",
|
||||
"target",
|
||||
|
@ -541,6 +547,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: ["first-label", "second-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -584,6 +591,7 @@ describe("cli runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["cli github cherry pick :cherries:", "original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -630,6 +638,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -676,6 +685,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -728,6 +738,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -778,6 +789,54 @@ describe("cli runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("additional pr comments", async () => {
|
||||
addProcessArgs([
|
||||
"-tb",
|
||||
"target",
|
||||
"-pr",
|
||||
"https://github.com/owner/reponame/pull/8632",
|
||||
"--comments",
|
||||
"first comment; second comment"
|
||||
]);
|
||||
|
||||
await runner.execute();
|
||||
|
||||
const cwd = process.cwd() + "/bp";
|
||||
|
||||
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||
|
||||
expect(GitCLIService.prototype.clone).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "target");
|
||||
|
||||
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-target-28f63db");
|
||||
|
||||
expect(GitCLIService.prototype.fetch).toBeCalledTimes(0);
|
||||
|
||||
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||
|
||||
expect(GitCLIService.prototype.push).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-target-28f63db");
|
||||
|
||||
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(1);
|
||||
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-target-28f63db",
|
||||
base: "target",
|
||||
title: "[target] PR Title",
|
||||
body: expect.stringContaining("**Backport:** https://github.com/owner/reponame/pull/8632"),
|
||||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: ["first comment", "second comment"],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -181,6 +181,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -238,6 +239,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -296,6 +298,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -352,6 +355,7 @@ describe("cli runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -401,6 +405,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label", "gitlab-original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -449,6 +454,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -493,6 +499,7 @@ describe("cli runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["cli gitlab cherry pick :cherries:", "gitlab-original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -540,6 +547,7 @@ describe("cli runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -125,6 +125,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -177,6 +178,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -226,6 +228,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -276,6 +279,7 @@ describe("gha runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -321,6 +325,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label", "original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -366,6 +371,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -408,6 +414,7 @@ describe("gha runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["gha github cherry pick :cherries:", "original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -452,6 +459,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -496,6 +504,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -541,6 +550,52 @@ describe("gha runner", () => {
|
|||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("additional pr comments", async () => {
|
||||
spyGetInput({
|
||||
"target-branch": "target",
|
||||
"pull-request": "https://github.com/owner/reponame/pull/2368",
|
||||
"comments": "first comment; second comment",
|
||||
});
|
||||
|
||||
await runner.execute();
|
||||
|
||||
const cwd = process.cwd() + "/bp";
|
||||
|
||||
expect(GitClientFactory.getOrCreate).toBeCalledTimes(1);
|
||||
expect(GitClientFactory.getOrCreate).toBeCalledWith(GitClientType.GITHUB, undefined, "https://api.github.com");
|
||||
|
||||
expect(GitCLIService.prototype.clone).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.clone).toBeCalledWith("https://github.com/owner/reponame.git", cwd, "target");
|
||||
|
||||
expect(GitCLIService.prototype.createLocalBranch).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.createLocalBranch).toBeCalledWith(cwd, "bp-target-28f63db");
|
||||
|
||||
expect(GitCLIService.prototype.fetch).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.fetch).toBeCalledWith(cwd, "pull/2368/head:pr/2368");
|
||||
|
||||
expect(GitCLIService.prototype.cherryPick).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.cherryPick).toBeCalledWith(cwd, "28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc", undefined, undefined);
|
||||
|
||||
expect(GitCLIService.prototype.push).toBeCalledTimes(1);
|
||||
expect(GitCLIService.prototype.push).toBeCalledWith(cwd, "bp-target-28f63db");
|
||||
|
||||
expect(GitHubClient.prototype.createPullRequest).toBeCalledTimes(1);
|
||||
expect(GitHubClient.prototype.createPullRequest).toBeCalledWith({
|
||||
owner: "owner",
|
||||
repo: "reponame",
|
||||
head: "bp-target-28f63db",
|
||||
base: "target",
|
||||
title: "[target] PR Title",
|
||||
body: expect.stringContaining("**Backport:** https://github.com/owner/reponame/pull/2368"),
|
||||
reviewers: ["gh-user", "that-s-a-user"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: ["first comment", "second comment"],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -136,6 +136,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -187,6 +188,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -236,6 +238,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["user1", "user2"],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -286,6 +289,7 @@ describe("gha runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -330,6 +334,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label", "gitlab-original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -373,6 +378,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: ["cherry-pick :cherries:", "another-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -416,6 +422,7 @@ describe("gha runner", () => {
|
|||
reviewers: [],
|
||||
assignees: ["user3", "user4"],
|
||||
labels: ["gha gitlab cherry pick :cherries:", "gitlab-original-label"],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -461,6 +468,7 @@ describe("gha runner", () => {
|
|||
reviewers: ["superuser"],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
comments: [],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -34,18 +34,24 @@ export const getAxiosMocked = (url: string) => {
|
|||
|
||||
export const NEW_GITLAB_MR_ID = 999;
|
||||
export const SECOND_NEW_GITLAB_MR_ID = 1000;
|
||||
export const postAxiosMocked = (_url: string, data?: {source_branch: string,}) => {
|
||||
export const postAxiosMocked = async (url: string, data?: {source_branch: string,}) => {
|
||||
let responseData = undefined;
|
||||
|
||||
// gitlab
|
||||
|
||||
if (data?.source_branch === "bp-branch") {
|
||||
if (url.includes("notes")) {
|
||||
// creating comments
|
||||
responseData = {
|
||||
// we do not need the whole response
|
||||
iid: NEW_GITLAB_MR_ID,
|
||||
};
|
||||
} else if (data?.source_branch === "bp-branch") {
|
||||
responseData = {
|
||||
// we do not need the whole response
|
||||
iid: NEW_GITLAB_MR_ID,
|
||||
web_url: "https://my.gitlab.host.com/superuser/backporting-example/-/merge_requests/" + NEW_GITLAB_MR_ID
|
||||
};
|
||||
} if (data?.source_branch === "bp-branch-2") {
|
||||
} else if (data?.source_branch === "bp-branch-2") {
|
||||
responseData = {
|
||||
// we do not need the whole response
|
||||
iid: SECOND_NEW_GITLAB_MR_ID,
|
||||
|
@ -169,6 +175,13 @@ export const mockGitHubClient = (apiUrl = "https://api.github.com"): Moctokit =>
|
|||
data: {}
|
||||
});
|
||||
|
||||
mock.rest.issues
|
||||
.createComment()
|
||||
.reply({
|
||||
status: 201,
|
||||
data: {}
|
||||
});
|
||||
|
||||
// invalid requests
|
||||
mock.rest.pulls
|
||||
.get({
|
||||
|
|
Loading…
Add table
Reference in a new issue