From 0baf729413a6b3a76b3f10dc798f7bcc4e126954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 19 Sep 2023 22:36:19 +0200 Subject: [PATCH] Make the backport branch name used configurable (#478) --- docs/cli-options.md | 1 + docs/config-file-options.md | 21 ++++++++++++++ .../cherrypickAndCreateTargetPullRequest.ts | 6 +++- .../getBackportBranchName.test.ts | 29 +++++++++++++++++++ .../getBackportBranchName.ts | 23 +++++++++++++-- src/options/ConfigOptions.ts | 1 + src/options/cliArgs.ts | 5 ++++ src/options/options.ts | 1 + .../e2e/cli/entrypoint.cli.private.test.ts | 2 ++ 9 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.test.ts diff --git a/docs/cli-options.md b/docs/cli-options.md index cc916ec2..e33ab341 100644 --- a/docs/cli-options.md +++ b/docs/cli-options.md @@ -40,6 +40,7 @@ The CLI options will override the [config-file-options.md](/docs/config-file-opt | --signoff | -s | Pass the --signoff option to the cherry-pick command | false | | --copySourcePRLabels | | Copy labels from source PR to the target PR | false | | --copySourcePRReviewers | | Copy reviewers from source PR to the target PR | false | +| --backportBranchName | | Name template to use for the branch name of the backport | | | --source-branch | | Specify a non-default branch to backport from | | | --source-pr-label | | Labels added to the source PR | | | --target-branch | -b | Target branch(es) to backport to | | diff --git a/docs/config-file-options.md b/docs/config-file-options.md index f2d84a35..2e24991e 100644 --- a/docs/config-file-options.md +++ b/docs/config-file-options.md @@ -518,3 +518,24 @@ Labels that will be added to the target (backport) pull request. This can be use "targetPRLabels": ["backport", "apm-team"] } ``` + +#### `backportBranchName` + +Branch name to use for the backport PR +Template values: + +- `{{targetBranch}}`: Branch the backport PR will be targeting +- `{{sourcePullRequest}}`: Original pull request object (see [interface](https://github.com/sqren/backport/blob/9e42503a7d0e06e60c575ed2c3b7dc3e5df0dd5c/src/lib/sourceCommit/parseSourceCommit.ts#L23-L31)) +- `{{refValues}}`: Name representing the original commit/PR, `commit-` or `pr-` respectively. + +Default: `backport/{{targetBranch}}/{{refValues}}` + +**Example** + +```json +{ + "backportBranchName": "{{targetBranch}}-{{refValues}}-backport" +} +``` + +See [source code](https://github.com/sqren/backport/blob/main/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.ts#L14). diff --git a/src/lib/cherrypickAndCreateTargetPullRequest/cherrypickAndCreateTargetPullRequest.ts b/src/lib/cherrypickAndCreateTargetPullRequest/cherrypickAndCreateTargetPullRequest.ts index 490e1cf5..da9095ab 100644 --- a/src/lib/cherrypickAndCreateTargetPullRequest/cherrypickAndCreateTargetPullRequest.ts +++ b/src/lib/cherrypickAndCreateTargetPullRequest/cherrypickAndCreateTargetPullRequest.ts @@ -38,7 +38,11 @@ export async function cherrypickAndCreateTargetPullRequest({ commits: Commit[]; targetBranch: string; }): Promise<{ url: string; number: number; didUpdate: boolean }> { - const backportBranch = getBackportBranchName(targetBranch, commits); + const backportBranch = getBackportBranchName({ + options, + targetBranch, + commits, + }); const repoForkOwner = getRepoForkOwner(options); consoleLog(`\n${chalk.bold(`Backporting to ${targetBranch}:`)}`); diff --git a/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.test.ts b/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.test.ts new file mode 100644 index 00000000..ccb0b452 --- /dev/null +++ b/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.test.ts @@ -0,0 +1,29 @@ +import { Commit } from '../../entrypoint.api'; +import { ValidConfigOptions } from '../../options/options'; +import { getBackportBranchName } from './getBackportBranchName'; + +const commit = { sourcePullRequest: { number: 1234 } } as Commit; + +describe('getBackportBranchName', () => { + it('returns the default name', () => { + const name = getBackportBranchName({ + options: { + backportBranchName: undefined, + } as ValidConfigOptions, + targetBranch: '7.x', + commits: [commit], + }); + expect(name).toBe('backport/7.x/pr-1234'); + }); + + it('returns a custom name', () => { + const name = getBackportBranchName({ + options: { + backportBranchName: 'bp/pull-{{sourcePullRequest.number}}', + } as ValidConfigOptions, + targetBranch: '7.x', + commits: [commit], + }); + expect(name).toBe('bp/pull-1234'); + }); +}); diff --git a/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.ts b/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.ts index 07068576..48b2135a 100644 --- a/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.ts +++ b/src/lib/cherrypickAndCreateTargetPullRequest/getBackportBranchName.ts @@ -1,4 +1,6 @@ +import Handlebars from 'handlebars'; import { Commit } from '../../entrypoint.api'; +import { ValidConfigOptions } from '../../options/options'; import { getShortSha } from '../github/commitFormatters'; /* @@ -9,7 +11,15 @@ import { getShortSha } from '../github/commitFormatters'; * For a single commit: `backport/7.x/commit-abcdef` * For multiple: `backport/7.x/pr-1234_commit-abcdef` */ -export function getBackportBranchName(targetBranch: string, commits: Commit[]) { +export function getBackportBranchName({ + options, + targetBranch, + commits, +}: { + options: ValidConfigOptions; + targetBranch: string; + commits: Commit[]; +}) { const refValues = commits .map((commit) => commit.sourcePullRequest @@ -18,5 +28,14 @@ export function getBackportBranchName(targetBranch: string, commits: Commit[]) { ) .join('_') .slice(0, 200); - return `backport/${targetBranch}/${refValues}`; + const defaultBackportBranchName = 'backport/{{targetBranch}}/{{refValues}}'; + const template = Handlebars.compile( + options.backportBranchName ?? defaultBackportBranchName, + ); + + return template({ + sourcePullRequest: commits[0].sourcePullRequest, // assume that all commits are from the same PR + targetBranch, + refValues, + }); } diff --git a/src/options/ConfigOptions.ts b/src/options/ConfigOptions.ts index 92b8fde2..a94a1e32 100644 --- a/src/options/ConfigOptions.ts +++ b/src/options/ConfigOptions.ts @@ -27,6 +27,7 @@ type Options = Partial<{ autoMerge: boolean; autoMergeMethod: string; backportBinary: string; + backportBranchName: string; cherrypickRef: boolean; commitConflicts: boolean; commitPaths: string[]; diff --git a/src/options/cliArgs.ts b/src/options/cliArgs.ts index 587a3322..11f7db58 100644 --- a/src/options/cliArgs.ts +++ b/src/options/cliArgs.ts @@ -405,6 +405,11 @@ export function getOptionsFromCliArgs(processArgs: readonly string[]) { string: true, }) + .option('backportBranchName', { + description: 'Name template to use for the branch name of the backport', + type: 'string', + }) + // cli-only .option('verify', { description: `Opposite of no-verify`, diff --git a/src/options/options.ts b/src/options/options.ts index 26e0e818..ed139ea7 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -178,6 +178,7 @@ function throwForRequiredOptions( 'author', 'autoMergeMethod', 'backportBinary', + 'backportBranchName', 'dir', 'editor', 'gitHostname', diff --git a/src/test/e2e/cli/entrypoint.cli.private.test.ts b/src/test/e2e/cli/entrypoint.cli.private.test.ts index 3930bc08..b858e964 100644 --- a/src/test/e2e/cli/entrypoint.cli.private.test.ts +++ b/src/test/e2e/cli/entrypoint.cli.private.test.ts @@ -121,6 +121,8 @@ Options: -b, --targetBranch, --branch Branch(es) to backport to [array] --targetBranchChoice List branches to backport to [array] -l, --targetPRLabel, --label Add labels to the target (backport) PR [array] + --backportBranchName Name template to use for the branch name of + the backport [string] --verify Opposite of no-verify [boolean] --help Show help [boolean]