From d723d78f1cbfa310b35f084c3da42e4da2bbbc73 Mon Sep 17 00:00:00 2001
From: marcovmun <16606883+marcovmun@users.noreply.github.com>
Date: Wed, 5 Jan 2022 08:53:53 +0100
Subject: [PATCH] feat(matchBaseBranches): Support regex expression (#13322)

---
 docs/usage/configuration-options.md | 14 ++++++++++++
 lib/config/options/index.ts         |  2 +-
 lib/util/package-rules.spec.ts      | 35 +++++++++++++++++++++++++++++
 lib/util/package-rules.ts           |  9 +++++++-
 4 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index 5e98e7db6d..f423844643 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -1489,6 +1489,20 @@ Use this field to restrict rules to a particular branch. e.g.
 }
 ```
 
+This field also supports Regular Expressions if they begin and end with `/`. e.g.
+
+```json
+{
+  "packageRules": [
+    {
+      "matchBaseBranches": ["/^release\\/.*/"],
+      "excludePackagePatterns": ["^eslint"],
+      "enabled": false
+    }
+  ]
+}
+```
+
 ### matchManagers
 
 Use this field to restrict rules to a particular package manager. e.g.
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index c4bff82781..5b966d52df 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -852,7 +852,7 @@ const options: RenovateOptions[] = [
   {
     name: 'matchBaseBranches',
     description:
-      'List of branches to match (e.g. ["master"]). Valid only within `packageRules` object.',
+      'List of strings containing exact matches (e.g. `["main"]`) and/or regex expressions (e.g. `["/^release\\/.*/"]`). Valid only within `packageRules` object.',
     type: 'array',
     subType: 'string',
     allowString: true,
diff --git a/lib/util/package-rules.spec.ts b/lib/util/package-rules.spec.ts
index 2d8d0d2226..c39a6e7cae 100644
--- a/lib/util/package-rules.spec.ts
+++ b/lib/util/package-rules.spec.ts
@@ -381,6 +381,41 @@ describe('util/package-rules', () => {
     const res = applyPackageRules({ ...config, ...dep });
     expect(res.x).toBeUndefined();
   });
+  it('filters branches with matching branch regex', () => {
+    const config: TestConfig = {
+      packageRules: [
+        {
+          matchBaseBranches: ['/^release\\/.*/'],
+          x: 1,
+        },
+      ],
+    };
+    const dep = {
+      depType: 'dependencies',
+      datasource: OrbDatasource.id,
+      baseBranch: 'release/5.8',
+    };
+    const res = applyPackageRules({ ...config, ...dep });
+    expect(res.x).toBe(1);
+  });
+
+  it('filters branches with non-matching branch regex', () => {
+    const config: TestConfig = {
+      packageRules: [
+        {
+          matchBaseBranches: ['/^release\\/.*/'],
+          x: 1,
+        },
+      ],
+    };
+    const dep = {
+      depType: 'dependencies',
+      datasource: OrbDatasource.id,
+      baseBranch: 'master',
+    };
+    const res = applyPackageRules({ ...config, ...dep });
+    expect(res.x).toBeUndefined();
+  });
   it('filters updateType', () => {
     const config: TestConfig = {
       packageRules: [
diff --git a/lib/util/package-rules.ts b/lib/util/package-rules.ts
index 92228a94fc..b951688a66 100644
--- a/lib/util/package-rules.ts
+++ b/lib/util/package-rules.ts
@@ -100,7 +100,14 @@ function matchesRule(
     positiveMatch = true;
   }
   if (matchBaseBranches.length) {
-    const isMatch = matchBaseBranches.includes(baseBranch);
+    const isMatch = matchBaseBranches.some((matchBaseBranch): boolean => {
+      const isAllowedPred = configRegexPredicate(matchBaseBranch);
+      if (isAllowedPred) {
+        return isAllowedPred(baseBranch);
+      }
+      return matchBaseBranch === baseBranch;
+    });
+
     if (!isMatch) {
       return false;
     }
-- 
GitLab