Report severed exec streams as execution_timeout, not success#318
Open
eapache-opslevel wants to merge 1 commit into
Open
Report severed exec streams as execution_timeout, not success#318eapache-opslevel wants to merge 1 commit into
eapache-opslevel wants to merge 1 commit into
Conversation
When a job pod's exec stream is torn down before the command sequence finishes (pod evicted or exceeded its lifetime), the k8s API server can close the stream without delivering an exit status. StreamWithContext then returns nil, so the runner reported the job as `success` with a missing/partial outcome. For repo-check batches on large repos that time out mid-loop, this silently dropped the result and prevented retries. Emit a unique completion marker from the shell's EXIT trap and tee stdout through a detector. A nil error with no marker means the shell never exited (stream severed) -> report execution_timeout (retryable) instead of success. The EXIT trap covers normal completion and explicit `exit 0` (used by some templates) but not SIGKILL/torn-down streams. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issues
Relates to https://gitlab.com/jklabsinc/OpsLevel/-/issues/14761.
Summary
While investigating #14761 we found repo-check jobs on large repos (e.g. a 25k-file repo, ~100 checks) that run for ~26 min, stop mid-loop around check 84/100, and are recorded as
successwith a missingresultoutcome — so the check silently produces no result and the job never retries.Root cause on the runner side: the job is exec'd into a
sleep <lifetime>pod, and the outcome is decided purely by whetherStreamWithContextreturns an error. When the pod is terminated (evicted / exceeds its lifetime) while the exec is streaming, the API server can close the stream without delivering a non-zero exit status, soStreamWithContextreturnsniland the job is misreported as a success.Change
EXITtrap, and tee stdout through a small detector (markerWriter).execution_timeout(retryable) instead ofsuccess.EXITtrap fires on normal completion and explicitexit 0(used by theRepoPropertyInferenceV1template), but not onSIGKILL/ torn-down streams — which is exactly the case we want to catch. On aset -efailure the trap also fires, butrunErris non-nil then, so we reportFailedbefore checking the marker.This is fix (3) of three identified in #14761.
Changelog
execution_timeoutinstead ofsuccesschangieentry (Bugfix)Tophatting
New unit tests cover the marker detector (single write, split-across-writes, absent, large-stream-then-marker) and the marker identity:
Shell verification of the
EXITtrap (marker on normal exit and explicitexit 0; failing command still exits non-zero so it's reportedFailed):🤖 Generated with Claude Code