Repository navigation
Stop the lifecycle CI jobs failing at random - #218
Conversation
Quest-Claim: fb39382efc3023a6
Hosted macOS runners can queue past the job's timeout, which reports a job that never ran as failed. Pull requests keep native macOS coverage through Release's lifecycle checks; main still checks the flake's macOS build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On windows-11-arm, GitHub's hosted runner agent (provjobd, started by hosted-compute-agent) periodically opens the images of running processes without delete sharing for a few hundred milliseconds. When that caught the check's last quest.exe run, removing the check's copy of the binary failed with EBUSY. Run the caller's binary in place, and let the runner discard install-check.ps1's scratch under RUNNER_TEMP rather than deleting it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c8f9c206f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Merging as a squash at 7c8f9c2.
(Written by Claude Opus 5.5) |
Resolve the quest/m0/README.md conflict by dropping both finished quests (lifecycle-flakes merged in #218, worker-tests finishes here). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completes
quest/m0/lifecycle-flakes.md: the lifecycle CI jobs no longer fail for reasons outside the code under test.Windows
EBUSYCause. On
windows-11-armhosted runners, GitHub'shosted-compute-agentstarts an unsigned helper,%TEMP%\provjobd.exe<N>. About every 15–35 s it opens the image of a running process. It first opens itwithout delete sharing for 300–450 ms (
RW-), then with delete sharing for about 3 s (RWD). If that scancaught the check's last
quest.exerun,rmSync(work)hit theRW-window while removing the check's copy atwork\tool bin\quest.exe, and failed withEBUSY.windows-2022has no failures, and its Defender real-timeprotection is off. The JS build in Check never failed because
bun.exelives outside the temp directory.Reproduction. I used a throwaway
diag/lifecycle-ebusybranch, now deleted. It looped the check on nativerunners, running Sysinternals Handle when the check failed and polling it in the background:
EBUSYin 390 runs onwindows-11-arm(0 in 80 onwindows-2022). Each time, the only thing leftwas
tool bin\quest.exe, held byprovjobd.exe. The failingrmstarted 0 ms after the lastquest uninstallexited, inside a polled
RW-window (06:22:23.003–23.461,rmat 23.067). It was removable a moment later.lifecycle-check.mjsand 120 runs ofinstall-check.ps1 -Method archiveonwindows-11-arm.Fix. Nothing deletes an executable the check just ran. There are no retries, sleeps, or ignored errors.
lifecycle-check.mjsruns the caller's binary in place instead of copying it into the directory it deletes.lifecycle-check.shcopies the binary into"$work/tool bin/"first, which keeps the Linux/macOS coverage of abinary path with spaces.
install-check.ps1puts its scratch underRUNNER_TEMP, which the runner empties after every job, and nolonger removes it itself. It already installs to a path with spaces (
quest install <guid>). The script isCI-only (Release and Install check), so it now refuses to run without
RUNNER_TEMP.macOS queue timeout
When hosted macOS runners are short, the
lifecycle (macos-14)job waits in the queue untiltimeout-minutescancels it. That happened on kixelated/quest#191 (queued 15:40:13,
cancelled 15:55:14, no runner). The job then shows as failed. Pull requests now run
lifecycleonubuntu-latestonly.macos-14still runs on pushes tomainand on manual runs.macOS stays covered on pull requests by Release. Its native
check (aarch64-apple-darwin)andcheck (x86_64-apple-darwin)jobs run the lifecycle check on any PR that touchessrc/,scripts/, or thelockfiles. The only macOS check missing from PRs is the flake's own Nix build on Darwin, which now runs on
main.Choices made without asking
failure. A cancelled job can't be made to report as skipped.
install-check.ps1now needsRUNNER_TEMP, so running it locally is unsupported. It never had any local use.dist/quest.jsfrom the checkout. That path has no spaces, so thespaces coverage on Windows now comes from the native binary that Release and Install check run.
Validation
just checkandjust testpassed locally (both lifecycle builds included), as didquest check --base origin/main.windows-11-armand macOS lifecycle checks.Suggested follow-ups
checkjobs can hit the same queue timeout. On a PR, that shows as a failed (non-required)Release check.
test/gate.test.ts"concurrent processes never admit past the headroom" (5 of the last 15 failed Check runs),test/move.test.ts"refuses a claimed quest" timing out at 5 s, andtest/start.test.tstimeouts.quest startfailed once with "git push to origin failed" even though the remote printed the "Create a pullrequest" hint. A retry worked. The error dropped the porcelain stdout, which would have explained it.
🤖 Generated with Claude Code
(Written by Claude Opus 5.5)