From ea816f8ff06ebaf03ffecfa171bab8cfe50cd14d Mon Sep 17 00:00:00 2001
From: Philip <42116482+PhilipAbed@users.noreply.github.com>
Date: Thu, 31 Oct 2024 11:42:49 +0200
Subject: [PATCH] feat(config): rebaseWhen = automerging (#31527)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-authored-by: Nabeel Saabna <48175656+nabeelsaabna@users.noreply.github.com>
---
 docs/usage/configuration-options.md           |  1 +
 lib/config/options/index.ts                   |  8 +++-
 .../repository/update/branch/reuse.spec.ts    | 37 +++++++++++++++++++
 lib/workers/repository/update/branch/reuse.ts | 12 +++---
 4 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index 9dcf5c6fe2..fa203a61a3 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -3628,6 +3628,7 @@ By default this label is `"rebase"` but you can configure it to anything you wan
 Possible values and meanings:
 
 - `auto`: Renovate will autodetect the best setting. It will use `behind-base-branch` if configured to automerge or repository has been set to require PRs to be up to date. Otherwise, `conflicted` will be used instead
+- `automerging`: Renovate will use `behind-base-branch` if configured to automerge, Otherwise, `never` will be used instead
 - `never`: Renovate will never rebase the branch or update it unless manually requested
 - `conflicted`: Renovate will rebase only if the branch is conflicted
 - `behind-base-branch`: Renovate will rebase whenever the branch falls 1 or more commit behind its base branch
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index fc73f619c5..515e245c88 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -1813,7 +1813,13 @@ const options: RenovateOptions[] = [
     name: 'rebaseWhen',
     description: 'Controls when Renovate rebases an existing branch.',
     type: 'string',
-    allowedValues: ['auto', 'never', 'conflicted', 'behind-base-branch'],
+    allowedValues: [
+      'auto',
+      'never',
+      'conflicted',
+      'behind-base-branch',
+      'automerging',
+    ],
     default: 'auto',
   },
   {
diff --git a/lib/workers/repository/update/branch/reuse.spec.ts b/lib/workers/repository/update/branch/reuse.spec.ts
index d5113d962a..979278e089 100644
--- a/lib/workers/repository/update/branch/reuse.spec.ts
+++ b/lib/workers/repository/update/branch/reuse.spec.ts
@@ -263,6 +263,43 @@ describe('workers/repository/update/branch/reuse', () => {
       expect(result.rebaseWhen).toBe('conflicted');
     });
 
+    it('converts rebaseWhen=automerging to behind-base-branch', async () => {
+      config.rebaseWhen = 'automerging';
+      config.automerge = true;
+      scm.branchExists.mockResolvedValueOnce(true);
+      scm.isBranchBehindBase.mockResolvedValueOnce(false);
+
+      const result = await shouldReuseExistingBranch(config);
+
+      expect(config.rebaseWhen).toBe('automerging');
+      expect(result.rebaseWhen).toBe('behind-base-branch');
+    });
+
+    it('converts rebaseWhen=automerging to behind-base-branch if keep-updated', async () => {
+      config.rebaseWhen = 'automerging';
+      config.keepUpdatedLabel = 'keep-updated';
+      config.automerge = false;
+      scm.branchExists.mockResolvedValueOnce(true);
+      scm.isBranchBehindBase.mockResolvedValueOnce(false);
+      platform.getBranchPr.mockResolvedValueOnce(pr);
+
+      const result = await shouldReuseExistingBranch(config);
+
+      expect(config.rebaseWhen).toBe('automerging');
+      expect(result.rebaseWhen).toBe('behind-base-branch');
+    });
+
+    it('converts rebaseWhen=automerging to never', async () => {
+      config.rebaseWhen = 'automerging';
+      scm.branchExists.mockResolvedValueOnce(true);
+      scm.isBranchBehindBase.mockResolvedValueOnce(false);
+
+      const result = await shouldReuseExistingBranch(config);
+
+      expect(config.rebaseWhen).toBe('automerging');
+      expect(result.rebaseWhen).toBe('never');
+    });
+
     it('converts rebaseWhen=auto to behind-base-branch if automerge is true AND branch is new', async () => {
       config.rebaseWhen = 'auto';
       config.automerge = true;
diff --git a/lib/workers/repository/update/branch/reuse.ts b/lib/workers/repository/update/branch/reuse.ts
index 7b052eeebf..b779727d2b 100644
--- a/lib/workers/repository/update/branch/reuse.ts
+++ b/lib/workers/repository/update/branch/reuse.ts
@@ -113,7 +113,7 @@ export async function shouldReuseExistingBranch(
 }
 
 /**
- * This method updates rebaseWhen value when it's set to auto(default)
+ * This method updates rebaseWhen value when it's set to auto(default) or automerging
  *
  * @param result BranchConfig
  * @param keepUpdated boolean
@@ -122,16 +122,18 @@ async function determineRebaseWhenValue(
   result: BranchConfig,
   keepUpdated: boolean,
 ): Promise<void> {
-  if (result.rebaseWhen === 'auto') {
+  if (result.rebaseWhen === 'auto' || result.rebaseWhen === 'automerging') {
     let reason;
-
     let newValue = 'behind-base-branch';
     if (result.automerge === true) {
       reason = 'automerge=true';
-    } else if (await platform.getBranchForceRebase?.(result.baseBranch)) {
-      reason = 'platform is configured to require up-to-date branches';
     } else if (keepUpdated) {
       reason = 'keep-updated label is set';
+    } else if (result.rebaseWhen === 'automerging') {
+      newValue = 'never';
+      reason = 'no keep-updated label and automerging is set';
+    } else if (await platform.getBranchForceRebase?.(result.baseBranch)) {
+      reason = 'platform is configured to require up-to-date branches';
     } else {
       newValue = 'conflicted';
       reason = 'no rule for behind-base-branch applies';
-- 
GitLab