Files
renovate/lib/modules/versioning/versioning-metadata.spec.ts
Sebastian Poxhofer 2dbfd85506 refactor(linters): enable node/no-sync and migrate to async calls (#44693)
* 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>
2026-07-20 14:28:26 +00:00

67 lines
1.8 KiB
TypeScript

import { readdir } from 'node:fs/promises';
import { readFile } from 'fs-extra';
import { z } from 'zod/v4';
import { markdownLinkRegex } from './common.ts';
const allVersioning = (
await readdir('lib/modules/versioning', {
withFileTypes: true,
})
)
.filter((item) => item.isDirectory())
.map((item) => item.name);
describe('modules/versioning/versioning-metadata', () => {
describe.each(allVersioning)('%s', (versioning) => {
it('readme with no h1 or h2 markdown headers', async () => {
let readme = '';
try {
readme = await readFile(
`lib/modules/versioning/${versioning}/readme.md`,
'utf8',
);
} catch {
// ignore missing file
}
const lines = readme.split('\n');
let isCode = false;
const res: string[] = [];
for (const line of lines) {
if (line.startsWith('```')) {
isCode = !isCode;
} else if (!isCode) {
res.push(line);
}
}
expect(
res.some((line) => line.startsWith('# ') || line.startsWith('## ')),
).toBeFalse();
});
it('contains mandatory fields', async () => {
const Base = z.object({
id: z.string(),
displayName: z.string(),
urls: z.array(
z.string().regex(markdownLinkRegex, 'url must be a markdown link'),
),
});
const VersioningMetadata = z.discriminatedUnion('supportsRanges', [
Base.extend({
supportsRanges: z.literal(true),
supportedRangeStrategies: z.array(z.string()),
}),
Base.extend({
supportsRanges: z.literal(false),
}),
]);
const versioningObj = VersioningMetadata.parse(
await import(`./${versioning}/index.ts`),
);
expect(versioningObj.id).toEqual(versioning);
});
});
});