diff --git a/lib/config/migration.ts b/lib/config/migration.ts index 8b66fdfd7bb328..7d1f4b16718893 100644 --- a/lib/config/migration.ts +++ b/lib/config/migration.ts @@ -141,31 +141,6 @@ export function migrateConfig(config: RenovateConfig): MigratedConfig { } } } - if (is.array(migratedConfig.packageRules)) { - const newRules: PackageRule[] = []; - const renameMap = { - paths: 'matchPaths', - languages: 'matchLanguages', - baseBranchList: 'matchBaseBranches', - managers: 'matchManagers', - datasources: 'matchDatasources', - depTypeList: 'matchDepTypes', - packageNames: 'matchPackageNames', - packagePatterns: 'matchPackagePatterns', - sourceUrlPrefixes: 'matchSourceUrlPrefixes', - updateTypes: 'matchUpdateTypes', - } as const; - for (const packageRule of migratedConfig.packageRules) { - const newRuleObj = {} as PackageRule; - for (const [oldKey, ruleVal] of Object.entries(packageRule)) { - const key = renameMap[oldKey as keyof typeof renameMap] ?? oldKey; - // TODO: fix types #7154 - newRuleObj[key] = ruleVal as never; - } - newRules.push(newRuleObj); - } - migratedConfig.packageRules = newRules; - } // Migrate nested packageRules if (is.nonEmptyArray(migratedConfig.packageRules)) { const existingRules = migratedConfig.packageRules; diff --git a/lib/config/migrations/custom/package-rules-migration.spec.ts b/lib/config/migrations/custom/package-rules-migration.spec.ts new file mode 100644 index 00000000000000..21285fbf9b0114 --- /dev/null +++ b/lib/config/migrations/custom/package-rules-migration.spec.ts @@ -0,0 +1,60 @@ +import type { RenovateConfig } from '../../types'; +import { MigrationsService } from '../migrations-service'; +import { PackageRulesMigration, renameMap } from './package-rules-migration'; + +describe('config/migrations/custom/package-rules-migration', () => { + it('should preserve config order', () => { + const originalConfig: RenovateConfig = { + packageRules: [ + { + paths: [], + labels: ['linting'], + baseBranchList: [], + languages: [], + managers: [], + datasources: [], + depTypeList: [], + addLabels: [], + packageNames: [], + packagePatterns: [], + sourceUrlPrefixes: [], + updateTypes: [], + }, + ], + }; + const migratedPackageRules = + MigrationsService.run(originalConfig).packageRules; + + const mappedProperties = Object.keys(migratedPackageRules![0]); + const expectedMappedProperties = Object.keys( + originalConfig.packageRules![0] + ).map((key) => renameMap[key as keyof typeof renameMap] ?? key); + + expect(expectedMappedProperties).toEqual(mappedProperties); + }); + + it('should not migrate nested packageRules', () => { + expect(PackageRulesMigration).toMigrate( + { + packageRules: [ + { + paths: [], + packgageRules: { + languages: ['javascript'], + }, + }, + ], + }, + { + packageRules: [ + { + matchPaths: [], + packgageRules: { + languages: ['javascript'], + }, + }, + ], + } + ); + }); +}); diff --git a/lib/config/migrations/custom/package-rules-migration.ts b/lib/config/migrations/custom/package-rules-migration.ts new file mode 100644 index 00000000000000..e3be4c4c910ac0 --- /dev/null +++ b/lib/config/migrations/custom/package-rules-migration.ts @@ -0,0 +1,37 @@ +import type { PackageRule } from '../../types'; +import { AbstractMigration } from '../base/abstract-migration'; + +export const renameMap = { + paths: 'matchPaths', + languages: 'matchLanguages', + baseBranchList: 'matchBaseBranches', + managers: 'matchManagers', + datasources: 'matchDatasources', + depTypeList: 'matchDepTypes', + packageNames: 'matchPackageNames', + packagePatterns: 'matchPackagePatterns', + sourceUrlPrefixes: 'matchSourceUrlPrefixes', + updateTypes: 'matchUpdateTypes', +}; +type RenameMapKey = keyof typeof renameMap; + +function renameKeys(packageRule: PackageRule): PackageRule { + const newPackageRule: PackageRule = {}; + for (const [key, val] of Object.entries(packageRule)) { + newPackageRule[renameMap[key as RenameMapKey] ?? key] = val; + } + return newPackageRule; +} + +export class PackageRulesMigration extends AbstractMigration { + override readonly propertyName = 'packageRules'; + + override run(value: unknown): void { + let packageRules = (this.get('packageRules') as PackageRule[]) ?? []; + packageRules = Array.isArray(packageRules) ? [...packageRules] : []; + + packageRules = packageRules.map(renameKeys); + + this.rewrite(packageRules); + } +} diff --git a/lib/config/migrations/migrations-service.ts b/lib/config/migrations/migrations-service.ts index da950b2d1c70f9..50e139fd1404de 100644 --- a/lib/config/migrations/migrations-service.ts +++ b/lib/config/migrations/migrations-service.ts @@ -27,6 +27,7 @@ import { NodeMigration } from './custom/node-migration'; import { PackageFilesMigration } from './custom/package-files-migration'; import { PackageNameMigration } from './custom/package-name-migration'; import { PackagePatternMigration } from './custom/package-pattern-migration'; +import { PackageRulesMigration } from './custom/package-rules-migration'; import { PackagesMigration } from './custom/packages-migration'; import { PathRulesMigration } from './custom/path-rules-migration'; import { PinVersionsMigration } from './custom/pin-versions-migration'; @@ -130,6 +131,7 @@ export class MigrationsService { DryRunMigration, RequireConfigMigration, PackageFilesMigration, + PackageRulesMigration, NodeMigration, SemanticPrefixMigration, ];