mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 10:09:50 +00:00
2dbfd85506
* ci(linter): add renovate/no-sync-io rule Flags calls to a fixed list of Node.js sync I/O APIs (readFileSync, writeFileSync, mkdirSync, rmSync, readdirSync, statSync, existsSync, copyFileSync, execSync, spawnSync, execFileSync) in tools/** and **/*.spec.ts only; production lib code is not targeted. Set to "warn" instead of "error": the repo has 40 pre-existing violations, exceeding the agreed fix threshold of 30, so violations are left in place for follow-up rather than mass-fixed here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(linter): enforce renovate/no-sync-io at error Promote the rule from warn to error now that the codebase has been migrated off synchronous I/O in tools/ and spec files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(tools): migrate synchronous fs calls to async equivalents Replace *Sync fs calls with their async/promise-based counterparts in tools/ scripts (generate-imports, check runner, utils, cwdchanged hook) now that renovate/no-sync-io is enforced at error there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test: migrate synchronous fs calls in specs to async equivalents Replace *Sync fs calls (readdirSync, writeFileSync, existsSync, etc.) with their async/promise-based counterparts across affected spec files, making the enclosing it()/module-scope initializers async as needed, to satisfy renovate/no-sync-io now enforced at error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(linter): replace custom no-sync-io rule with built-in node/no-sync The oxc built-in covers a superset of the custom fixed-name list. Migrate the additionally flagged sites: async glob in test-shards, async execa in prepare-deps, promisified gzip/generateKeyPair in rpm/hex specs, and rename the misleading execSync mock alias (it mocks the async rawExec). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
import { readdir } from 'node:fs/promises';
|
|
import upath from 'upath';
|
|
import type { RenovateConfig } from '../types.ts';
|
|
import { AbstractMigration } from './base/abstract-migration.ts';
|
|
import { MigrationsService } from './migrations-service.ts';
|
|
import type { Migration } from './types.ts';
|
|
|
|
describe('config/migrations/migrations-service', () => {
|
|
it('should remove deprecated properties', () => {
|
|
for (const property of MigrationsService.removedProperties) {
|
|
const originalConfig: RenovateConfig = {
|
|
[property]: 'test',
|
|
};
|
|
|
|
const migratedConfig = MigrationsService.run(originalConfig);
|
|
expect(
|
|
MigrationsService.isMigrated(originalConfig, migratedConfig),
|
|
).toBeTrue();
|
|
expect(migratedConfig).toEqual({});
|
|
}
|
|
});
|
|
|
|
it('should rename renamed properties', () => {
|
|
for (const [
|
|
oldPropertyName,
|
|
newPropertyName,
|
|
] of MigrationsService.renamedProperties.entries()) {
|
|
const originalConfig: RenovateConfig = {
|
|
[oldPropertyName]: 'test',
|
|
};
|
|
|
|
const migratedConfig = MigrationsService.run(originalConfig);
|
|
expect(
|
|
MigrationsService.isMigrated(originalConfig, migratedConfig),
|
|
).toBeTrue();
|
|
expect(migratedConfig).toEqual({
|
|
[newPropertyName]: 'test',
|
|
});
|
|
}
|
|
});
|
|
|
|
it('should save original order of properties', () => {
|
|
const originalConfig = {
|
|
exposeEnv: true,
|
|
versionScheme: 'test',
|
|
excludedPackageNames: ['test'],
|
|
};
|
|
const migratedConfig = MigrationsService.run(originalConfig);
|
|
|
|
const mappedProperties = Object.keys(originalConfig).map((property) =>
|
|
MigrationsService.renamedProperties.get(property),
|
|
);
|
|
|
|
expect(
|
|
MigrationsService.isMigrated(originalConfig, migratedConfig),
|
|
).toBeTrue();
|
|
expect(mappedProperties).toEqual(Object.keys(migratedConfig));
|
|
});
|
|
|
|
it('should allow custom migrations by regexp', () => {
|
|
let isMigrationDone = false;
|
|
const originalConfig: RenovateConfig = {
|
|
// @ts-expect-error -- testing
|
|
fooBar: 'one',
|
|
};
|
|
class CustomMigration extends AbstractMigration {
|
|
override readonly deprecated = true;
|
|
override readonly propertyName = /^foo/;
|
|
|
|
override run(): void {
|
|
isMigrationDone = true;
|
|
}
|
|
}
|
|
|
|
class CustomMigrationsService extends MigrationsService {
|
|
public static override getMigrations(
|
|
original: RenovateConfig,
|
|
migrated: RenovateConfig,
|
|
): readonly Migration[] {
|
|
return [new CustomMigration(original, migrated)];
|
|
}
|
|
}
|
|
|
|
const migratedConfig = CustomMigrationsService.run(originalConfig);
|
|
expect(migratedConfig).toEqual({});
|
|
expect(isMigrationDone).toBeTrue();
|
|
});
|
|
|
|
it('there should be a single migration per property name', () => {
|
|
const migrations = MigrationsService.getMigrations({}, {});
|
|
|
|
const set = new Set<string | RegExp>();
|
|
const duplicateProperties: (string | RegExp)[] = [];
|
|
for (const { propertyName } of migrations) {
|
|
if (set.has(propertyName)) {
|
|
duplicateProperties.push(propertyName);
|
|
continue;
|
|
}
|
|
set.add(propertyName);
|
|
}
|
|
expect(duplicateProperties).toBeEmptyArray();
|
|
});
|
|
|
|
it('includes all defined migration classes in MigrationsService.customMigrations', async () => {
|
|
const allDefinedMigrationClasses: string[] = (
|
|
await readdir(upath.join(import.meta.dirname, 'custom'), {
|
|
withFileTypes: true,
|
|
})
|
|
)
|
|
.map((file) => file.name)
|
|
.filter((name) => !name.includes('spec.ts'));
|
|
|
|
expect(MigrationsService.customMigrations).toHaveLength(
|
|
allDefinedMigrationClasses.length,
|
|
);
|
|
});
|
|
});
|