mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
4b44c1c53a
The enumerated single-retry policy (#1419) has fired zero times since it landed on 2026-07-29: 0 of 234 sampled Coverage-job lane envelopes (2026-08-11 to 2026-08-18) have retryCount > 0, and none of 17 recent failed runs was retried (5 refused "outside the enumerated retry list", 4 refused "unhandled error"). All three trackers its entries pointed at (#1098, #1414, #1419) are closed. It cost ~1,454 LOC, a per-run secret marker threaded through a setup file on every Vitest project, and a standing obligation for every future gate reporter to call the blocker bus. Delete the scripts, tests and fixtures, the check:contention-retry script and gate, the envelope artifact upload, and the runner-timeout setup file; test:coverage:ci is a plain `vitest run --coverage` again. lane-envelope.ts stays: the mutation, fuzz and concurrency-torture lanes build their envelopes from it. run-blocker-bus.ts goes: its only consumer was the retry's failure sink, and its only publisher already fails the run by setting process.exitCode. Keep the subprocess-stub project for the three files that really spawn (client-metro, fuzz harness, fuzz corpus-replay) and drop the three that run in 31/212/277ms in CI, which cannot contend for anything. The list is now a plain array in vitest.config.ts with the reason at each entry. Membership and the project's kill criterion live in #1823. Because test:coverage:ci is a bare vitest run, the gate manifest reads its projects directly, so OPAQUE_RUNNERS no longer needs it and an unrun Vitest project becomes unrepresentable rather than detected; the audit test now constructs that state by project-scoping the script.
143 lines
5.0 KiB
TypeScript
143 lines
5.0 KiB
TypeScript
// Load-bearing ownership, path-reachability, and suite-registration witnesses.
|
|
|
|
import { execFileSync } from 'node:child_process';
|
|
import assert from 'node:assert/strict';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import { audit } from './audit.ts';
|
|
import { categories, loadModel, type Model } from './model.ts';
|
|
import type { Lane } from './workflows.ts';
|
|
|
|
const repoRoot = path.resolve(import.meta.dirname, '../..');
|
|
const tracked = execFileSync('git', ['ls-files'], {
|
|
cwd: repoRoot,
|
|
encoding: 'utf8',
|
|
})
|
|
.split('\n')
|
|
.filter(Boolean);
|
|
const base = loadModel(repoRoot, tracked);
|
|
|
|
function mutate(change: (model: Model) => Partial<Model>): Model {
|
|
return { ...base, ...change(base) };
|
|
}
|
|
|
|
function messages(model: Model): string[] {
|
|
return audit(model).map((failure) => failure.message);
|
|
}
|
|
|
|
function mapLane(
|
|
model: Model,
|
|
match: (lane: Lane) => boolean,
|
|
change: (lane: Lane) => Lane,
|
|
): Lane[] {
|
|
return model.lanes.map((lane) => (match(lane) ? change(lane) : lane));
|
|
}
|
|
|
|
test('the live tree is green — every planted failure below is a real difference', () => {
|
|
assert.deepEqual(messages(base), []);
|
|
});
|
|
|
|
test('deleting the lane that runs a gate reports exactly that gate, naming the runner', () => {
|
|
const model = mutate((m) => ({
|
|
lanes: mapLane(
|
|
m,
|
|
(lane) => lane.gates.includes('fuzz-parsers'),
|
|
(lane) => ({
|
|
...lane,
|
|
gates: lane.gates.filter((id) => id !== 'fuzz-parsers'),
|
|
}),
|
|
),
|
|
}));
|
|
const found = messages(model);
|
|
assert.equal(found.length, 1);
|
|
assert.match(
|
|
found[0] ?? '',
|
|
/check "fuzz-parsers" is not declared by any pull_request\/schedule lane/,
|
|
);
|
|
assert.match(found[0] ?? '', /run-gate action step for `fuzz-parsers`/);
|
|
});
|
|
|
|
test('a docs-only change still reaches the command-reference gate (#1420)', () => {
|
|
const model = mutate((m) => ({
|
|
lanes: mapLane(
|
|
m,
|
|
(lane) => lane.workflow === 'pr-preview.yml',
|
|
(lane) => ({ ...lane, paths: ['website/assets/**'] }),
|
|
),
|
|
}));
|
|
const found = messages(model);
|
|
assert.equal(found.length, 1);
|
|
assert.match(found[0] ?? '', /website\/docs\/docs\/commands\.md/);
|
|
assert.match(found[0] ?? '', /selects "command-docs"/);
|
|
});
|
|
|
|
test('a path filter that excludes a category fails, though the check still runs somewhere', () => {
|
|
// Take the category's path from the derivation rather than naming a file, so the
|
|
// case keeps exercising the real classification as the tree changes.
|
|
const category = categories(base).find((entry) => entry.rule === 'own:daemon-wire-compat');
|
|
assert.ok(category, 'the wire ledger must still be a category');
|
|
const model = mutate((m) => ({
|
|
lanes: mapLane(
|
|
m,
|
|
(lane) => lane.workflow === 'ci.yml',
|
|
(lane) => ({
|
|
...lane,
|
|
pathsIgnore: [...lane.pathsIgnore, category.path],
|
|
}),
|
|
),
|
|
}));
|
|
const found = messages(model);
|
|
assert.ok(
|
|
found.every((message) => !/is not run by any/.test(message)),
|
|
'the checks still run somewhere — only this path stops reaching them',
|
|
);
|
|
assert.ok(found.some((message) => message.includes(category.path)));
|
|
assert.ok(found.some((message) => /selects "daemon-wire-compat"/.test(message)));
|
|
});
|
|
|
|
// The Coverage lane runs a bare `vitest run --coverage`, which runs every project the config
|
|
// declares — so an unrun project is only representable once that script names its projects.
|
|
const projectScoped = (projects: readonly string[]): string =>
|
|
`vitest run --coverage ${projects.map((name) => `--project ${name}`).join(' ')}`;
|
|
|
|
test('a Vitest project no check runs is reported, and so is a suite script', () => {
|
|
const project = mutate((m) => ({
|
|
scripts: { ...m.scripts, 'test:coverage:ci': projectScoped(m.vitestProjects) },
|
|
vitestProjects: [...m.vitestProjects, 'new-lane'],
|
|
}));
|
|
assert.ok(
|
|
messages(project).some((message) =>
|
|
/Vitest project "new-lane" is run by no registered check/.test(message),
|
|
),
|
|
);
|
|
|
|
const script = mutate((m) => ({
|
|
scripts: {
|
|
...m.scripts,
|
|
'test:coverage:ci': projectScoped(m.vitestProjects),
|
|
'test:orphan': 'vitest run --project unit-core --project orphan-only',
|
|
},
|
|
vitestProjects: [...m.vitestProjects, 'orphan-only'],
|
|
}));
|
|
assert.ok(
|
|
messages(script).some((message) =>
|
|
/package script "test:orphan" runs vitest:orphan-only/.test(message),
|
|
),
|
|
);
|
|
});
|
|
|
|
test('a `test:*` script that is a suite by name, not by shape, needs an owner', () => {
|
|
// The five `test:replay:*` scripts run `node src/bin.ts test <dir>`, which resolves to a
|
|
// `script:` leaf. A shape-only rule could not see them: four were owned because someone
|
|
// hand-registered them, and `test:replay:android` was neither registered nor reported.
|
|
const model = mutate((m) => ({
|
|
scripts: { ...m.scripts, 'test:replay:freebsd': 'node src/bin.ts test test/replays/freebsd' },
|
|
}));
|
|
assert.ok(
|
|
messages(model).some((message) =>
|
|
/package script "test:replay:freebsd" runs script:test:replay:freebsd/.test(message),
|
|
),
|
|
'a new test:* script with no catalog entry must fail `registered`',
|
|
);
|
|
});
|