fix(wait): stop sharing exit code 2 with Click's usage errors - #5
Merged
Merged
Conversation
`run wait` exits to tell a script what happened -- 0 everything passed, 1
something failed, and it used 2 for a timeout. But Click already exits 2
for any usage error: an unknown flag, a missing argument, an
out-of-range --interval. All three verified against the built command.
So the one thing the feature promises -- "gate on the outcome without
parsing anything" -- is the thing that breaks. A script written as
sp run wait $ID
case $? in 0) merge ;; 1) block ;; 2) sleep 600; retry ;; esac
reads a mistyped --timeout as "still running" and retries forever a
command that never made a single API call. Nothing crashes and nothing
is printed; the script just takes the wrong branch quietly, which is the
failure mode exit codes exist to prevent.
Timeout is now 9. The README's table stopped at 8 and skipped 2 already,
which is why that gap was there; both are now stated explicitly so the
next command does not rediscover this.
Also: always render a collection.
payload = rows[0] if len(rows) == 1 else {'data': rows}
made the output shape depend on how many ids were passed, so
`sp run wait $IDS | jq '.data[]'` worked until the list happened to hold
one run. Every other list in the CLI is {'data': [...]} whether it has
one row or a hundred.
And a note in the docstring that a `pass` status can come from a run that
recorded results for a fraction of its samples -- the API derives it from
the rows that exist, not the ones expected -- so a green wait is not
proof of coverage. Production run 9360 reports `pass` on 1 of 237.
gaurav02081
force-pushed
the
fix/run-wait-exit-code
branch
from
August 15, 2026 18:21
ea1dfe1 to
fe8384a
Compare
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.
Follow-up to #3. Three things, one of which I think matters.
The exit code collides with Click's
run waituses2for a timeout, but Click already exits2on any usage error. Verified against the built command:That undoes the feature's own promise — "a script can gate on the outcome without parsing anything". Written the obvious way:
a mistyped
--timeoutreads as "still running", and the script retries forever a command that never made an API call. Nothing crashes, nothing is printed — it just takes the wrong branch silently.Timeout is now 9. The README's table stopped at 8 and skipped 2 already, which is why the gap was there; both facts are now written down.
The payload shape depends on the argument count
So
sp run wait $IDS | jq '.data[]'works until the list happens to hold a single run. Every other list in the CLI is{'data': [...]}whether it has one row or a hundred;waitnow matches.A
passis not proof of coverageNoted in the docstring rather than changed. The API derives run status from the result rows that exist, not the ones expected, so a run that recorded 1 of 237 samples still reports
pass— production run 9360 does exactly that. Worth knowing for a command whose whole job is gating a script.Testing
Two new tests: one asserting usage errors and a timeout are distinguishable, one that the payload is a collection either way. Updated the existing timeout test. 218 pass; isort/pycodestyle/pydocstyle/mypy clean.
Nice work on the command itself — the stderr/stdout split and treating an unknown status as terminal are both the right calls.