Skip to content

The cookbook race that reddened two branches in one afternoon - #207

Merged
rohanrkamath merged 2 commits into
mainfrom
fix/cookbook-recipe-race
Sep 14, 2026
Merged

rohanrkamath merged 2 commits into
mainfrom
fix/cookbook-recipe-race

Conversation

@arpanghoshal

@arpanghoshal arpanghoshal commented Sep 14, 2026

Copy link
Copy Markdown
Member

test_every_recipe_runs_offline_and_is_repeatable[verify-in-github-actions] failed once on release/0.11.0 and once on a v0.12 branch, passed on re-run, and passed 19/19 in isolation. I recorded it in #206 as an unexplained flake rather than as fixed. It is neither.

The cause

Recipes ran in examples/cookbook/<name>/ itself, and two tests share a recipe. Under -n auto they land on different xdist workers and run concurrently in that one directory. verify-in-github-actions does this:

ctrlrun verify --json > verify-report.json
python -c "... open('verify-report.json') ..."
rm -f verify-report.json

One worker's rm -f lands between the other's write and read. _run invokes bash -euo pipefail, so the FileNotFoundError becomes a non-zero exit and the assertion fires with nothing wrong in the library. ctrlrun verify spawns eight processes for G4, so the window is widest exactly when the suite is busiest, which is why the full parallel run reproduced it and -k cookbook never did.

Measured

Four concurrent runs of that recipe, with the flags the test uses:

shared directory   2 rc=0   2 rc=1
one copy per run   4 rc=0

The fix

Each test copies the recipe into its own tmp_path. The repeatability test still runs twice in one directory, which is its whole point, and that directory is now its own rather than the repository's. The suite also stops writing into the working tree, so git status after a run says what it should.

Gate

All checks passed!            (ruff, ruff format, mypy --strict)
4576 passed, 6 warnings in 185.25s

Worth stating plainly: a suite that fails once in a while teaches people to re-run it, and this project's gate is only worth anything while green means green. I should have chased this the first time instead of labelling it.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Improved cookbook test isolation by running each recipe in a private temporary workspace.
    • Prevented concurrent test runs from interfering with one another.
    • Avoided test-generated files being written to the project’s working directory.
    • Preserved repeatability checks within the same isolated workspace.

`test_every_recipe_runs_offline_and_is_repeatable[verify-in-github-actions]`
failed once on `release/0.11.0` and once on a v0.12 branch, passed on re-run,
and passed 19/19 in isolation. I recorded it in #206 as an unexplained flake
rather than as fixed. It is neither: it is a shared-directory race with a
one-line cause.

Recipes ran in `examples/cookbook/<name>/` itself, and **two tests share a
recipe**. Under `-n auto` they land on different workers and run concurrently
in that one directory. `verify-in-github-actions` writes `verify-report.json`,
reads it, then `rm -f`s it, so one worker's delete lands between the other's
write and read. `_run` invokes `bash -euo pipefail`, which turns the resulting
`FileNotFoundError` into a non-zero exit, and the assertion fires with nothing
wrong in the library.

Measured, four concurrent runs of that recipe with the flags the test uses:

    shared directory   2 rc=0   2 rc=1
    one copy per run   4 rc=0

Each test now copies the recipe into its own `tmp_path`. The repeatability test
still runs twice in **one** directory, which is its whole point, and that
directory is now its own rather than the repository's. The suite also stops
writing into the working tree, so `git status` after a run says what it should.

Worth stating plainly: a suite that fails once in a while teaches people to
re-run it, and this project's gate is only worth anything while green means
green. I should have chased this the first time instead of labelling it.

Signed-off-by: arpan <contact@arpanghoshal.com>
@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: e88165b3-f96a-4af4-beb2-7be8b481a22d

📥 Commits

Reviewing files that changed from the base of the PR and between 8a81289 and 8bda466.

📒 Files selected for processing (1)
  • tests/test_cookbook.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Cookbook tests now copy each recipe into a temporary per-test directory. Recipe processes run from the copy. Repeatability checks execute twice in the same sandbox, and refusal checks use a separate sandbox.

Changes

Cookbook test isolation

Layer / File(s) Summary
Sandboxed recipe execution
tests/test_cookbook.py
The tests copy recipes with _sandbox, pass the sandbox path to _run, and use it as the subprocess working directory. The repeatability test runs twice in the same sandbox. The refusal test uses its own sandbox.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 173ec

This test-only change correctly isolates cookbook runs and removes the reported shared-directory race without introducing a demonstrated merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the cookbook test race that the pull request fixes. It is concise and directly related to the main change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cookbook-recipe-race

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rohanrkamath
rohanrkamath merged commit 320f0b0 into main Sep 14, 2026
15 of 16 checks passed
@rohanrkamath
rohanrkamath deleted the fix/cookbook-recipe-race branch September 14, 2026 21:37
@arpanghoshal

Copy link
Copy Markdown
Member Author

The red docs job here is not this branch. It is the API reference drifting against kernel main, which now carries #208: Decision and POLICY_UNAPPROVED moved to decision.py, so 83 generated pages and 38 CLAIMS.md citations changed their source locations.

This branch has no same-named docs branch, so CI pairs it against docs main, which does not have the regeneration yet. ctrlrun-docs#39 carries it and is green. Re-running this job after #39 merges will clear it.

The check jobs on all four Pythons, package, adapters, fuzz, verify, gate, dco and CodeQL are green here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants