diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 2284f7b6824145a50fa46b69e70ea094d8dc2788..2155e6dd28dc50a9eb9919d9acfeefdf46b7e3c2 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2080,6 +2080,11 @@ Here's an example of how you would define PR priority so that devDependencies ar The PR title is important for some of Renovate's matching algorithms (e.g. determining whether to recreate a PR or not) so ideally don't modify it much. +## pruneBranchAfterAutomerge + +By default Renovate deletes, or "prunes", the branch after automerging. +Set `pruneBranchAfterAutomerge` to `false` to keep the branch after automerging. + ## pruneStaleBranches Configure to `false` to disable deleting orphan branches and autoclosing PRs. diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 757ad222ec1d46044c710ca70aa9aa7b15407f51..09b01bdec95364c6688d526c93a3e5493137453b 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -1499,6 +1499,12 @@ const options: RenovateOptions[] = [ env: false, supportedPlatforms: ['github'], }, + { + name: 'pruneBranchAfterAutomerge', + description: 'Set to `true` to enable branch pruning after automerging.', + type: 'boolean', + default: true, + }, // Default templates { name: 'branchName', diff --git a/lib/config/types.ts b/lib/config/types.ts index 3191acdd83c66363d30dfac8fa8e68c5d5cfde03..bd1dfa9efd7953e4eb2b5b876a8a1118a0e66644 100644 --- a/lib/config/types.ts +++ b/lib/config/types.ts @@ -23,6 +23,7 @@ export interface RenovateSharedConfig { $schema?: string; automerge?: boolean; automergeStrategy?: MergeStrategy; + pruneBranchAfterAutomerge?: boolean; branchPrefix?: string; branchName?: string; manager?: string; diff --git a/lib/workers/repository/update/pr/automerge.spec.ts b/lib/workers/repository/update/pr/automerge.spec.ts index b5160535a3d02557ed7383748fb51b175dc7afcd..adf095f1a2fb064d156da5002c29648f486a09df 100644 --- a/lib/workers/repository/update/pr/automerge.spec.ts +++ b/lib/workers/repository/update/pr/automerge.spec.ts @@ -28,6 +28,7 @@ describe('workers/repository/update/pr/automerge', () => { it('should automerge if enabled and pr is mergeable', async () => { config.automerge = true; + config.pruneBranchAfterAutomerge = true; platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); platform.mergePr.mockResolvedValueOnce(true); const res = await prAutomerge.checkAutoMerge(pr, config); @@ -72,6 +73,16 @@ describe('workers/repository/update/pr/automerge', () => { expect(platform.ensureComment).toHaveBeenCalledTimes(1); }); + it('should skip branch deletion after automerge if prune is disabled', async () => { + config.automerge = true; + config.pruneBranchAfterAutomerge = false; + platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); + platform.mergePr.mockResolvedValueOnce(true); + const res = await prAutomerge.checkAutoMerge(pr, config); + expect(res).toEqual({ automerged: true, branchRemoved: false }); + expect(platform.mergePr).toHaveBeenCalledTimes(1); + }); + it('should not automerge if enabled and pr is mergeable but cannot rebase', async () => { config.automerge = true; platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green); diff --git a/lib/workers/repository/update/pr/automerge.ts b/lib/workers/repository/update/pr/automerge.ts index 001a433c093ab6d59e58c7cc607fded740c0b023..d26a635cf7598616e91fb8a63d4ba45844d1d749 100644 --- a/lib/workers/repository/update/pr/automerge.ts +++ b/lib/workers/repository/update/pr/automerge.ts @@ -39,6 +39,7 @@ export async function checkAutoMerge( branchName, automergeType, automergeStrategy, + pruneBranchAfterAutomerge, automergeComment, ignoreTests, rebaseRequested, @@ -129,6 +130,10 @@ export async function checkAutoMerge( }); if (res) { logger.info({ pr: pr.number, prTitle: pr.title }, 'PR automerged'); + if (!pruneBranchAfterAutomerge) { + logger.info('Skipping pruning of merged branch'); + return { automerged: true, branchRemoved: false }; + } let branchRemoved = false; try { await deleteBranch(branchName);