mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-10 10:40:32 +01:00
Keep Free Tests planning under its job cap when the duration seed goes stale (GST-2193) (#4245)
* Keep Free Tests planning under the job cap when the duration seed is stale (GST-2193) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Refresh the free-suite duration seed from run 42691699570 (GST-2193) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Admit the eight test files the fresh seed records over 60 seconds as annotated exceptions (GST-2193) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
dcebc44fa7
commit
72cbb49ddf
8 files changed
+1813
-1453
No files matched your search
+1637
-1441
File diff suppressed because it is too large.
Load diff
@@ -4,6 +4,14 @@
|
||||
{"file": "test/shared-libs-stage-actor.test.ts", "reason": "re-runs the paid shared-libs runner body against git fixture repos per test; owned by the paid-harness value-bar review"},
|
||||
{"file": "test/setup-install-registry.test.ts", "reason": "82s in the 2026-10-15 recording (58s on 2026-10-04): 11 cases each run the real ./setup, gstack-relink, gstack-config and gstack-uninstall against throwaway checkouts", "todo": "split by describe block so the packer can balance it, then rerun bun run test:ubicloud --record-durations (TODOS.md, fix wave 2 follow-ups)"},
|
||||
{"file": "test/brain-sync.test.ts", "reason": "89s in the 2026-10-19 weekly recording (58s on 2026-10-15): #3254 added the case-collision suite, and every case drains a real gstack-brain-sync against a local bare remote", "todo": "split by describe block so the packer can balance it, then rerun bun run test:ubicloud --record-durations (TODOS.md, fix wave 2 follow-ups)"},
|
||||
{"file": "test/setup-codex-scope.test.ts", "reason": "64s in the 2026-10-19 weekly recording (59s on 2026-10-15): each case runs the real ./setup twice against a Codex install fixture", "todo": "split by describe block so the packer can balance it, then rerun bun run test:ubicloud --record-durations (TODOS.md, fix wave 2 follow-ups)"}
|
||||
{"file": "test/setup-codex-scope.test.ts", "reason": "64s in the 2026-10-19 weekly recording (59s on 2026-10-15): each case runs the real ./setup twice against a Codex install fixture", "todo": "split by describe block so the packer can balance it, then rerun bun run test:ubicloud --record-durations (TODOS.md, fix wave 2 follow-ups)"},
|
||||
{"file": "test/review-pass.test.ts", "reason": "221s in the 2026-11-09 recording (run 42691699570; 24s on 2026-10-31); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/review-exclude.test.ts", "reason": "126s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/ubicloud-runner-recovery.test.ts", "reason": "79s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/ship-rereview-triggers.test.ts", "reason": "78s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "crew/test/ship-queue-train-generic.test.ts", "reason": "77s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/ship-finish-stack-parent.test.ts", "reason": "68s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/ship-ci-carry.test.ts", "reason": "67s in the 2026-11-09 recording (run 42691699570; unseeded before); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"},
|
||||
{"file": "test/ship-queue-land.test.ts", "reason": "60s in the 2026-11-09 recording (run 42691699570; 59s on 2026-10-31); admitted so the refreshed seed can land", "todo": "split or speed up; post-11-21 slow-test pass"}
|
||||
]
|
||||
}
|
||||
@@ -460,16 +460,34 @@ const runsSerialUnderJobs = (file: string) => file in TREE_MUTATING || file in S
|
||||
const planDigest = (plan: Omit<FreeCiPlan, 'id'>): string =>
|
||||
createHash('sha256').update(JSON.stringify(plan)).digest('hex');
|
||||
|
||||
/** One immutable plan is shared by isolated CI machines; never repack per job. */
|
||||
export function createFreeCiPlan(files: string[], count: number, durations: Record<string, number>, revision: string, shardJobs = 1): FreeCiPlan {
|
||||
/**
|
||||
* The largest packed prediction whose CI job still fits MAX_CI_JOB_TIMEOUT_MINUTES
|
||||
* (inverse of ciShardJobTimeoutMinutes's prediction term).
|
||||
*/
|
||||
export function maxPredictedMsUnderJobCap(setupSeconds: number): number {
|
||||
return Math.floor(((MAX_CI_JOB_TIMEOUT_MINUTES * 60 - setupSeconds) * 1000 - wallTimeoutForShard(FLAKY_RETRY_CAP)) / 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* One immutable plan is shared by isolated CI machines; never repack per job.
|
||||
* With setupSeconds (--ci-plan --job-setup-seconds), a shard whose 99th-percentile
|
||||
* estimates for unseeded files would push its job past the cap has its prediction
|
||||
* cut back to the cap (GST-2193): a stale seed lengthens the job up to the cap and
|
||||
* never fails the plan. Recorded durations are never cut, so a shard whose seeded
|
||||
* files alone pass the cap still fails it.
|
||||
*/
|
||||
export function createFreeCiPlan(files: string[], count: number, durations: Record<string, number>, revision: string, shardJobs = 1, setupSeconds?: number): FreeCiPlan {
|
||||
const readers = files.filter(file => !(file in TREE_MUTATING));
|
||||
const exclusive = files.filter(file => file in TREE_MUTATING).sort();
|
||||
const packed = packShardsByDuration(readers, count, durations);
|
||||
const planned = packed.shards.map((files, index) => ({ files, predictedMs: packed.predictedMs[index] }));
|
||||
if (exclusive.length) planned.push({ files: exclusive, predictedMs: exclusive.reduce((ms, file) => ms + (durations[file] ?? 0), 0) });
|
||||
const limitMs = setupSeconds === undefined ? Infinity : maxPredictedMsUnderJobCap(setupSeconds);
|
||||
const seededMs = (shardFiles: string[]) => shardFiles.reduce((ms, file) => ms + (durations[normalizeRelativePath(file)] ?? 0), 0);
|
||||
const shards = planned.map(({ files, predictedMs }, index) => {
|
||||
const jobs = plannedShardJobs(files, shardJobs, runsSerialUnderJobs);
|
||||
return { shard: index + 1, files, predictedMs, ...(jobs ? { jobs } : {}) };
|
||||
const capped = predictedMs > limitMs && seededMs(files) <= limitMs ? limitMs : predictedMs;
|
||||
return { shard: index + 1, files, predictedMs: capped, ...(jobs ? { jobs } : {}) };
|
||||
});
|
||||
const body = { version: 1 as const, revision, shards };
|
||||
return { ...body, id: planDigest(body) };
|
||||
@@ -2036,7 +2054,7 @@ async function main(): Promise<number> {
|
||||
appendStepSummary(line);
|
||||
}
|
||||
warnUnseededFreeFiles(ciFiles, durations);
|
||||
const plan = createFreeCiPlan(ciFiles, options.shardCount, durations, revision, options.shardJobs);
|
||||
const plan = createFreeCiPlan(ciFiles, options.shardCount, durations, revision, options.shardJobs, options.jobSetupSeconds);
|
||||
validateFreeCiPlan(plan, ciFiles, revision);
|
||||
const matrix = ciPlanMatrix(plan, options.jobSetupSeconds);
|
||||
if ('include' in matrix) {
|
||||
|
||||
Reference in new issue
Block a user