Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changes/pr-pipeline/perf-dispatch-verdict-exact-name-439816b1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
bump: patch
---

### Changed

- No workflow looks for the artifact listing pr-merge's last run saved any more. The verdict
reader reads the FAIL index by exact name and saves a listing only for a pull request past
`INDEX_NAMES_CAP` index names, so each search cost one run listing and up to ten runs'
artifact listings and almost always found nothing. Past that cap a dispatcher's FAIL-cap
read now lists in full. The address-feedback and
pr-unblock dispatchers' FAIL-cap reads (`verify-cap.mjs`), pr-merge's `merge` and
`enable-auto-merge` jobs, and ci-status's merge-queue reader no longer run it; the run cache
and head-ref map are still carried. `BABYSIT_VERIFY_LISTING_CARRY` is gone from every job.

### Removed

- `.github/scripts/pr-merge/listing-carry.mjs` and its floor row, and pr-merge's
`pr-merge-verify-listing` upload with its credential scan.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
bump: patch
---

### Changed

- `babysit_verify_evidence.py` documents that no workflow names `BABYSIT_VERIFY_LISTING_CARRY`
now that index mode saves no listing to carry; the reader still takes one when named. The
floor-path pins drop the removed `listing-carry.mjs` row.
8 changes: 0 additions & 8 deletions .github/artifact-retention.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,6 @@
"reason": "Read by the next run; 1 day is the minimum.",
"scan": "upload"
},
"pr-merge-verify-listing": {
"retention-days": 1,
"readers": [
".github/scripts/pr-merge/listing-carry.mjs LISTING_ARTIFACT, from the newest trusted run"
],
"reason": "Read by the next run as its listing base; 1 day is the minimum.",
"scan": "upload"
},
"pr-merge-head-refs": {
"retention-days": 1,
"readers": [
Expand Down
1 change: 0 additions & 1 deletion .github/scripts/pr-merge/clear-escalations.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@
// GITHUB_API_URL
// GITHUB_RUN_NUMBER where the sweep starts (rotated)
// BABYSIT_VERIFY_GH_TOKEN, BABYSIT_VERIFY_LISTING, BABYSIT_VERIFY_HEAD_REFS,
// BABYSIT_VERIFY_LISTING_CARRY,
// BABYSIT_RUN_CACHE the gate reader's Actions token and the run's shared
// reads, as enable-auto-merge passes them; the job
// token also reads branch activity, check runs and
Expand Down
88 changes: 0 additions & 88 deletions .github/scripts/pr-merge/listing-carry.mjs

This file was deleted.

98 changes: 0 additions & 98 deletions .github/scripts/pr-merge/listing-carry.test.mjs

This file was deleted.

1 change: 0 additions & 1 deletion .github/scripts/pr-merge/merge-holds.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ export const HOLD_PATH_CLASSES = Object.freeze([
[".github/scripts/pr-merge/who.mjs", "gate"],
[".github/scripts/pr-merge/post-unarmed-status.mjs", "gate"],
[".github/scripts/pr-merge/verify-answers.mjs", "gate"],
[".github/scripts/pr-merge/listing-carry.mjs", "gate"],
[".github/actions/report-check-run/posting-run.mjs", "gate"],
["scripts/sync-hold-floor.py", "trust"],
[".github/scripts/pr-unblock/address-feedback.mjs", "enforcement"],
Expand Down
15 changes: 12 additions & 3 deletions .github/scripts/pr-merge/workflow.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -814,8 +814,8 @@ test("enable-auto-merge skips its work when a waiting run's enable-auto-merge jo
// answers in that job's RUNNER_TEMP; the readers' tests count what it saves.
test("the merge and enable-auto-merge jobs' kept-file readers share their reads", () => {
for (const [id, scripts] of [
["merge", ["rotation.mjs", "head-ref-map.mjs read", "lane-records.mjs read", "listing-carry.mjs"]],
["enable-auto-merge", ["head-ref-map.mjs read", "lane-records.mjs read", "verify-answers.mjs", "listing-carry.mjs"]],
["merge", ["rotation.mjs", "head-ref-map.mjs read", "carry-run-cache.mjs read", "lane-records.mjs read"]],
["enable-auto-merge", ["head-ref-map.mjs read", "carry-run-cache.mjs read", "lane-records.mjs read", "verify-answers.mjs"]],
["post-merge-dispatch", ["lane-records.mjs read", "last-report.mjs"]],
]) {
for (const script of scripts) {
Expand All @@ -825,6 +825,15 @@ test("the merge and enable-auto-merge jobs' kept-file readers share their reads"
}
});

// The verdict reader reads the FAIL index by exact name, so no run saves an
// artifact listing for the next: none is uploaded, looked for or named.
test("no job keeps, fetches or names a carried artifact listing", () => {
const text = read("pr-merge.yml");
assert.doesNotMatch(text, /pr-merge-verify-listing/);
assert.doesNotMatch(text, /listing-carry/);
assert.doesNotMatch(text, /BABYSIT_VERIFY_LISTING_CARRY/);
});

test("the last verifier read enable-auto-merge starts ends inside its step's timeout", () => {
const arm = job("enable-auto-merge");
const step = /- name: Arm and disarm auto-merge\n {8}id: arm\n {8}if: .*\n {8}timeout-minutes: ([0-9]+)\n/.exec(arm);
Expand Down Expand Up @@ -1517,7 +1526,7 @@ test("a dispatch that failed skips the record", () => {
test("every credential scan has a timeout of at most 2 minutes, and the upload it guards needs its clean output", () => {
const bestEffort = {
"post-merge-dispatch": ["scan-upload", "scan-upload-5"],
merge: ["scan-upload-2", "scan-upload-3", "scan-upload-4", "scan-upload-5", "scan-upload-6", "scan-upload-7"],
merge: ["scan-upload-2", "scan-upload-3", "scan-upload-4", "scan-upload-5", "scan-upload-6"],
"enable-auto-merge": ["scan-upload", "scan-upload-2"],
"dispatch-full-run": [],
};
Expand Down
22 changes: 13 additions & 9 deletions .github/scripts/pr-unblock/verify-cap.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
// record and a compare per FAIL and a download per untied FAIL: on 2026-10-31,
// 458 FAILs were 1,252 reads, and every read was killed at
// VERIFY_CAP_TIMEOUT_MS with its calls spent and no answer. The
// reads pr-merge carried answer them with no request: its listing
// (listing-carry.mjs), run cache (carry-run-cache.mjs) and head-ref map
// (head-ref-map.mjs), used as its gate uses them, only where they count a FAIL.
// They are fetched on the first read only, so a run that skips before any read
// spends none of their calls, and the run cache keeps what each read adds for
// the next.
// reads pr-merge carried answer them with no request: its run cache
// (carry-run-cache.mjs) and head-ref map (head-ref-map.mjs), used as its gate
// uses them, only where they count a FAIL. They are fetched on the first read
// only, so a run that skips before any read spends none of their calls, and
// the run cache keeps what each read adds for the next. pr-merge's artifact
// listing is not fetched: the reader reads the FAIL index by exact name
// (babysit_verify_evidence.py `index_mode`), so no gate saves a listing to
// carry, and looking for one cost one run listing and ten runs' artifact
// listings a job.
//
// A count miss on the carried listing takes the reader's waits, about 45 s a
// read, and a read that ends in DEADLINE_UNREADABLE saves no listing, so the
Expand Down Expand Up @@ -119,7 +122,7 @@ export const CARRY_TIMEOUT_MS = 2 * 60_000;
export function carrySteps(env) {
const shared = { PR_MERGE_READS_PATH: `${env.RUNNER_TEMP}/verify-carry-reads.json` };
const carriedFile = `${env.RUNNER_TEMP}/pr-merge-carried.json`;
const steps = [{ script: "listing-carry.mjs", args: [], env: { ...shared, API_BUDGET_SCRIPT: "listing-carry" } }];
const steps = [];
if (env.BABYSIT_RUN_CACHE) {
steps.push(
{ script: "carry-run-cache.mjs", args: ["read"], env: { ...shared, API_BUDGET_SCRIPT: "carry-run-cache", CARRY_TO: carriedFile } },
Expand Down Expand Up @@ -191,7 +194,8 @@ function stderrSummary(stderr) {
// merge.max-verify-fails (the lower of that commit's and main's).
// `expected`: refusals the round is sent for, which warn nothing.
// `carry`: fetches what pr-merge carried, before the first read only, when the
// job names BABYSIT_VERIFY_LISTING_CARRY; a failed fetch is no carry.
// job names BABYSIT_RUN_CACHE or BABYSIT_VERIFY_HEAD_REFS (`carrySteps`); a
// failed fetch is no carry.
export function verifyCapReader(env, options) {
const read = verifyReader(env, options);
return async (request) => (await read(request)).cap;
Expand All @@ -216,7 +220,7 @@ export function verifyReader(env, { spawn = spawnAsync, log = (line) => console.
let carried = null;
let deadlineMissed = false;
return async ({ number, head, base, expected = [] }) => {
if (env.BABYSIT_VERIFY_LISTING_CARRY) {
if (carrySteps(env).length > 0) {
carried ??= Promise.resolve()
.then(() => carry(env))
.catch((error) => log(`::warning::pr-merge's carried reads were not all fetched (${oneLine(error?.message ?? error)}); the reader asks GitHub for the rest`));
Expand Down
Loading
Loading