UNPKG

backport

Version:

A CLI tool that automates the process of backporting commits

115 lines 5.31 kB
/** Per-branch backport: cherry-pick commits, resolve conflicts, create target PR, add labels/assignees/reviewers. */ import chalk from 'chalk'; import { flatten } from 'lodash-es'; import { getSourceBranchFromCommits } from '../get-source-branch-from-commits.js'; import { createBackportBranch, deleteBackportBranch, pushBackportBranch, getRepoForkOwner, } from '../git/index.js'; import { addAssigneesToPullRequest } from '../github/v3/add-assignees-to-pull-request.js'; import { addLabelsToPullRequest } from '../github/v3/add-labels-to-pull-request.js'; import { addReviewersToPullRequest } from '../github/v3/add-reviewers-to-pull-request.js'; import { createPullRequest } from '../github/v3/create-pull-request/create-pull-request.js'; import { getPullRequestBody } from '../github/v3/create-pull-request/get-pull-request-body.js'; import { getTitle } from '../github/v3/create-pull-request/get-title.js'; import { validateTargetBranch } from '../github/v4/validate-target-branch.js'; import { consoleLog } from '../logger.js'; import { sequentially } from '../sequential-helper.js'; import { autoMergeNowOrLater } from './auto-merge-now-or-later.js'; import { copySourcePullRequestReviewersToTargetPullRequest } from './copy-source-pull-request-reviewers-to-target-pull-request.js'; import { getBackportBranchName } from './get-backport-branch-name.js'; import { getMergeCommits } from './get-merge-commit.js'; import { getTargetPRLabels } from './getTargetPRLabels/get-target-prlabels.js'; import { waitForCherrypick } from './wait-for-cherrypick.js'; export async function cherrypickAndCreateTargetPullRequest({ options, commits, targetBranch, }) { const backportBranch = getBackportBranchName({ options, targetBranch, commits, }); const repoForkOwner = getRepoForkOwner(options); consoleLog(`\n${chalk.bold(`Backporting to ${targetBranch}:`)}`); await validateTargetBranch({ ...options, branchName: targetBranch }); await createBackportBranch({ options, sourceBranch: getSourceBranchFromCommits(commits), targetBranch, backportBranch, }); const commitsFlattened = flatten(await Promise.all(commits.map((c) => getMergeCommits(options, c)))); const cherrypickResults = await sequentially(commitsFlattened, (commit) => waitForCherrypick(options, commit, targetBranch)); const hasAnyCommitWithConflicts = cherrypickResults.some((r) => r.hasCommitsWithConflicts); const unresolvedFiles = cherrypickResults.flatMap((r) => r.unresolvedFiles); if (!options.dryRun) { await pushBackportBranch({ options, backportBranch }); await deleteBackportBranch({ options, backportBranch }); } const prPayload = { owner: options.repoOwner, repo: options.repoName, title: getTitle({ options, commits, targetBranch }), body: getPullRequestBody({ options, commits, targetBranch, hasAnyCommitWithConflicts, unresolvedFiles, }), head: `${repoForkOwner}:${backportBranch}`, // eg. sorenlouv:backport/7.x/pr-75007 base: targetBranch, // eg. 7.x draft: options.draft, }; const targetPullRequest = await createPullRequest({ options, prPayload }); // add assignees to target pull request const assignees = options.autoAssign ? [options.authenticatedUsername] : options.assignees; if (assignees.length > 0) { await addAssigneesToPullRequest({ ...options, pullNumber: targetPullRequest.number, assignees, }); } // add reviewers to target pull request if (options.reviewers.length > 0) { await addReviewersToPullRequest({ ...options, pullNumber: targetPullRequest.number, reviewers: options.reviewers, }); } // add reviewers of the original PRs to the target pull request if (options.copySourcePRReviewers) { await copySourcePullRequestReviewersToTargetPullRequest(options, commits, targetPullRequest.number); } const targetPRLabels = getTargetPRLabels({ interactive: options.interactive, targetPRLabels: options.targetPRLabels, copySourcePRLabels: options.copySourcePRLabels, commits, targetBranch, }); // add labels to target pull request if (targetPRLabels.length > 0) { await addLabelsToPullRequest({ ...options, pullNumber: targetPullRequest.number, labels: targetPRLabels, }); } // make PR auto mergable if (options.autoMerge && !hasAnyCommitWithConflicts) { await autoMergeNowOrLater(options, targetPullRequest.number); } // add labels to source pull requests if (options.sourcePRLabels.length > 0) { await Promise.all(commits .filter((commit) => commit.sourcePullRequest) .map((commit) => addLabelsToPullRequest({ ...options, pullNumber: commit.sourcePullRequest.number, labels: options.sourcePRLabels, }))); } consoleLog(`View pull request: ${targetPullRequest.url}`); return targetPullRequest; } //# sourceMappingURL=cherrypick-and-create-target-pull-request.js.map