mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-09 18:28:15 +01:00
free-ci-health: a split shard's overrun compares wall time with its prediction over jobs (GST-1653) (#4085)
shardOverruns compared a shard's wall-clock elapsedMs with predictedMs, the shard's serial seed sum. free-tests.yml plans every shard at --shard-jobs 4, so the 1.5x warning only fired after about a 6x slowdown. The prediction is now divided by the plan shard's jobs, ciHealthSummary carries jobs through, and the warning names the parallel job count. k=1 output is unchanged. Rewritten on main from #4051, which fixes #3851. Co-authored-by: Indra Prasetya <indraoverflow@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
4 files changed
+43
-8
No files matched your search
@@ -134,6 +134,15 @@ describe('free lane CI warnings', () => {
|
||||
expect(overrunWarning([])).toBeNull();
|
||||
});
|
||||
|
||||
test('a shard split across parallel jobs is measured against its prediction divided by its job count', () => {
|
||||
const timing = (shard: number, jobs: number, elapsedMs: number) => ({ shard, predictedMs: 400_000, elapsedMs, jobs });
|
||||
expect(shardOverruns([timing(1, 1, 610_000), timing(2, 1, 590_000)]).map(overrun => overrun.shard)).toEqual([1]);
|
||||
const overruns = shardOverruns([timing(1, 4, 160_000), timing(2, 4, 140_000)]);
|
||||
expect(overruns.map(overrun => overrun.shard)).toEqual([1]);
|
||||
expect(overrunWarning(overruns)).toContain('shard 1 took 160s vs 100s predicted across 4 parallel jobs');
|
||||
expect(overrunWarning([timing(1, 1, 610_000)])).toContain('shard 1 took 610s vs 400s predicted)');
|
||||
});
|
||||
|
||||
test('the --ci-verify summary lists shards that outran the seed, counting the first attempt only', () => {
|
||||
const outcome = (shard: number, files: string[], failingFiles: string[], elapsedMs: number): FreeShardOutcome =>
|
||||
({ shard, files, failingFiles, elapsedMs, status: failingFiles.length ? 'failed' : 'passed' }) as FreeShardOutcome;
|
||||
@@ -151,4 +160,21 @@ describe('free lane CI warnings', () => {
|
||||
expect(summary[0]).not.toContain('shard 1');
|
||||
expect(ciHealthSummary(plan, [results[0]].map(r => ({ ...r, outcome: { ...r.outcome, elapsedMs: 100_000 } })))).toEqual([]);
|
||||
});
|
||||
|
||||
test('the --ci-verify summary divides each shard\'s prediction by the plan shard\'s jobs', () => {
|
||||
const outcome = (shard: number, elapsedMs: number): FreeShardOutcome =>
|
||||
({ shard, files: [], status: 'passed', exitCode: 0, elapsedMs, groupPid: null, failingFiles: [], unattributedFailures: 0 });
|
||||
const plan = { version: 1, revision: 'r', id: 'p', shards: [
|
||||
{ shard: 1, files: ['test/a.test.ts'], predictedMs: 400_000, jobs: 4 },
|
||||
{ shard: 2, files: ['test/b.test.ts'], predictedMs: 400_000, jobs: 4 },
|
||||
] } satisfies FreeCiPlan;
|
||||
const results: FreeCiResult[] = [
|
||||
{ planId: 'p', revision: 'r', outcome: outcome(1, 160_000), retry: null },
|
||||
{ planId: 'p', revision: 'r', outcome: outcome(2, 120_000), retry: null },
|
||||
];
|
||||
const summary = ciHealthSummary(plan, results);
|
||||
expect(summary).toHaveLength(1);
|
||||
expect(summary[0]).toContain('shard 1 took 160s vs 100s predicted across 4 parallel jobs');
|
||||
expect(summary[0]).not.toContain('shard 2');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user