Skip to content

Commit 1bbf40c

Browse files
authored
ci: Harden Codex retry state
1 parent 5404b10 commit 1bbf40c

1 file changed

Lines changed: 52 additions & 27 deletions

File tree

‎.github/workflows/codex-review-gate.yml‎

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ jobs:
103103
typeof value.probe.head_sha === 'string'
104104
? value.probe.head_sha
105105
: null,
106+
base_sha:
107+
typeof value.probe.base_sha === 'string'
108+
? value.probe.base_sha
109+
: null,
106110
requested_at:
107111
typeof value.probe.requested_at === 'string'
108112
? value.probe.requested_at
@@ -387,7 +391,10 @@ jobs:
387391
if (pull.draft) continue;
388392
389393
let run = await latestGateRun(pull.head.sha);
390-
if (run && run.external_id !== pull.base.sha) run = undefined;
394+
const baseChanged = Boolean(
395+
run && run.external_id !== pull.base.sha,
396+
);
397+
if (baseChanged) run = undefined;
391398
if (!run) run = await createPendingGate(pull);
392399
393400
if (run.status === 'completed') continue;
@@ -409,9 +416,11 @@ jobs:
409416
if (outcome.quota) quotaEvents.push(outcome.quota);
410417
411418
pending.push({
419+
base_sha: pull.base.sha,
412420
check_run_id: run.id,
413421
head_sha: pull.head.sha,
414422
needs_manual:
423+
baseChanged ||
415424
context.eventName === 'pull_request_target' &&
416425
context.payload.pull_request?.number === pull.number &&
417426
(context.payload.action === 'synchronize' ||
@@ -477,41 +486,50 @@ jobs:
477486
available_since: latestTerminal.at.toISOString(),
478487
};
479488
} else if (latestQuota) {
480-
const lastFailure = asDate(state.last_failure_at);
481-
const separated = !lastFailure || latestQuota.at - lastFailure >= fiveHours;
482-
if (separated) {
483-
const failures = state.consecutive_failures + 1;
484-
const nextProbe =
485-
failures >= 3
486-
? nextDailyProbe(latestQuota.at)
487-
: new Date(latestQuota.at.getTime() + retryDelay);
488-
state = {
489-
...state,
490-
consecutive_failures: failures,
491-
last_failure_at: latestQuota.at.toISOString(),
492-
mode: failures >= 3 ? 'daily' : 'normal',
493-
next_probe_at: nextProbe.toISOString(),
494-
probe: null,
495-
};
496-
} else {
497-
state.probe = null;
498-
if (!asDate(state.next_probe_at) && lastFailure) {
489+
const probeRequestedAt = asDate(state.probe?.requested_at);
490+
const quotaAnswersProbe =
491+
!probeRequestedAt || latestQuota.at >= probeRequestedAt;
492+
if (quotaAnswersProbe) {
493+
const lastFailure = asDate(state.last_failure_at);
494+
const separated =
495+
!lastFailure || latestQuota.at - lastFailure >= fiveHours;
496+
if (separated) {
497+
const failures = state.consecutive_failures + 1;
499498
const nextProbe =
500-
state.mode === 'daily'
501-
? nextDailyProbe(lastFailure)
502-
: new Date(lastFailure.getTime() + retryDelay);
503-
state.next_probe_at = nextProbe.toISOString();
499+
failures >= 3
500+
? nextDailyProbe(latestQuota.at)
501+
: new Date(latestQuota.at.getTime() + retryDelay);
502+
state = {
503+
...state,
504+
consecutive_failures: failures,
505+
last_failure_at: latestQuota.at.toISOString(),
506+
mode: failures >= 3 ? 'daily' : 'normal',
507+
next_probe_at: nextProbe.toISOString(),
508+
probe: null,
509+
};
510+
} else {
511+
state.probe = null;
512+
if (!asDate(state.next_probe_at) && lastFailure) {
513+
const nextProbe =
514+
state.mode === 'daily'
515+
? nextDailyProbe(lastFailure)
516+
: new Date(lastFailure.getTime() + retryDelay);
517+
state.next_probe_at = nextProbe.toISOString();
518+
}
504519
}
505520
}
506521
}
507522
508523
const effectiveAvailableSince = asDate(state.available_since);
509524
510525
const pendingByKey = new Map(
511-
pending.map((item) => [`${item.pr}:${item.head_sha}`, item]),
526+
pending.map((item) => [
527+
`${item.pr}:${item.head_sha}:${item.base_sha}`,
528+
item,
529+
]),
512530
);
513531
if (state.probe) {
514-
const key = `${state.probe.pr}:${state.probe.head_sha}`;
532+
const key = `${state.probe.pr}:${state.probe.head_sha}:${state.probe.base_sha}`;
515533
if (!pendingByKey.has(key)) {
516534
state.probe = null;
517535
} else {
@@ -554,6 +572,7 @@ jobs:
554572
state.probe = {
555573
pr: candidate.pr,
556574
head_sha: candidate.head_sha,
575+
base_sha: candidate.base_sha,
557576
requested_at: now.toISOString(),
558577
comment_id: Number(comment.data.id),
559578
};
@@ -572,7 +591,13 @@ jobs:
572591
}
573592
}
574593
575-
if (JSON.stringify(state) !== JSON.stringify(originalState)) {
594+
const shouldCheckpointDefaultPush =
595+
context.eventName === 'push' &&
596+
context.ref === `refs/heads/${defaultBranch}`;
597+
if (
598+
shouldCheckpointDefaultPush ||
599+
JSON.stringify(state) !== JSON.stringify(originalState)
600+
) {
576601
await writeState(state);
577602
}
578603

0 commit comments

Comments
 (0)