Report the gh error, not just an exit code - #50
Merged
Conversation
The 2026-09-05 reconciler run said only: FAIL labels: could not list (exit 1) FAIL labels: could not list (exit 1) The cause was HTTP 403 — the swimblocks-reconciler App had no issues permission, and labels sit under issues for GitHub Apps. gh had said so on stderr, and the script threw it away, so establishing that took reading the workflow logs, noticing the failures were confined to private repos, and querying the installation to compare declared against granted permissions. The output could have handed it over. These calls run with capture_output=True, so the message was already on CalledProcessError.stderr. gh_error() appends its last line — the "gh: ... (HTTP 403)" summary rather than the noise above it — and falls back to the exit code when stderr is empty. Applied to the label paths and to the ruleset apply. The private-repo branch-protection SKIP is left alone: an unsupported plan is the documented expected outcome and that message already explains itself. The failure also printed twice per repo, because apply_labels and verify_labels each call list_labels and each reported. main() discarded apply_labels' return value entirely, so verifying ran even when applying had already failed. It now verifies only if applying got that far, which fixes the duplicate and stops a real failure being dropped. Against a live failure: before: FAIL labels: could not list (exit 1) after: FAIL labels: could not list: gh: Not Found (HTTP 404) Closes #49 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CgLE8cg9huy2EZnRoXhmwp
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.
Closes #49
What & why
The reconciler run on 2026-09-05 reported this and nothing else:
The cause was
HTTP 403: theswimblocks-reconcilerApp had noissuespermission, and labels sit underissuesfor GitHub Apps.ghhad said so on stderr, and the script discarded it — so establishing it meant reading the workflow logs, noticing the failures were confined to private repos, and then querying the installation to compare the App's declared permissions against the ones actually granted.These calls run with
capture_output=True, so the message was already sitting onCalledProcessError.stderr.gh_error()appends its last line — thegh: … (HTTP 403)summary rather than the noise above it — and falls back to the exit code when stderr is empty. Applied to the label paths and the ruleset apply.Not applied to the private-repo branch-protection
SKIP. An unsupported plan is the documented expected outcome there and the message already explains itself; appending a rawgherror would make a normal condition read like a fault.A second bug, found while writing it
main()discardedapply_labels' return value:Two consequences. The failure printed twice per repo, because
apply_labelsandverify_labelseach calllist_labelsand each reported. And a genuine apply failure could be dropped whenever verification happened to pass. It now verifies only if applying got that far.Testing
ruff check .clean.pytest -q— 26 passed, up from 21; five new tests ongh_errorcovering the real 403 text, multi-line stderr, empty stderr,Nonestderr, and whitespace-only stderr.Proved against a live
ghfailure rather than only mocks:Also confirmed the underlying incident is resolved and the reconciler is green end to end —
issues: writeaccepted on the installation, and a deliberately deleted label recreated on a private repo:Which is the small irony of this PR: the run that would have shown off the better message came back clean.
Checklist
ruff check .clean (Python repos)🤖 Generated with Claude Code