feat(gpush): print what a failed CI run reported - #372
Merged
Merged
Conversation
When a CI run failed, gpush printed only "CI failed (Standards Check: failure)", so finding the failed linter meant opening the run in a browser. For each failed job, gpush now prints the job's check-run annotations, at most 40 lines per job, followed by the job URL. It prints failure and warning levels only, sorted by start_line: the API returns them newest first. Notices and the runner's "Process completed with exit code N" line are dropped. When a job has no readable annotations, gpush prints the "##[error]" lines of its failed-step log instead. It never prints the raw log, which is mostly checkout noise. The "CI failed (...)" line and the exit code are unchanged. The added calls cannot change the exit path; a failed read just prints less. Measured 2026-09-25 with a fine-grained PAT against twistedmelonman/claude-config run 35944355297: the annotations endpoint and `gh run view --job <id> --log-failed` both returned data, and the job's databaseId is the check-run id. Test: bash/tests/test-gpush-wrapper-failure-detail.sh runs gpush end to end against stub git and gh (the stub gh runs the wrapper's jq filters through real jq). Against origin/main's wrapper, 6 of its 11 checks fail. Closes smartwatermelon/dev-env#113
This comment has been minimized.
This comment has been minimized.
|
No blocking issues found. The new failure-detail function correctly filters and displays CI annotations, gracefully degrades on API errors, and integrates safely into the existing gpush flow. Array handling under set -u is correct, and output formatting is secure. VERDICT: PASS |
twistedmelonman
deleted the
claude/feat-gpush-failure-detail-8a854048
branch
September 25, 2026 22:13
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.
What
When CI failed, gpush printed one line:
CI failed (Standards Check: failure). To see which linter failed, you had to open the run in a browser.gpush now prints what each failed job reported before that line:
That is real output from the new helper, run against a real failed run from 2026-09-24.
How it works (
_gpush_print_failure_detailinbash/gpush-wrapper.sh):databaseIdis also its check-run id.start_line, because the API returns them newest first. It drops notices and the runner'sProcess completed with exit code Nline. When an annotation has a title, it prints the title first. Since feat(standards): name what failed, not just that something did smartwatermelon/github-workflows#176, the title is the linter name and the message holds up to 20 lines of findings.##[error]lines fromgh run view --job <id> --log-failed. The raw log is never printed. For this run it was 549 lines, almost all checkout output.The
CI failed (...)line and the exit code have not changed. A failed read in the helper only means less output. It can't change how gpush exits.Token check
Fine-grained PATs can't read some Checks endpoints, so I tested this one before writing any code. With the twistedmelonman fine-grained PAT (
github_pat_prefix), against twistedmelonman/claude-config run 35944355297, job 107458893019:gh api repos/.../check-runs/107458893019/annotationsreturned all 7 annotations.gh run view --job 107458893019 --log-failedreturned the log, including 3##[error]lines.So this annotations endpoint reads fine with that token type. (An earlier dev-env note records that GraphQL CheckRuns come back null under a fine-grained PAT. I did not re-measure that here.)
Not verified: gpush in an interactive shell with no
GH_TOKENset, which uses the keyring identity. I can't test that path, since agents are barred from the keychain. An OAuth token should have at least the same access, but no one has measured it.The live run above predates #176, so its annotations have no titles and no findings. No run in the new format has failed yet, so I couldn't observe one live. What the live run proves is the mechanism: the endpoint, the token, and the job-to-check-run id mapping. The test fixture covers the new format: a titled annotation with findings on several lines.
Tests
New
bash/tests/test-gpush-wrapper-failure-detail.shruns gpush end to end with stubgitandghbinaries on PATH. The stubghpasses the wrapper's own-q/--jqexpressions through real jq. That way the test checks the real filters, not copies of them. Fixture shapes come from the live run above.Against origin/main's
gpush-wrapper.sh, 6 of its 11 checks fail (known-bad):linter annotation title and finding are printedfinal error annotation is printedannotations are printed oldest firstfailed job URL is printedempty annotations fall back to the log's error lines onlylong annotations are cut to the line limit with a countThe other five are guards and pass on both: the exit code, the summary line, dropped notices, no query for successful jobs, and a passing run printing nothing extra.
The full suite ran in pre-push: 35 passed, 0 failed.
shellcheck -S infois clean on both files.test-my-prs-issues.shfailed once when I ran the suite with the shell's cwd outside the repo. It fails the same way on the clean main checkout (caller cwd unchanged — expected [.../dotfiles], got [.../dev-env]), so this change didn't cause it. It passed in the pre-push run.Closes smartwatermelon/dev-env#113