ci: pin codex-action to v1.11 and cap review-job runtime - #141
Conversation
🤖 Codex Code ReviewNo findings. The changes look aligned with the stated goal: the model job loses write permissions, the review output is handed off via artifact, and the posting job can still run after a teardown failure without running untrusted code. The added timeouts also cap the observed runner-idle failure mode without changing normal review behavior. Residual risk: if |
🤖 Claude Code ReviewReviewed the two workflow files on the merge ref. The core design — cap the hang with A few real issues: 1. When Impact today is small: fork PRs get a read-only if: ${{ !cancelled() && needs.codex-review.result != 'skipped' }}2. Empty review fails the check; a crashed review passes it ( The two failure paths land on opposite check colors:
So the harder failure produces the friendlier signal. Previously an empty message just skipped posting silently. Worth picking one convention — either treat "no artifact" as a failure too, or downgrade the empty case to 3.
4. Pre-existing, adjacent: git fetch origin ${{ github.event.pull_request.base.ref }}
DIFF=$(git diff origin/${{ github.event.pull_request.base.ref }}...HEAD --stat)Git ref names permit Nothing blocking on the artifact-handoff mechanics themselves; items 1 and 3 are the ones I'd want fixed before merge. |
🤖 Codex Code ReviewFindings: None. The changes look sound for the stated goal: the model jobs are read-only, posting is isolated to a separate write-token job, the Codex teardown hang is bounded, and the artifact handoff avoids shell evaluation of model output. Residual risk: I only reviewed the workflow diff statically; I did not execute |
🤖 Claude Code ReviewReviewed the two workflow files on the merge ref. The overall shape is right: pinning Empty review now turns a green PR into a red check
So a run where codex exits 0 but produces no final message now fails the PR instead of quietly skipping. Cheapest fix that keeps the artifact isolation: - name: Save review output
if: steps.run_codex.outputs.final-message != ''
...
- name: Upload review output
if: steps.run_codex.outputs.final-message != ''Then the missing artifact takes the existing
|
47897c0 to
681defe
Compare
🤖 Codex Code ReviewFindings
Open Questions
|
🤖 Claude Code ReviewVerified the diff against The substance is sound: Two things worth raising: 1. The title's second claim isn't in the diff. "isolate its posting job" — 2. The cap doesn't change the check's outcome, only its duration. Per the comment, the stall occurs after every step completes — so the review comment has already been posted by the time the job hangs. Minor, pre-existing, in a file this PR touches: codex's |
codex-code-review has been hanging: Codex prints its final message and token count, the step then emits no `##[end-action]`, and the job idles until GitHub's 60-minute default kills it. 287 runs since 2026-04-28 never exceeded 15 minutes; since 2026-08-24T22:25Z there have been 18 hangs of 23-64 minutes. It blocked PR #133 and several since. Cause is upstream, in the action rather than in anything of ours: the floating `@v1` tag moved to v1.12 (86365089) on 2026-08-20T23:38:51Z, and v1.12 rewrote the privilege-isolation launch path. It spawns the CLI with inherited stdio and waits on the child's `close` event, so a descendant outliving the turn keeps those descriptors open and the action never returns. Tracked upstream as openai/codex-action#150 and #169; a wrapper fix using private pipes and completing on `exit` is proposed in their #151. So pin to v1.11 (52fe01ec), which is what other affected orgs are running. Worth recording how this was nearly mis-diagnosed, because the trap is generic. The first pass here blamed an unpinned CLI: `codex-version` defaults to empty, so every run installs whatever npm `latest` is at that moment, and 0.149.1 published 2026-08-24T00:32Z — 22 hours before our first hang. That fit, and it was wrong. Our 20 clean runs before the boundary were all light (max 3 min), and the failure is workload-sensitive, so the CLI-version boundary and the action-version boundary are perfectly confounded in our data: both explain it equally well and our runs cannot separate them. What separates them is evidence we do not own — another org hit the same hang on codex-version 0.147.0, which predates the suspect release, and a third has 145/145 clean on v1.11 against 69/74 on v1.12 with model and effort held fixed. The intermittency is the reason a green run proves nothing: on 2026-08-31 the same PR succeeded in 2 min at 14:38, hung 63 min at 14:45, and succeeded in 3 min at 15:05. timeout-minutes caps the damage at 10 minutes rather than 60. Note it is at JOB level deliberately — `timeout-minutes` does not apply to a step that `uses:` a composite action, so a step-level value here would silently do nothing. Claude's workflow gets the same guard at 15/5 minutes; it has never hung, but it runs the same class of model-driven step behind a floating tag. Deliberately NOT changed: posting stays inline in the same job. An earlier draft moved it to an artifact plus a separate posting job so a review would survive the hang, but in every observed hang the comment posted fine — posting runs before the stall. That solved a failure that never happened. 🤖 Built with SMT <smt@agora.build>
681defe to
3a2f751
Compare
🤖 Codex Code ReviewFindings
No other concrete issues found in the timeout additions or the pinning change. |
🤖 Claude Code ReviewReviewed both workflow files against the diff. The pin itself is the right call and the comment justifying it is unusually good — it distinguishes "a green run cleared it" from "controlled data indicts it," which is the distinction that actually matters for a nondeterministic hang. Two things worth resolving before merge. 1. The PR title claims something the diff doesn't do. Title says "cap the codex-review hang and isolate its posting job," but
Not urgent on its own — the trusted-author gate means the injecting party already has push access — but the same gate applies to 2. Unquoted Minor / no action needed:
Everything else — permissions scoping, the trusted-author gates, the |
Problem
codex-code-reviewhangs: Codex prints its final message and token count, the step then emits no##[end-action], and the job idles until GitHub's 60-minute default kills it. It blocked #133 and several PRs since.287 runs since 2026-04-28 never exceeded 15 minutes. Since
2026-08-24T22:25Zthere have been 18 hangs of 23–64 minutes.Cause
Upstream, in the action — not in anything of ours. This file was last edited 2026-06-16.
The floating
@v1tag moved to v1.12 (86365089) on 2026-08-20T23:38:51Z. v1.12 rewrote the privilege-isolation launch path (dropSudo/runCodexExec/linuxCredentials); it spawns the CLI with inherited stdio and waits on the child'scloseevent, so a descendant that outlives the turn holds those descriptors open and the action never returns.Tracked upstream as openai/codex-action#150 and #169. A wrapper fix (private pipes, complete on
exit) is proposed in their #151.Fix
Pin the action to v1.11 (
52fe01ec), the last release before the rewrite, which is what the other affected orgs are running.A near-miss worth recording
My first pass blamed the wrong thing, and the trap is generic enough to be worth writing down.
codex-versiondefaults to empty, so every run installs whatever npmlatestis at that moment.@openai/codex@0.149.1published2026-08-24T00:32Z— 22 hours before our first hang. Clean fit, and wrong.Our 20 runs before the boundary were all light (max 3 min) and the failure is workload-sensitive, so in our data the CLI-version boundary and the action-version boundary are perfectly confounded — both explain the evidence equally well, and no run of ours can separate them. What separates them is evidence we don't own: another org hit the same hang on
codex-version0.147.0, which predates the suspect release, and a third reports 145/145 clean on v1.11 vs 69/74 on v1.12 with model and effort held fixed.The intermittency is why a green run proves nothing. On 2026-08-31 the same PR succeeded in 2 min at 14:38, hung 63 min at 14:45, then succeeded in 3 min at 15:05.
Also in this PR
timeout-minutesat JOB level, capping a hang at 10 min instead of 60. Deliberately job-level:timeout-minutesdoes not apply to a step thatuses:a composite action, so a step-level value here would silently do nothing.claude-code-review.yml(15/5 min). It has never hung — this is a cap, not a fix — but it runs the same class of model-driven step behind a floating tag.Deliberately not done
Posting stays inline in the same job. An earlier draft of this PR moved it to an artifact plus a separate posting job so a completed review would survive the hang. But in every observed hang the comment posted fine — posting runs before the stall. It solved a failure that never happened, at the cost of an extra job and an artifact round-trip.
Generated with SMT smt@agora.build