From a0a770338f3d57205044656c2a58dd56d5c4aa21 Mon Sep 17 00:00:00 2001
From: Sebastian Poxhofer <secustor@users.noreply.github.com>
Date: Thu, 16 Dec 2021 16:12:35 +0100
Subject: [PATCH] feat(autodiscover): allow array for autodiscoverfilter
 (#13100)

---
 docs/usage/self-hosted-configuration.md |  2 +-
 lib/config/options/index.ts             |  4 +++-
 lib/config/types.ts                     |  2 +-
 lib/workers/global/autodiscover.spec.ts | 25 +++++++++++++++++++++----
 lib/workers/global/autodiscover.ts      | 10 +++++++++-
 lib/workers/global/config/parse/env.ts  |  3 ++-
 lib/workers/global/config/parse/file.ts |  3 ++-
 7 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md
index b1b8a67bd3..0971b51cb3 100644
--- a/docs/usage/self-hosted-configuration.md
+++ b/docs/usage/self-hosted-configuration.md
@@ -85,7 +85,7 @@ e.g.
 
 ```json
 {
-  "autodiscoverFilter": "project/*"
+  "autodiscoverFilter": ["project/*"]
 }
 ```
 
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index 84b34978c2..885ed89e86 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -668,7 +668,9 @@ const options: RenovateOptions[] = [
     name: 'autodiscoverFilter',
     description: 'Filter the list of autodiscovered repositories.',
     stage: 'global',
-    type: 'string',
+    type: 'array',
+    subType: 'string',
+    allowString: true,
     default: null,
   },
   {
diff --git a/lib/config/types.ts b/lib/config/types.ts
index cd4e2e32ae..151f9de951 100644
--- a/lib/config/types.ts
+++ b/lib/config/types.ts
@@ -72,7 +72,7 @@ export interface RenovateSharedConfig {
 // The below should contain config options where stage=global
 export interface GlobalOnlyConfig {
   autodiscover?: boolean;
-  autodiscoverFilter?: string;
+  autodiscoverFilter?: string[];
   baseDir?: string;
   cacheDir?: string;
   detectHostRulesFromEnv?: boolean;
diff --git a/lib/workers/global/autodiscover.spec.ts b/lib/workers/global/autodiscover.spec.ts
index 076d179cc3..e3953c3437 100644
--- a/lib/workers/global/autodiscover.spec.ts
+++ b/lib/workers/global/autodiscover.spec.ts
@@ -1,4 +1,4 @@
-import type { RenovateConfig } from '../../config/types';
+import type { AllConfig } from '../../config/types';
 import { PlatformId } from '../../constants';
 import * as platform from '../../platform';
 import * as _ghApi from '../../platform/github';
@@ -13,7 +13,7 @@ const hostRules = _hostRules;
 const ghApi: jest.Mocked<typeof _ghApi> = _ghApi as never;
 
 describe('workers/global/autodiscover', () => {
-  let config: RenovateConfig;
+  let config: AllConfig;
   beforeEach(async () => {
     jest.resetAllMocks();
     config = {};
@@ -48,7 +48,7 @@ describe('workers/global/autodiscover', () => {
   });
   it('filters autodiscovered github repos', async () => {
     config.autodiscover = true;
-    config.autodiscoverFilter = 'project/re*';
+    config.autodiscoverFilter = ['project/re*'];
     config.platform = PlatformId.Github;
     hostRules.find = jest.fn(() => ({
       token: 'abc',
@@ -61,7 +61,7 @@ describe('workers/global/autodiscover', () => {
   });
   it('filters autodiscovered github repos but nothing matches', async () => {
     config.autodiscover = true;
-    config.autodiscoverFilter = 'project/re*';
+    config.autodiscoverFilter = ['project/re*'];
     config.platform = 'github';
     hostRules.find = jest.fn(() => ({
       token: 'abc',
@@ -72,4 +72,21 @@ describe('workers/global/autodiscover', () => {
     const res = await autodiscoverRepositories(config);
     expect(res).toEqual(config);
   });
+  it('filters autodiscovered github repos with multiple values', async () => {
+    config.autodiscover = true;
+    config.autodiscoverFilter = ['another-project/re*', 'department/dev/*'];
+    config.platform = 'github';
+    hostRules.find = jest.fn(() => ({
+      token: 'abc',
+    }));
+    const expectedRepositories = [
+      'another-project/repo',
+      'department/dev/aProject',
+    ];
+    ghApi.getRepos = jest.fn(() =>
+      Promise.resolve(['another-project/another-repo', ...expectedRepositories])
+    );
+    const res = await autodiscoverRepositories(config);
+    expect(res.repositories).toEqual(expectedRepositories);
+  });
 });
diff --git a/lib/workers/global/autodiscover.ts b/lib/workers/global/autodiscover.ts
index 03b66b293a..128d7bb0d6 100644
--- a/lib/workers/global/autodiscover.ts
+++ b/lib/workers/global/autodiscover.ts
@@ -30,7 +30,15 @@ export async function autodiscoverRepositories(
     return config;
   }
   if (config.autodiscoverFilter) {
-    discovered = discovered.filter(minimatch.filter(config.autodiscoverFilter));
+    const matched = new Set<string>();
+    for (const filter of config.autodiscoverFilter) {
+      const res = minimatch.match(discovered, filter);
+      for (const repository of res) {
+        matched.add(repository);
+      }
+    }
+    discovered = [...matched];
+
     if (!discovered.length) {
       // Soft fail (no error thrown) if no accessible repositories match the filter
       logger.debug('None of the discovered repositories matched the filter');
diff --git a/lib/workers/global/config/parse/env.ts b/lib/workers/global/config/parse/env.ts
index ca96985431..d747f113f3 100644
--- a/lib/workers/global/config/parse/env.ts
+++ b/lib/workers/global/config/parse/env.ts
@@ -1,4 +1,5 @@
 import is from '@sindresorhus/is';
+import { massageConfig } from '../../../../config/massage';
 import { getOptions } from '../../../../config/options';
 import type { AllConfig, RenovateOptions } from '../../../../config/types';
 import { PlatformId } from '../../../../constants';
@@ -132,5 +133,5 @@ export function getConfig(inputEnv: NodeJS.ProcessEnv): AllConfig {
 
   unsupportedEnv.forEach((val) => delete env[val]);
 
-  return config;
+  return massageConfig(config);
 }
diff --git a/lib/workers/global/config/parse/file.ts b/lib/workers/global/config/parse/file.ts
index 24a0e31df7..aa738acc72 100644
--- a/lib/workers/global/config/parse/file.ts
+++ b/lib/workers/global/config/parse/file.ts
@@ -2,6 +2,7 @@ import is from 'is';
 import { load } from 'js-yaml';
 import JSON5 from 'json5';
 import upath from 'upath';
+import { massageConfig } from '../../../../config/massage';
 import { migrateConfig } from '../../../../config/migration';
 import type { AllConfig, RenovateConfig } from '../../../../config/types';
 import { logger } from '../../../../logger';
@@ -64,5 +65,5 @@ export async function getConfig(env: NodeJS.ProcessEnv): Promise<AllConfig> {
     );
     config = migratedConfig;
   }
-  return config;
+  return massageConfig(config);
 }
-- 
GitLab