diff --git a/lib/config/migration.ts b/lib/config/migration.ts index 7d1f4b16718893a43fd225fbb4e20ba8572db7b9..3679b9b01e3fd66fcf869d8255d49ee9a81f4de6 100644 --- a/lib/config/migration.ts +++ b/lib/config/migration.ts @@ -31,26 +31,9 @@ export function migrateConfig(config: RenovateConfig): MigratedConfig { } const newConfig = MigrationsService.run(config); const migratedConfig = clone(newConfig) as MigratedRenovateConfig; - const depTypes = [ - 'dependencies', - 'devDependencies', - 'engines', - 'optionalDependencies', - 'peerDependencies', - ]; + for (const [key, val] of Object.entries(newConfig)) { - if (depTypes.includes(key)) { - migratedConfig.packageRules = is.array(migratedConfig.packageRules) - ? migratedConfig.packageRules - : []; - const depTypePackageRule = migrateConfig( - val as RenovateConfig - ).migratedConfig; - depTypePackageRule.depTypeList = [key]; - delete depTypePackageRule.packageRules; - migratedConfig.packageRules.push(depTypePackageRule); - delete migratedConfig[key]; - } else if (is.string(val) && val.includes('{{baseDir}}')) { + if (is.string(val) && val.includes('{{baseDir}}')) { migratedConfig[key] = val.replace( regEx(/{{baseDir}}/g), '{{packageFileDir}}' @@ -70,26 +53,6 @@ export function migrateConfig(config: RenovateConfig): MigratedConfig { '{{semanticPrefix}}', '{{#if semanticCommitType}}{{semanticCommitType}}{{#if semanticCommitScope}}({{semanticCommitScope}}){{/if}}: {{/if}}' ); - } else if (key === 'depTypes' && is.array(val)) { - val.forEach((depType) => { - if (is.object(depType) && !is.array(depType)) { - const depTypeName = (depType as any).depType; - if (depTypeName) { - migratedConfig.packageRules = is.array( - migratedConfig.packageRules - ) - ? migratedConfig.packageRules - : []; - const newPackageRule = migrateConfig( - depType as RenovateConfig - ).migratedConfig; - delete newPackageRule.depType; - newPackageRule.depTypeList = [depTypeName]; - migratedConfig.packageRules.push(newPackageRule); - } - } - }); - delete migratedConfig.depTypes; } else if (optionTypes[key] === 'object' && is.boolean(val)) { migratedConfig[key] = { enabled: val }; } else if (optionTypes[key] === 'boolean') { diff --git a/lib/config/migrations/custom/dep-types-migration.spec.ts b/lib/config/migrations/custom/dep-types-migration.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c21e9d053f0154b62f92aeb001207cc39197ad4 --- /dev/null +++ b/lib/config/migrations/custom/dep-types-migration.spec.ts @@ -0,0 +1,90 @@ +import { DepTypesMigration } from './dep-types-migration'; + +describe('config/migrations/custom/dep-types-migration', () => { + it('should only add depTypes to packageRules', () => { + expect(DepTypesMigration).toMigrate( + { + peerDependencies: { + versionStrategy: 'widen', + }, + dependencies: { + versionStrategy: 'widen', + }, + engines: { + rangeStrategy: 'auto', + }, + optionalDependencies: { + versionStrategy: 'widen', + }, + devDependencies: { + versionStrategy: 'widen', + }, + depTypes: [ + 'dependencies', + { + depType: 'optionalDependencies', + respectLatest: false, + }, + ], + packageRules: [ + { + packagePatterns: '^(@angular|typescript)' as never, + groupName: ['angular packages'] as never, + excludedPackageNames: 'foo', + }, + { + packageNames: ['foo'], + packageRules: [ + { + depTypeList: ['bar'], + automerge: true, + }, + ], + }, + ], + }, + { + packageRules: [ + { + packagePatterns: '^(@angular|typescript)' as never, + groupName: ['angular packages'] as never, + excludedPackageNames: 'foo', + }, + { + packageNames: ['foo'], + packageRules: [ + { + depTypeList: ['bar'], + automerge: true, + }, + ], + }, + { + matchDepTypes: ['peerDependencies'], + versionStrategy: 'widen', + }, + { + matchDepTypes: ['dependencies'], + versionStrategy: 'widen', + }, + { + matchDepTypes: ['engines'], + rangeStrategy: 'auto', + }, + { + matchDepTypes: ['optionalDependencies'], + versionStrategy: 'widen', + }, + { + matchDepTypes: ['devDependencies'], + versionStrategy: 'widen', + }, + { + matchDepTypes: ['optionalDependencies'], + respectLatest: false, + }, + ], + } + ); + }); +}); diff --git a/lib/config/migrations/custom/dep-types-migration.ts b/lib/config/migrations/custom/dep-types-migration.ts new file mode 100644 index 0000000000000000000000000000000000000000..f7a824729b69c3263ad0b819cae446f3cb229605 --- /dev/null +++ b/lib/config/migrations/custom/dep-types-migration.ts @@ -0,0 +1,38 @@ +import is from '@sindresorhus/is'; +import type { PackageRule, PackageRuleInputConfig } from '../../types'; +import { AbstractMigration } from '../base/abstract-migration'; + +interface DepTypesRule extends PackageRule, PackageRuleInputConfig {} + +export class DepTypesMigration extends AbstractMigration { + override readonly deprecated = true; + override readonly propertyName = + /^(?:(?:d|devD|optionalD|peerD)ependencies|engines|depTypes)$/; + + override run(value: unknown, key: string): void { + const packageRules: PackageRule[] = this.get('packageRules') ?? []; + if (is.nonEmptyObject(value) && !is.array(value)) { + packageRules.push({ + matchDepTypes: [key], + ...value, + } as PackageRule); + } + + if (is.array(value)) { + for (const depType of value as DepTypesRule[]) { + if (is.object(depType) && !is.array(depType)) { + const depTypeName = depType.depType; + if (depTypeName) { + delete depType.depType; + depType.matchDepTypes = [depTypeName]; + packageRules.push({ ...(depType as PackageRule) }); + } + } + } + } + + if (packageRules.length) { + this.setHard('packageRules', packageRules); + } + } +} diff --git a/lib/config/migrations/migrations-service.ts b/lib/config/migrations/migrations-service.ts index 50e139fd1404de17b13d7a3b33538edd8f6bdb1f..0ded6715208a15667a0d13aaa68329dbfcea9713 100644 --- a/lib/config/migrations/migrations-service.ts +++ b/lib/config/migrations/migrations-service.ts @@ -15,6 +15,7 @@ import { BranchNameMigration } from './custom/branch-name-migration'; import { BranchPrefixMigration } from './custom/branch-prefix-migration'; import { CompatibilityMigration } from './custom/compatibility-migration'; import { ComposerIgnorePlatformReqsMigration } from './custom/composer-ignore-platform-reqs-migration'; +import { DepTypesMigration } from './custom/dep-types-migration'; import { DryRunMigration } from './custom/dry-run-migration'; import { EnabledManagersMigration } from './custom/enabled-managers-migration'; import { ExtendsMigration } from './custom/extends-migration'; @@ -131,6 +132,7 @@ export class MigrationsService { DryRunMigration, RequireConfigMigration, PackageFilesMigration, + DepTypesMigration, PackageRulesMigration, NodeMigration, SemanticPrefixMigration,