diff --git a/lib/config/migration.ts b/lib/config/migration.ts index fed7d7ffd750f6a992a0fdb08a9607d06c693e67..7699283c9242136c53960460228f6e9dfd9aad02 100644 --- a/lib/config/migration.ts +++ b/lib/config/migration.ts @@ -3,10 +3,8 @@ import { dequal } from 'dequal'; import { logger } from '../logger'; import { clone } from '../util/clone'; import { regEx } from '../util/regex'; -import { GlobalConfig } from './global'; import { MigrationsService } from './migrations'; import { getOptions } from './options'; -import { removedPresets } from './presets/common'; import type { MigratedConfig, MigratedRenovateConfig, @@ -43,7 +41,6 @@ export function migrateConfig( 'optionalDependencies', 'peerDependencies', ]; - const { migratePresets } = GlobalConfig.get(); for (const [key, val] of Object.entries(newConfig)) { if (key === 'matchStrings' && is.array(val)) { migratedConfig.matchStrings = val @@ -139,28 +136,6 @@ export function migrateConfig( } else { migratedConfig.semanticCommitScope = null; } - } else if ( - key === 'extends' && - (is.array<string>(val) || is.string(val)) - ) { - if (is.string(migratedConfig.extends)) { - migratedConfig.extends = [migratedConfig.extends]; - } - const presets = migratedConfig.extends; - for (let i = 0; i < presets.length; i += 1) { - const preset = presets[i]; - if (is.string(preset)) { - let newPreset = removedPresets[preset]; - if (newPreset !== undefined) { - presets[i] = newPreset; - } - newPreset = migratePresets?.[preset]; - if (newPreset !== undefined) { - presets[i] = newPreset; - } - } - } - migratedConfig.extends = migratedConfig.extends.filter(Boolean); } else if (key === 'separateMajorReleases') { delete migratedConfig.separateMultipleMajor; migratedConfig.separateMajorMinor = val; diff --git a/lib/config/migrations/custom/extends-migration.spec.ts b/lib/config/migrations/custom/extends-migration.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..33dbe7faeda63a8219c2374a96d3c4f8c3f9f1ea --- /dev/null +++ b/lib/config/migrations/custom/extends-migration.spec.ts @@ -0,0 +1,75 @@ +import { GlobalConfig } from '../../global'; +import { ExtendsMigration } from './extends-migration'; + +describe('config/migrations/custom/extends-migration', () => { + it('it migrates preset strings to array', () => { + expect(ExtendsMigration).toMigrate( + { + extends: ':js-app', + } as any, + { + extends: ['config:js-app'], + } + ); + + expect(ExtendsMigration).toMigrate( + { + extends: 'foo', + } as any, + { + extends: ['foo'], + } + ); + }); + + it('it migrates presets array', () => { + expect(ExtendsMigration).toMigrate( + { + extends: ['foo', ':js-app', 'bar'], + }, + { + extends: ['foo', 'config:js-app', 'bar'], + } + ); + }); + + it('should remove non string values', () => { + expect(ExtendsMigration).toMigrate( + { + extends: [{}], + } as any, + { + extends: [], + } + ); + }); + + it('should remove removed presets', () => { + expect(ExtendsMigration).toMigrate( + { + extends: ['helpers:oddIsUnstable'], + }, + { + extends: [], + } + ); + }); + + it('it migrates presets', () => { + GlobalConfig.set({ + migratePresets: { + '@org': 'local>org/renovate-config', + '@org2/foo': '', + }, + }); + expect(ExtendsMigration).toMigrate( + { + extends: ['@org', '@org2/foo'], + }, + { + extends: ['local>org/renovate-config'], + } + ); + GlobalConfig.reset(); + }); +}); diff --git a/lib/config/migrations/custom/extends-migration.ts b/lib/config/migrations/custom/extends-migration.ts new file mode 100644 index 0000000000000000000000000000000000000000..64a444b9170ede0c92a77f8c2adbde5c6627197c --- /dev/null +++ b/lib/config/migrations/custom/extends-migration.ts @@ -0,0 +1,44 @@ +import is from '@sindresorhus/is'; +import { GlobalConfig } from '../../global'; +import { removedPresets } from '../../presets/common'; +import { AbstractMigration } from '../base/abstract-migration'; + +export class ExtendsMigration extends AbstractMigration { + override readonly propertyName = 'extends'; + + override run(): void { + const value = this.get('extends'); + let newPresets: string[] = []; + + if (is.string(value)) { + newPresets = this.normalizePresets([value]); + } + + if (Array.isArray(value)) { + newPresets = this.normalizePresets(value); + } + + this.rewrite(newPresets); + } + + private normalizePresets(presets: string[]): string[] { + return presets + .filter(is.string) + .map((preset) => this.normalizePreset(preset)) + .filter(is.nonEmptyString); + } + + private normalizePreset(preset: string): string | null { + const { migratePresets } = GlobalConfig.get(); + + if (removedPresets[preset] !== undefined) { + return removedPresets[preset]; + } + + if (migratePresets?.[preset] !== undefined) { + return migratePresets?.[preset]; + } + + return preset; + } +} diff --git a/lib/config/migrations/migrations-service.ts b/lib/config/migrations/migrations-service.ts index 6cb47c2d6a524682d0a413bebf231aab7dc309ee..ae065f7c4a6c691aec10632a7cf3b738894a54df 100644 --- a/lib/config/migrations/migrations-service.ts +++ b/lib/config/migrations/migrations-service.ts @@ -13,6 +13,7 @@ import { BranchNameMigration } from './custom/branch-name-migration'; import { CompatibilityMigration } from './custom/compatibility-migration'; import { ComposerIgnorePlatformReqsMigration } from './custom/composer-ignore-platform-reqs-migration'; import { EnabledManagersMigration } from './custom/enabled-managers-migration'; +import { ExtendsMigration } from './custom/extends-migration'; import { GoModTidyMigration } from './custom/go-mod-tidy-migration'; import { HostRulesMigration } from './custom/host-rules-migration'; import { IgnoreNodeModulesMigration } from './custom/ignore-node-modules-migration'; @@ -78,6 +79,7 @@ export class MigrationsService { CompatibilityMigration, ComposerIgnorePlatformReqsMigration, EnabledManagersMigration, + ExtendsMigration, GoModTidyMigration, HostRulesMigration, IgnoreNodeModulesMigration,