Skip to content

Commit

Permalink
refactor: migrate inline with the same sort
Browse files Browse the repository at this point in the history
  • Loading branch information
pret-a-porter committed Oct 9, 2021
1 parent d55650f commit 8d9a6b9
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 62 deletions.
15 changes: 3 additions & 12 deletions lib/config/migration.ts
Expand Up @@ -4,7 +4,7 @@ import { dequal } from 'dequal';
import { logger } from '../logger';
import { clone } from '../util/clone';
import { getGlobalConfig } from './global';
import { applyMigrations } from './migrations';
import { MigrationsRunner } from './migrations';
import { getOptions } from './options';
import { removedPresets } from './presets/common';
import type {
Expand All @@ -20,7 +20,6 @@ const options = getOptions();
let optionTypes: Record<string, RenovateOptions['type']>;

const removedOptions = [
'maintainYarnLock',
'yarnCacheFolder',
'yarnMaintenanceBranchName',
'yarnMaintenanceCommitMessage',
Expand Down Expand Up @@ -49,7 +48,8 @@ export function migrateConfig(
optionTypes[option.name] = option.type;
});
}
const migratedConfig = clone(config) as MigratedRenovateConfig;
const newConfig = MigrationsRunner.runAllMigrations(config);
const migratedConfig = clone(newConfig) as MigratedRenovateConfig;
const depTypes = [
'dependencies',
'devDependencies',
Expand All @@ -58,18 +58,9 @@ export function migrateConfig(
'peerDependencies',
];
const { migratePresets } = getGlobalConfig();
applyMigrations(config, migratedConfig);
for (const [key, val] of Object.entries(config)) {
if (removedOptions.includes(key)) {
delete migratedConfig[key];
} else if (key === 'pathRules') {
if (is.array(val)) {
migratedConfig.packageRules = is.array(migratedConfig.packageRules)
? migratedConfig.packageRules
: [];
migratedConfig.packageRules = val.concat(migratedConfig.packageRules);
}
delete migratedConfig.pathRules;
} else if (key === 'suppressNotifications') {
if (is.nonEmptyArray(val) && val.includes('prEditNotification')) {
migratedConfig.suppressNotifications =
Expand Down
17 changes: 17 additions & 0 deletions lib/config/migrations/base/deprecate-property-migration.ts
@@ -0,0 +1,17 @@
import type { RenovateConfig } from '../../types';
import type { Migration } from '../migration';

export class DeprecatePropertyMigration implements Migration {
private readonly deprecatedPropertyName: string;

constructor(deprecatedPropertyName: string) {
this.deprecatedPropertyName = deprecatedPropertyName;
}

run(config: RenovateConfig): RenovateConfig {
// eslint-disable-next-line no-param-reassign
delete config[this.deprecatedPropertyName];

return config;
}
}
29 changes: 29 additions & 0 deletions lib/config/migrations/base/replace-property-migration.ts
@@ -0,0 +1,29 @@
import type { RenovateConfig } from '../../types';
import type { Migration } from '../migration';

export abstract class ReplacePropertyMigration implements Migration {
protected abstract readonly deprecatedPropertyName: string;

protected abstract readonly newPropertyName: string;

abstract run(config: RenovateConfig): RenovateConfig;

protected replaceProperty(
config: RenovateConfig,
newValue?: unknown
): Record<string, unknown> {
const migratedConfig: Record<string, unknown> = {};

for (const [key, value] of Object.entries(config)) {
if (key === this.deprecatedPropertyName) {
if (newValue !== undefined) {
migratedConfig[this.newPropertyName] = newValue;
}
} else {
migratedConfig[key] = value;
}
}

return migratedConfig;
}
}
19 changes: 1 addition & 18 deletions lib/config/migrations/index.ts
@@ -1,18 +1 @@
import { RenovateConfig } from '../types';
import type { Migration } from './migration';
import { RequiredStatusChecksMigration } from './required-status-checks-migration';

export function applyMigrations(
originalConfig: RenovateConfig,
migratedConfig: RenovateConfig
): RenovateConfig {
const migrations: Migration[] = [
new RequiredStatusChecksMigration(originalConfig, migratedConfig),
];

for (const migration of migrations) {
migration.migrate();
}

return migratedConfig;
}
export * from './migrations-runner';
17 changes: 2 additions & 15 deletions lib/config/migrations/migration.ts
@@ -1,18 +1,5 @@
import type { RenovateConfig } from '../types';

export abstract class Migration {
protected readonly originalConfig: RenovateConfig;

protected readonly migratedConfig: RenovateConfig;

constructor(originalConfig: RenovateConfig, migratedConfig: RenovateConfig) {
this.originalConfig = originalConfig;
this.migratedConfig = migratedConfig;
}

abstract migrate(): void;

protected delete(property: string): void {
delete this.migratedConfig[property];
}
export interface Migration {
run(config: RenovateConfig): RenovateConfig;
}
23 changes: 23 additions & 0 deletions lib/config/migrations/migrations-runner.ts
@@ -0,0 +1,23 @@
import type { RenovateConfig } from '../types';
import { DeprecatePropertyMigration } from './base/deprecate-property-migration';
import type { Migration } from './migration';
import { PathRulesMigration } from './path-rules-migration';
import { RequiredStatusChecksMigration } from './required-status-checks-migration';

export class MigrationsRunner {
private static readonly migrations: ReadonlyArray<Migration> = [
new DeprecatePropertyMigration('maintainYarnLock'),
new PathRulesMigration(),
new RequiredStatusChecksMigration(),
];

static runAllMigrations(originalConfig: RenovateConfig): RenovateConfig {
let config = originalConfig;

for (const migration of MigrationsRunner.migrations) {
config = migration.run(config);
}

return config;
}
}
20 changes: 20 additions & 0 deletions lib/config/migrations/path-rules-migration.ts
@@ -0,0 +1,20 @@
import type { RenovateConfig } from '../types';
import { ReplacePropertyMigration } from './base/replace-property-migration';

export class PathRulesMigration extends ReplacePropertyMigration {
protected override readonly deprecatedPropertyName = 'pathRules';

protected override readonly newPropertyName = 'packageRules';

override run(config: RenovateConfig): RenovateConfig {
const { pathRules } = config;
const packageRules = Array.isArray(config.packageRules)
? config.packageRules
: [];

return this.replaceProperty(
config,
Array.isArray(pathRules) ? pathRules.concat(packageRules) : packageRules
);
}
}
14 changes: 4 additions & 10 deletions lib/config/migrations/required-status-checks-migration.spec.ts
@@ -1,20 +1,14 @@
import type { RenovateConfig } from '../types';
import { RequiredStatusChecksMigration } from './required-status-checks-migration';

describe('config/migrations/required-status-checks-migration', () => {
it('should migrate requiredStatusChecks=null to ignoreTests=true', () => {
const originalConfig: any = {
const originalConfig: Partial<RenovateConfig> = {
requiredStatusChecks: null,
};
const migratedConfig: any = {
requiredStatusChecks: null,
};
const migration = new RequiredStatusChecksMigration(
originalConfig,
migratedConfig
);
const migration = new RequiredStatusChecksMigration();
const migratedConfig = migration.run(originalConfig);

expect(migratedConfig.requiredStatusChecks).toBeNull();
migration.migrate();
expect(migratedConfig.requiredStatusChecks).toBeUndefined();
expect(migratedConfig.ignoreTests).toBeTrue();
});
Expand Down
18 changes: 11 additions & 7 deletions lib/config/migrations/required-status-checks-migration.ts
@@ -1,11 +1,15 @@
import { Migration } from './migration';
import type { RenovateConfig } from '../types';
import { ReplacePropertyMigration } from './base/replace-property-migration';

export class RequiredStatusChecksMigration extends Migration {
public migrate(): void {
this.delete('requiredStatusChecks');
export class RequiredStatusChecksMigration extends ReplacePropertyMigration {
protected override readonly deprecatedPropertyName = 'requiredStatusChecks';

if (this.originalConfig.requiredStatusChecks === null) {
this.migratedConfig.ignoreTests = true;
}
protected override readonly newPropertyName = 'ignoreTests';

override run(config: RenovateConfig): RenovateConfig {
return this.replaceProperty(
config,
config.requiredStatusChecks === null ? true : undefined
);
}
}

0 comments on commit 8d9a6b9

Please sign in to comment.