Repository navigation
rubyspec-gate's expected-PASS list can be split into shards - #8012
Merged
Merged
Conversation
make gate's slowest leg is rubyspec-gate's language suite, which runs every expected-PASS example in one pass with no way to split it across CI jobs. RUBYSPEC_SHARD=k/n keeps only every n-th expected-PASS example per suite (0-indexed offset k-1), so a fork running the gate's legs as parallel jobs can split language's 1,025 examples into two (or more) jobs instead of one. Each shard still runs its own "every listed example ran" and "no regression" check; running k=1..n covers the full expected-PASS list exactly once, so the shards' combined result is the same gate the unsharded target runs. Without the variable, the target is unchanged. Verified locally on core/range: a 1/2+2/2 and a 1/3+2/3+3/3 split each reproduce the full 200-example expected-PASS set with no overlap and no gaps, every shard passes with 0 regressions, and an unsharded run is byte-for-byte identical to the one before this change. The same partitioning math checked against language's actual expectations file (1,025 examples -> 513 + 512, union equal to the unsharded list). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
An out-of-range RUBYSPEC_SHARD (k=0, k>n, or n=0) made the awk filter match no line, and a non-numeric one crashed awk outright -- in both cases the recipe kept going with an empty expected-PASS list, and the gate's own "ran == want, no non-PASS" check passed vacuously: "all 0 expected-PASS examples still pass" reads as a real pass. Reject the variable up front unless it is k/n with k and n both positive integers and k <= n, before it ever reaches the awk filter. Found by CodeRabbit on the fork PR; verified the vacuous-pass failure mode by hand before fixing it (RUBYSPEC_SHARD=0/2 and =5/2 each gave an empty shard with no error from the unguarded version). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Gate: green tree 196d316 master 9c7ea3c (linux-x86_64 gcc-13.3.0) tests 6421/0
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (1)
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. Comment |
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.
make gate takes a while even in parallel: splitting it across fork Actions jobs (corpus in TEST_SHARD slices, one job per rubyspec-gate suite, props, bench, optcarrot) gets it down to about 11-14 minutes, except for one leg. rubyspec-gate's language suite has no way to split: it runs every expected-PASS example (1,025 today) in one job, and stays the longest leg even with 4 workers.
RUBYSPEC_SHARD=k/n keeps only every n-th expected-PASS example per suite (0-indexed offset k-1), so a CI fork can run language (or any suite) as two or more parallel jobs instead of one. Each shard still runs the gate's own checks per suite ("every listed example ran", "no regression"); running every k from 1 to n covers the full expected-PASS list exactly once, so the shards' combined result is the same gate the unsharded target runs. Without the variable, make rubyspec-gate is unchanged.
The variable is validated before use: CodeRabbit caught, on the fork PR, that an out-of-range RUBYSPEC_SHARD (k=0, k>n, or n=0) made the awk filter match no line, and a non-numeric one crashed awk outright -- in both cases the recipe kept going with an empty expected-PASS list, and the gate's own "ran == want, no regression" check passed vacuously ("all 0 expected-PASS examples still pass" reads as a real pass). The variable is now rejected up front unless it is k/n with both positive integers and k <= n.
Verified locally on core/range (200 expected-PASS examples): a 1/2+2/2 split and a 1/3+2/3+3/3 split each reproduce the full example set with no overlap and no gaps, every shard passes with 0 regressions, and a run without RUBYSPEC_SHARD is byte-for-byte identical to the one before this change. The same partition math checked against language's actual expectations file (1,025 -> 513 + 512, union equal to the full list). The validation was checked against the actual failure modes (RUBYSPEC_SHARD=bogus, =0/2, =5/2) before and after the fix.
Related: #6762 proposes widening what the gate covers; no overlap with this change, since #6762 is about which examples get enrolled, not about splitting execution of an already-enrolled suite.
Gate ran sharded on the fork: https://github.com/yosefbennywidyo/spinel/actions/runs/37731651385 (17 jobs, all green, ~14 min). The commit's own
Gate:trailer records it:Gate: green tree 196d31629368 master 9c7ea3c (linux-x86_64 gcc-13.3.0) tests 6421/0
🤖 Generated with Claude Code
Summary by CodeRabbit