scripts/run-changed-vitest.mjs
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
const workspace = resolve(process.cwd());
const testFilePattern = /(?:^|\/)[^/]+\.(?:test|spec)\.[cm]?[jt]sx?$/;
function run(command, args, options = {}) {
const result = spawnSync(command, args, {
cwd: workspace,
encoding: 'utf8',
maxBuffer: 10 * 1024 * 1024,
stdio: options.inherit ? 'inherit' : 'pipe',
});
if (result.error) throw result.error;
return result;
}
function resolveCommit(ref, label) {
if (!ref || ref.startsWith('-') || !/^[A-Za-z0-9._/^~-]+$/.test(ref)) {
throw new Error(`${label} must be a safe Git commit or ref`);
}
const result = run('git', ['rev-parse', '--verify', `${ref}^{commit}`]);
if (result.status !== 0) {
throw new Error(
`Could not resolve ${label} ${ref}: ${result.stderr.trim()}`
);
}
return result.stdout.trim();
}
function changedTestFiles(baseCommit, headCommit) {
const result = run('git', [
'diff',
'--name-only',
'--diff-filter=ACMR',
'-z',
baseCommit,
headCommit,
'--',
'src',
'test',
]);
if (result.status !== 0) {
throw new Error(
`Could not list changed test files: ${result.stderr.trim()}`
);
}
return result.stdout
.split('\0')
.filter(Boolean)
.filter((path) => testFilePattern.test(path))
.sort();
}
let exitCode = 1;
try {
const headRef = process.env.VITEST_HEAD_SHA;
let baseRef = process.env.VITEST_BASE_SHA;
if (baseRef && /^0+$/.test(baseRef)) baseRef = `${headRef}^`;
const baseCommit = resolveCommit(baseRef, 'VITEST_BASE_SHA');
const headCommit = resolveCommit(headRef, 'VITEST_HEAD_SHA');
const testFiles = changedTestFiles(baseCommit, headCommit);
if (testFiles.length === 0) {
console.log(
'No frontend test files were added or updated; skipping Vitest.'
);
exitCode = 0;
} else {
console.log(`Running ${testFiles.length} changed frontend test file(s):`);
testFiles.forEach((path) => console.log(` - ${path}`));
const executable = resolve(workspace, 'node_modules/.bin/vitest');
if (!existsSync(executable)) {
throw new Error('Vitest is not installed; run npm ci before this script');
}
const result = run(
executable,
[
'run',
'--config',
'vitest.config.ts',
'--passWithNoTests',
// GitHub-hosted runners can report more CPUs than they can sustain.
// Bound jsdom workers so frontend tests fit within the CPU available
// on GitHub-hosted runners.
'--maxWorkers=2',
'--minWorkers=1',
...testFiles.map((path) => `./${path}`),
],
{ inherit: true }
);
exitCode = result.status ?? 1;
}
} catch (error) {
console.error(error instanceof Error ? error.message : error);
exitCode = 1;
}
process.exitCode = exitCode;