Repository navigation
feat: distinguish failures by exit code and add --exec to the CLI - #75
Merged
Merged
Conversation
Every CLI failure exited 1, so a caller could not tell a rate limit from a revoked key from an installation that does not exist, and retried all of them. The library made that unavoidable: only throttling had a typed error, and every other rejection collapsed into a fmt.Errorf string the CLI would have had to pattern-match. APIError carries the status code instead. Its Error() renders the same string the fmt.Errorf did, so callers that log or match on the message keep working, and the CLI now maps status to an exit code: 3 for a credential GitHub refused, 4 for throttling, 5 for an App that is not installed where it was asked to be. A missing key file and a rejected key both exited 1 before and now exit 2 and 3. --exec runs a command with the credential in $GITHUB_TOKEN and prints it nowhere. A printed installation token stays valid for an hour in every log, scrollback and agent transcript that captured the output, and --exec is the way not to put it there. Agent mode was deliberately limited to errors. Grafana's gcx flips its default output format when it detects an agent, which works because its output is data; ours is a credential meant for $(githubauth token), and flipping it would have made the README's own curl example send a JSON object as the bearer token inside an agent session. So detection routes failures to stdout as one githubauth.error document and adds a stderr hint, and leaves the token line alone. Running the suite inside a coding agent showed why this matters: the tests inherited CLAUDECODE=1 and found errors on stdout. They now pin GITHUBAUTH_AGENT_MODE=0, which is what any downstream suite that shells out to githubauth will need.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #75 +/- ##
==========================================
- Coverage 96.96% 96.75% -0.22%
==========================================
Files 5 8 +3
Lines 462 586 +124
==========================================
+ Hits 448 567 +119
- Misses 14 19 +5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Summary
Every CLI failure exits 1 today, so a caller cannot tell a rate limit from a
revoked key from an installation that does not exist, and retries all of them.
The library makes that unavoidable: only throttling has a typed error, and every
other rejection collapses into a string the CLI would have to pattern-match.
This adds
APIErrorto the library, an exit code per failure class to the CLI,and
--exec, which hands the credential to a command instead of printing itwhere a log or an agent transcript will keep it for the hour it stays valid.
Changes
APIError{StatusCode, Message}replaces an untypedfmt.Errorffor every non-throttling rejection.Error()renders the identical string, so existing callers keep working.githubauth help.--exec -- <cmd>runs a command with the token in$GITHUB_TOKEN, prints nothing, and exits with the command's own code.--jsonor a detected coding agent, a failure is onegithubauth.errorJSON document on stdout with stderr silent, carryingexit_code,status_code,retry_after_secondsand suggestions.Rationale
Agent mode changes errors only. Grafana's gcx
flips its default output format on detection, which works because its output is
data; ours is a credential meant for
$(githubauth token), and flipping it wouldmake the README's own curl example send a JSON object as the bearer token inside
an agent session.
Migration Notes
$? -eq 1now sees 2, 3 or 5 for some failures. The library change is additive.githubauthfrom inside a coding agent should setGITHUBAUTH_AGENT_MODE=0. This repo's own suite needed it — the tests inheritedCLAUDECODE=1and found errors on stdout.CHANGELOG.mdis untouched, since this repo cuts it at release time.🤖 Generated with Claude Code