diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index a3ed397c64448c7c9b6d2494a29d050905d33b3c..860bcaf9ac6f0c5b4234ea4f86502ae3e8f80ba6 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -1170,6 +1170,16 @@ Example: } ``` +To enable custom managers you will need to add `custom.` prefix before their names + +Example: + +```json +{ + "enabledManagers": ["custom.regex"] +} +``` + For the full list of available managers, see the [Supported Managers](https://docs.renovatebot.com/modules/manager/#supported-managers) documentation. ## encrypted diff --git a/lib/config/migrations/custom/enabled-managers-migration.spec.ts b/lib/config/migrations/custom/enabled-managers-migration.spec.ts index 392018ad33c304cea9a64f3546465a8879be3114..4a14619aeac1cba4be3bca2cabd094ddbb6e089a 100644 --- a/lib/config/migrations/custom/enabled-managers-migration.spec.ts +++ b/lib/config/migrations/custom/enabled-managers-migration.spec.ts @@ -1,13 +1,29 @@ import { EnabledManagersMigration } from './enabled-managers-migration'; describe('config/migrations/custom/enabled-managers-migration', () => { - it('should replace yarn with npm', () => { + it('migrates', () => { expect(EnabledManagersMigration).toMigrate( { - enabledManagers: ['test1', 'yarn', 'test2'], + enabledManagers: ['test1', 'yarn', 'test2', 'regex', 'custom.regex'], }, { - enabledManagers: ['test1', 'npm', 'test2'], + enabledManagers: [ + 'test1', + 'npm', + 'test2', + 'custom.regex', + 'custom.regex', + ], + }, + ); + + // coverage + expect(EnabledManagersMigration).not.toMigrate( + { + enabledManagers: undefined, + }, + { + enabledManagers: undefined, }, ); }); diff --git a/lib/config/migrations/custom/enabled-managers-migration.ts b/lib/config/migrations/custom/enabled-managers-migration.ts index e5ee0d853900ef8c1d103303ffe1407e2c8d14be..f595ee42664f4fff753c12ed1ac9d259751f1687 100644 --- a/lib/config/migrations/custom/enabled-managers-migration.ts +++ b/lib/config/migrations/custom/enabled-managers-migration.ts @@ -5,11 +5,20 @@ export class EnabledManagersMigration extends AbstractMigration { override readonly propertyName = 'enabledManagers'; override run(value: unknown): void { - if (is.array(value)) { - const newValue = value.map((manager) => - manager === 'yarn' ? 'npm' : manager, - ); - this.rewrite(newValue); + if (!is.array<string>(value, is.string)) { + return; } + + const newValue = value.map((manager) => { + switch (manager) { + case 'yarn': + return 'npm'; + case 'regex': + return 'custom.regex'; + default: + return manager; + } + }); + this.rewrite(newValue); } } diff --git a/lib/config/validation.spec.ts b/lib/config/validation.spec.ts index 074fdee1ceeff736cf76e48c22d1d8edddd4a506..fb74dd9431ce1be6de9a96a52d840ff4fc7e300f 100644 --- a/lib/config/validation.spec.ts +++ b/lib/config/validation.spec.ts @@ -236,7 +236,7 @@ describe('config/validation', () => { [ 'multiple enabled managers', { - enabledManagers: ['npm', 'gradle', 'maven', 'regex'], + enabledManagers: ['npm', 'gradle', 'maven', 'custom.regex'], }, ], ])('validates enabled managers for %s', async (_case, config) => { diff --git a/lib/config/validation.ts b/lib/config/validation.ts index dfc4420d95b1570c4bd95956966a9a0bb6a0453c..7e928b23b66b5efddcc6e6033d74c9e4ec40b0b5 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -71,7 +71,7 @@ function validatePlainObject(val: Record<string, unknown>): true | string { function getUnsupportedEnabledManagers(enabledManagers: string[]): string[] { return enabledManagers.filter( - (manager) => !allManagersList.includes(manager), + (manager) => !allManagersList.includes(manager.replace('custom.', '')), ); } diff --git a/lib/modules/manager/custom/index.spec.ts b/lib/modules/manager/custom/index.spec.ts index 40332436ebd75ffdbbcd835af405807aa8be32f2..54e922bd1ec517d0179dff6b0138abcf444e2265 100644 --- a/lib/modules/manager/custom/index.spec.ts +++ b/lib/modules/manager/custom/index.spec.ts @@ -9,6 +9,7 @@ describe('modules/manager/custom/index', () => { it('works', () => { expect(customManager.isCustomManager('npm')).toBe(false); expect(customManager.isCustomManager('regex')).toBe(true); + expect(customManager.isCustomManager('custom.regex')).toBe(false); }); }); }); diff --git a/lib/modules/manager/index.spec.ts b/lib/modules/manager/index.spec.ts index f297c5f738107f2701644ab0078b5631d9ee9cad..a88e725fec72a740786a97d7aa7bb1a601866160 100644 --- a/lib/modules/manager/index.spec.ts +++ b/lib/modules/manager/index.spec.ts @@ -37,6 +37,16 @@ describe('modules/manager/index', () => { }); }); + describe('getEnabledManagersList()', () => { + it('works', () => { + expect(manager.getEnabledManagersList()).toEqual(manager.allManagersList); + expect(manager.getEnabledManagersList(['custom.regex', 'npm'])).toEqual([ + 'npm', + 'regex', + ]); + }); + }); + it('validates', () => { function validate(module: ManagerApi, moduleName: string): boolean { // no need to validate custom as it is a wrapper and not an actual manager diff --git a/lib/modules/manager/index.ts b/lib/modules/manager/index.ts index c5653ef9a140bf2368f9b0d31b40d683ecd85527..c1961df22eeb6129da701efa760bd9bb2dec32bc 100644 --- a/lib/modules/manager/index.ts +++ b/lib/modules/manager/index.ts @@ -103,3 +103,22 @@ export function getRangeStrategy(config: RangeConfig): RangeStrategy | null { return config.rangeStrategy; } + +/** + * Filter a list of managers based on enabled managers. + * + * If enabledManagers is provided, this function returns a subset of allManagersList + * that matches the enabled manager names, including custom managers. If enabledManagers + * is not provided or is an empty array, it returns the full list of managers. + */ +export function getEnabledManagersList(enabledManagers?: string[]): string[] { + if (enabledManagers?.length) { + return allManagersList.filter( + (manager) => + enabledManagers.includes(manager) || + enabledManagers.includes(`custom.${manager}`), + ); + } + + return allManagersList; +} diff --git a/lib/workers/repository/extract/extract-fingerprint-config.spec.ts b/lib/workers/repository/extract/extract-fingerprint-config.spec.ts index 685c799cb3f0fbabe3c6d6b4db14943e26af9eea..f6a7d3b92af9fe9d55d5f9421300d7ec04ddae00 100644 --- a/lib/workers/repository/extract/extract-fingerprint-config.spec.ts +++ b/lib/workers/repository/extract/extract-fingerprint-config.spec.ts @@ -19,7 +19,7 @@ describe('workers/repository/extract/extract-fingerprint-config', () => { notStable: 'http://some.link.2', }, }, - enabledManagers: ['npm', 'regex'], + enabledManagers: ['npm', 'custom.regex'], customManagers: [ { customType: 'regex', diff --git a/lib/workers/repository/extract/extract-fingerprint-config.ts b/lib/workers/repository/extract/extract-fingerprint-config.ts index be5cccd079b95e6539e5057385e2ca9715b7dc9a..8d1ad76c1431e933202141f75a3bb4ab000b9a25 100644 --- a/lib/workers/repository/extract/extract-fingerprint-config.ts +++ b/lib/workers/repository/extract/extract-fingerprint-config.ts @@ -1,6 +1,6 @@ import { getManagerConfig, mergeChildConfig } from '../../../config'; import type { RenovateConfig } from '../../../config/types'; -import { allManagersList } from '../../../modules/manager'; +import { getEnabledManagersList } from '../../../modules/manager'; import { isCustomManager } from '../../../modules/manager/custom'; import type { RegexManagerTemplates } from '../../../modules/manager/custom/regex/types'; import { validMatchFields } from '../../../modules/manager/custom/regex/utils'; @@ -55,13 +55,7 @@ export function generateFingerprintConfig( config: RenovateConfig, ): FingerprintExtractConfig { const managerExtractConfigs: WorkerExtractConfig[] = []; - let managerList: Set<string>; - const { enabledManagers } = config; - if (enabledManagers?.length) { - managerList = new Set(enabledManagers); - } else { - managerList = new Set(allManagersList); - } + const managerList = new Set(getEnabledManagersList(config.enabledManagers)); for (const manager of managerList) { const managerConfig = getManagerConfig(config, manager); diff --git a/lib/workers/repository/extract/index.spec.ts b/lib/workers/repository/extract/index.spec.ts index 5cdf1a9f1a880ba227c32af01690f182947b28c0..f769a214198a7669b984f35667019f95861d9142 100644 --- a/lib/workers/repository/extract/index.spec.ts +++ b/lib/workers/repository/extract/index.spec.ts @@ -42,10 +42,13 @@ describe('workers/repository/extract/index', () => { }); it('warns if no packages found for a enabled manager', async () => { - config.enabledManagers = ['npm']; + config.enabledManagers = ['npm', 'custom.regex']; managerFiles.getManagerPackageFiles.mockResolvedValue([]); expect((await extractAllDependencies(config)).packageFiles).toEqual({}); - expect(logger.debug).toHaveBeenCalled(); + expect(logger.debug).toHaveBeenCalledWith( + { manager: 'custom.regex' }, + `Manager explicitly enabled in "enabledManagers" config, but found no results. Possible config error?`, + ); }); it('warns if packageFiles is null', async () => { diff --git a/lib/workers/repository/extract/index.ts b/lib/workers/repository/extract/index.ts index 9216550726e5c372691ce647353c9f133a6aae42..8e0a71f7757e6ba50cd15b111300047a88c80701 100644 --- a/lib/workers/repository/extract/index.ts +++ b/lib/workers/repository/extract/index.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import { getManagerConfig, mergeChildConfig } from '../../../config'; import type { ManagerConfig, RenovateConfig } from '../../../config/types'; import { logger } from '../../../logger'; -import { allManagersList, hashMap } from '../../../modules/manager'; +import { getEnabledManagersList, hashMap } from '../../../modules/manager'; import { isCustomManager } from '../../../modules/manager/custom'; import { scm } from '../../../modules/platform/scm'; import type { ExtractResult, WorkerExtractConfig } from '../../types'; @@ -13,14 +13,7 @@ import { processSupersedesManagers } from './supersedes'; export async function extractAllDependencies( config: RenovateConfig, ): Promise<ExtractResult> { - let managerList = allManagersList; - const { enabledManagers } = config; - if (is.nonEmptyArray(enabledManagers)) { - logger.debug('Applying enabledManagers filtering'); - managerList = managerList.filter((manager) => - enabledManagers.includes(manager), - ); - } + const managerList = getEnabledManagersList(config.enabledManagers); const extractList: WorkerExtractConfig[] = []; const fileList = await scm.getFileList(); @@ -91,7 +84,9 @@ export async function extractAllDependencies( // If not, log a warning to indicate possible misconfiguration. if (is.nonEmptyArray(config.enabledManagers)) { for (const enabledManager of config.enabledManagers) { - if (!(enabledManager in extractResult.packageFiles)) { + if ( + !(enabledManager.replace('custom.', '') in extractResult.packageFiles) + ) { logger.debug( { manager: enabledManager }, `Manager explicitly enabled in "enabledManagers" config, but found no results. Possible config error?`,