From 10a46551ee6855bec529aa45b494c1d5058235a1 Mon Sep 17 00:00:00 2001 From: Andrea Lamparelli Date: Thu, 27 Jul 2023 11:26:39 +0200 Subject: [PATCH 1/2] refactor: move backport data generation to configs parser --- dist/cli/index.js | 48 +++--- dist/gha/index.js | 48 +++--- src/service/configs/configs.types.ts | 4 +- .../configs/pullrequest/pr-configs-parser.ts | 25 ++- src/service/git/git-client.ts | 1 + src/service/git/git.types.ts | 7 +- src/service/git/gitlab/gitlab-client.ts | 1 - src/service/runner/runner.ts | 33 +--- .../github-pr-configs-parser.test.ts | 155 +++++------------- .../gitlab-pr-configs-parser.test.ts | 145 ++++++---------- test/service/git/gitlab/gitlab-client.test.ts | 41 +++++ test/service/runner/cli-github-runner.test.ts | 14 +- test/service/runner/cli-gitlab-runner.test.ts | 8 + test/service/runner/gha-github-runner.test.ts | 10 ++ test/service/runner/gha-gitlab-runner.test.ts | 8 + 15 files changed, 238 insertions(+), 310 deletions(-) diff --git a/dist/cli/index.js b/dist/cli/index.js index b39241d..4d4cb2b 100755 --- a/dist/cli/index.js +++ b/dist/cli/index.js @@ -336,16 +336,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: [], // TODO fix comments }; } } @@ -1211,17 +1222,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 +1235,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)}`); } } } diff --git a/dist/gha/index.js b/dist/gha/index.js index cf28269..c89d340 100755 --- a/dist/gha/index.js +++ b/dist/gha/index.js @@ -307,16 +307,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: [], // TODO fix comments }; } } @@ -1182,17 +1193,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 +1206,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)}`); } } } diff --git a/src/service/configs/configs.types.ts b/src/service/configs/configs.types.ts index 0f82cfc..be46157 100644 --- a/src/service/configs/configs.types.ts +++ b/src/service/configs/configs.types.ts @@ -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, } diff --git a/src/service/configs/pullrequest/pr-configs-parser.ts b/src/service/configs/pullrequest/pr-configs-parser.ts index d83d9cd..4eb1111 100644 --- a/src/service/configs/pullrequest/pr-configs-parser.ts +++ b/src/service/configs/pullrequest/pr-configs-parser.ts @@ -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: [], // TODO fix comments }; } } \ No newline at end of file diff --git a/src/service/git/git-client.ts b/src/service/git/git-client.ts index b14f603..7b98c1b 100644 --- a/src/service/git/git-client.ts +++ b/src/service/git/git-client.ts @@ -38,4 +38,5 @@ import { BackportPullRequest, GitPullRequest } from "@bp/service/git/git.types"; * @returns {Promise} the pull request url */ createPullRequest(backport: BackportPullRequest): Promise; + } \ No newline at end of file diff --git a/src/service/git/git.types.ts b/src/service/git/git.types.ts index 4ca5405..6370eee 100644 --- a/src/service/git/git.types.ts +++ b/src/service/git/git.types.ts @@ -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 { diff --git a/src/service/git/gitlab/gitlab-client.ts b/src/service/git/gitlab/gitlab-client.ts index 725eacb..af4c626 100644 --- a/src/service/git/gitlab/gitlab-client.ts +++ b/src/service/git/gitlab/gitlab-client.ts @@ -141,7 +141,6 @@ export default class GitLabClient implements GitClient { return mr.web_url; } - /** * Retrieve a gitlab user given its username * @param username diff --git a/src/service/runner/runner.ts b/src/service/runner/runner.ts index 2ad5364..e5d0db0 100644 --- a/src/service/runner/runner.ts +++ b/src/service/runner/runner.ts @@ -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)}`); } } diff --git a/test/service/configs/pullrequest/github-pr-configs-parser.test.ts b/test/service/configs/pullrequest/github-pr-configs-parser.test.ts index 950c01f..ce432b9 100644 --- a/test/service/configs/pullrequest/github-pr-configs-parser.test.ts +++ b/test/service/configs/pullrequest/github-pr-configs-parser.test.ts @@ -129,25 +129,16 @@ describe("github pull request config parser", () => { commits: ["28f63db774185f4ec4b57cd9aaeb12dbfb4c9ecc"] }); expect(configs.backportPullRequest).toEqual({ - author: "GitHub", - url: undefined, - htmlUrl: undefined, - title: "[prod] PR Title", + 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,16 @@ 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: [], - 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: [], }); }); }); \ No newline at end of file diff --git a/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts b/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts index 8e10d17..8eb269b 100644 --- a/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts +++ b/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts @@ -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,17 @@ 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: [], + }); }); }); \ No newline at end of file diff --git a/test/service/git/gitlab/gitlab-client.test.ts b/test/service/git/gitlab/gitlab-client.test.ts index affe096..c4f4816 100644 --- a/test/service/git/gitlab/gitlab-client.test.ts +++ b/test/service/git/gitlab/gitlab-client.test.ts @@ -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,39 @@ 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(1); + 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); + // FIXME + // expect(axiosInstanceSpy.put).toBeCalledTimes(1); // just comments + // expect(axiosInstanceSpy.put).toBeCalledWith("/projects/superuser%2Fbackporting-example/merge_requests/" + SECOND_NEW_GITLAB_MR_ID, { + // labels: "label1,label2", + // }); + }); }); \ No newline at end of file diff --git a/test/service/runner/cli-github-runner.test.ts b/test/service/runner/cli-github-runner.test.ts index f70d446..3aa82ef 100644 --- a/test/service/runner/cli-github-runner.test.ts +++ b/test/service/runner/cli-github-runner.test.ts @@ -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,7 @@ describe("cli runner", () => { reviewers: ["gh-user", "that-s-a-user"], assignees: [], labels: [], + comments: [], } ); }); diff --git a/test/service/runner/cli-gitlab-runner.test.ts b/test/service/runner/cli-gitlab-runner.test.ts index c13be27..ab6f72b 100644 --- a/test/service/runner/cli-gitlab-runner.test.ts +++ b/test/service/runner/cli-gitlab-runner.test.ts @@ -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: [], } ); }); diff --git a/test/service/runner/gha-github-runner.test.ts b/test/service/runner/gha-github-runner.test.ts index 69de6d0..1f412ba 100644 --- a/test/service/runner/gha-github-runner.test.ts +++ b/test/service/runner/gha-github-runner.test.ts @@ -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,7 @@ describe("gha runner", () => { reviewers: ["gh-user", "that-s-a-user"], assignees: [], labels: [], + comments: [], } ); }); diff --git a/test/service/runner/gha-gitlab-runner.test.ts b/test/service/runner/gha-gitlab-runner.test.ts index 4610cee..8158818 100644 --- a/test/service/runner/gha-gitlab-runner.test.ts +++ b/test/service/runner/gha-gitlab-runner.test.ts @@ -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: [], } ); }); From bed7e29ddc1ba5498faa2c7cc33ec3b127947dcf Mon Sep 17 00:00:00 2001 From: Andrea Lamparelli Date: Thu, 27 Jul 2023 12:31:04 +0200 Subject: [PATCH 2/2] feat(issue-70): additional pr comments --- README.md | 1 + action.yml | 3 + dist/cli/index.js | 32 +++++++- dist/gha/index.js | 31 +++++++- src/service/args/args-parser.ts | 1 + src/service/args/args-utils.ts | 6 ++ src/service/args/args.types.ts | 1 + src/service/args/cli/cli-args-parser.ts | 4 +- src/service/args/gha/gha-args-parser.ts | 3 +- .../configs/pullrequest/pr-configs-parser.ts | 2 +- src/service/git/github/github-client.ts | 13 ++++ src/service/git/gitlab/gitlab-client.ts | 12 +++ test/service/args/cli/cli-args-parser.test.ts | 31 ++++++++ test/service/args/gha/gha-args-parser.test.ts | 26 +++++++ .../github-pr-configs-parser.test.ts | 75 +++++++++++++++++++ .../gitlab-pr-configs-parser.test.ts | 74 ++++++++++++++++++ test/service/git/gitlab/gitlab-client.test.ts | 14 ++-- test/service/runner/cli-github-runner.test.ts | 47 ++++++++++++ test/service/runner/gha-github-runner.test.ts | 45 +++++++++++ test/support/mock/git-client-mock-support.ts | 19 ++++- 20 files changed, 424 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 15d8d58..1988232 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/action.yml b/action.yml index 90bc2d5..5deca80 100644 --- a/action.yml +++ b/action.yml @@ -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 diff --git a/dist/cli/index.js b/dist/cli/index.js index 4d4cb2b..87e057f 100755 --- a/dist/cli/index.js +++ b/dist/cli/index.js @@ -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 ", "cherry-pick merge strategy, default to 'recursive'", undefined) .option("--strategy-option ", "cherry-pick merge strategy option, default to 'theirs'") + .option("--comments ", "semicolon separated list of additional comments to be posted to the backported pull request", args_utils_1.getAsSemicolonSeparatedList) .option("-cf, --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; @@ -356,7 +365,7 @@ class PullRequestConfigsParser extends configs_parser_1.default { reviewers: [...new Set(reviewers)], assignees: [...new Set(args.assignees)], labels: [...new Set(labels)], - comments: [], // TODO fix comments + comments: args.comments ?? [], }; } } @@ -721,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; } @@ -917,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); diff --git a/dist/gha/index.js b/dist/gha/index.js index c89d340..a4d41a2 100755 --- a/dist/gha/index.js +++ b/dist/gha/index.js @@ -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; @@ -327,7 +335,7 @@ class PullRequestConfigsParser extends configs_parser_1.default { reviewers: [...new Set(reviewers)], assignees: [...new Set(args.assignees)], labels: [...new Set(labels)], - comments: [], // TODO fix comments + comments: args.comments ?? [], }; } } @@ -692,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; } @@ -888,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); diff --git a/src/service/args/args-parser.ts b/src/service/args/args-parser.ts index d70fa27..5aee4a6 100644 --- a/src/service/args/args-parser.ts +++ b/src/service/args/args-parser.ts @@ -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) }; } } \ No newline at end of file diff --git a/src/service/args/args-utils.ts b/src/service/args/args-utils.ts index 13a3606..9f6165c 100644 --- a/src/service/args/args-utils.ts +++ b/src/service/args/args-utils.ts @@ -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; diff --git a/src/service/args/args.types.ts b/src/service/args/args.types.ts index b3c1860..880257c 100644 --- a/src/service/args/args.types.ts +++ b/src/service/args/args.types.ts @@ -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 } \ No newline at end of file diff --git a/src/service/args/cli/cli-args-parser.ts b/src/service/args/cli/cli-args-parser.ts index a6065dc..0e8b4e3 100644 --- a/src/service/args/cli/cli-args-parser.ts +++ b/src/service/args/cli/cli-args-parser.ts @@ -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 ", "cherry-pick merge strategy, default to 'recursive'", undefined) .option("--strategy-option ", "cherry-pick merge strategy option, default to 'theirs'") + .option("--comments ", "semicolon separated list of additional comments to be posted to the backported pull request", getAsSemicolonSeparatedList) .option("-cf, --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, }; } diff --git a/src/service/args/gha/gha-args-parser.ts b/src/service/args/gha/gha-args-parser.ts index e3d5ba0..a6c2534 100644 --- a/src/service/args/gha/gha-args-parser.ts +++ b/src/service/args/gha/gha-args-parser.ts @@ -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")), }; } diff --git a/src/service/configs/pullrequest/pr-configs-parser.ts b/src/service/configs/pullrequest/pr-configs-parser.ts index 4eb1111..3cc81ce 100644 --- a/src/service/configs/pullrequest/pr-configs-parser.ts +++ b/src/service/configs/pullrequest/pr-configs-parser.ts @@ -92,7 +92,7 @@ export default class PullRequestConfigsParser extends ConfigsParser { reviewers: [...new Set(reviewers)], assignees: [...new Set(args.assignees)], labels: [...new Set(labels)], - comments: [], // TODO fix comments + comments: args.comments ?? [], }; } } \ No newline at end of file diff --git a/src/service/git/github/github-client.ts b/src/service/git/github/github-client.ts index 0da22df..297052d 100644 --- a/src/service/git/github/github-client.ts +++ b/src/service/git/github/github-client.ts @@ -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; diff --git a/src/service/git/gitlab/gitlab-client.ts b/src/service/git/gitlab/gitlab-client.ts index af4c626..a6d21b8 100644 --- a/src/service/git/gitlab/gitlab-client.ts +++ b/src/service/git/gitlab/gitlab-client.ts @@ -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); diff --git a/test/service/args/cli/cli-args-parser.test.ts b/test/service/args/cli/cli-args-parser.test.ts index 4f64187..2951bf3 100644 --- a/test/service/args/cli/cli-args-parser.test.ts +++ b/test/service/args/cli/cli-args-parser.test.ts @@ -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"]); + }); }); \ No newline at end of file diff --git a/test/service/args/gha/gha-args-parser.test.ts b/test/service/args/gha/gha-args-parser.test.ts index ebe6e81..76efa13 100644 --- a/test/service/args/gha/gha-args-parser.test.ts +++ b/test/service/args/gha/gha-args-parser.test.ts @@ -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"]); + }); }); \ No newline at end of file diff --git a/test/service/configs/pullrequest/github-pr-configs-parser.test.ts b/test/service/configs/pullrequest/github-pr-configs-parser.test.ts index ce432b9..bca5d75 100644 --- a/test/service/configs/pullrequest/github-pr-configs-parser.test.ts +++ b/test/service/configs/pullrequest/github-pr-configs-parser.test.ts @@ -725,4 +725,79 @@ describe("github pull request config parser", () => { 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: "fork", + project: "reponame", + 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"], + }); + }); }); \ No newline at end of file diff --git a/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts b/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts index 8eb269b..691f061 100644 --- a/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts +++ b/test/service/configs/pullrequest/gitlab-pr-configs-parser.test.ts @@ -723,4 +723,78 @@ describe("gitlab merge request config parser", () => { 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"], + }); + }); }); \ No newline at end of file diff --git a/test/service/git/gitlab/gitlab-client.test.ts b/test/service/git/gitlab/gitlab-client.test.ts index c4f4816..57aa125 100644 --- a/test/service/git/gitlab/gitlab-client.test.ts +++ b/test/service/git/gitlab/gitlab-client.test.ts @@ -305,7 +305,7 @@ describe("github service", () => { 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(1); + 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", @@ -315,10 +315,12 @@ describe("github service", () => { assignee_ids: [], })); expect(axiosInstanceSpy.get).toBeCalledTimes(0); - // FIXME - // expect(axiosInstanceSpy.put).toBeCalledTimes(1); // just comments - // expect(axiosInstanceSpy.put).toBeCalledWith("/projects/superuser%2Fbackporting-example/merge_requests/" + SECOND_NEW_GITLAB_MR_ID, { - // labels: "label1,label2", - // }); + + 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", + }); }); }); \ No newline at end of file diff --git a/test/service/runner/cli-github-runner.test.ts b/test/service/runner/cli-github-runner.test.ts index 3aa82ef..27c78aa 100644 --- a/test/service/runner/cli-github-runner.test.ts +++ b/test/service/runner/cli-github-runner.test.ts @@ -793,4 +793,51 @@ describe("cli runner", () => { } ); }); + + 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"], + } + ); + }); }); \ No newline at end of file diff --git a/test/service/runner/gha-github-runner.test.ts b/test/service/runner/gha-github-runner.test.ts index 1f412ba..44e11a3 100644 --- a/test/service/runner/gha-github-runner.test.ts +++ b/test/service/runner/gha-github-runner.test.ts @@ -554,4 +554,49 @@ describe("gha runner", () => { } ); }); + + 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"], + } + ); + }); }); \ No newline at end of file diff --git a/test/support/mock/git-client-mock-support.ts b/test/support/mock/git-client-mock-support.ts index 02597f7..e36db5e 100644 --- a/test/support/mock/git-client-mock-support.ts +++ b/test/support/mock/git-client-mock-support.ts @@ -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({