fix(webhook): treat GitHub App resolution failures as terminal in command cores - #1095
Draft
Kiran01bm wants to merge 1 commit into
Draft
fix(webhook): treat GitHub App resolution failures as terminal in command cores#1095Kiran01bm wants to merge 1 commit into
Kiran01bm wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the durable issue_comment command-core error contracts so deterministic GitHub App resolution failures settle terminally (with an error recorded for triage) instead of being retried indefinitely, aligning behavior across apply/apply-confirm/unlock/rollback and the actor-authorization bootstrap seam.
Changes:
- Classifies
errGitHubAppResolutionas(retry=false, err)in apply/apply-confirm bootstrap and in unlock/rollback authorization-client creation paths. - Refactors
actorAuthorizationClientto return(*InstallationClient, error)so durable callers can distinguish deterministic App-resolution failures from transient client-creation failures. - Adds/extends contract tests to pin the retry disposition for deterministic vs transient failures at the App-resolution seam.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/webhook/apply_handlers.go | Treats App-resolution bootstrap failures as terminal-with-error in apply/apply-confirm; adds same disposition for unlock inference/authorization seams. |
| pkg/webhook/actor_authorization.go | Changes authorization client helper to return an error cause (instead of a blocked bool) while still failing closed and attempting best-effort comments. |
| pkg/webhook/rollback.go | Treats authorization-client App-resolution failures as terminal-with-error in rollback core. |
| pkg/webhook/plan.go | Updates actor-authorization client callsite for new (client, err) contract; continues fail-closed behavior for plan. |
| pkg/webhook/control.go | Updates control command actor-authorization client callsite for new (client, err) contract; continues fail-closed behavior for control commands. |
| pkg/webhook/apply_error_contract_test.go | Adds contract test pinning apply core’s terminal disposition for errGitHubAppResolution in bootstrap. |
| pkg/webhook/apply_confirm_error_contract_test.go | Adds contract test pinning apply-confirm core’s terminal disposition for errGitHubAppResolution in bootstrap. |
| pkg/webhook/unlock_test.go | Adds an authorization-enabled handler helper to support new unlock authorization-client seam contract tests. |
| pkg/webhook/unlock_error_contract_test.go | Adds contract tests pinning unlock’s terminal vs retryable disposition for App-resolution vs transient auth client failures. |
| pkg/webhook/rollback_error_contract_test.go | Adds contract tests pinning rollback’s terminal vs retryable disposition for App-resolution vs transient auth client failures. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+16
to
+17
| // when PR command authorization is enabled; a nil client with a nil error | ||
| // means the gate is disabled. A client resolution failure fails closed: the |
A GitHub App resolution failure is deterministic per deployment config, so durable apply, apply-confirm, unlock, and rollback deliveries that hit one re-drove indefinitely instead of settling. The actor authorization gate now surfaces the client-creation cause so durable cores can classify it; transient token/client failures stay retryable. Ref: PLAT-38832 (WH-9b-v-a-ii)
Kiran01bm
force-pushed
the
kiran01bm/wh-9b-v-a-ii-app-resolution-terminal
branch
from
August 19, 2026 23:38
ea44438 to
e22a4e0
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.
Summary
A GitHub App resolution failure (
errGitHubAppResolution) is deterministic per deployment config — a re-drive only reproduces it. The four durableissue_commentcommand cores (apply, apply-confirm, unlock, rollback) previously classified it as retryable, so a delivery that hit one re-drove indefinitely instead of settling. These cores now classify it as terminal-with-error: the delivery is not re-driven, and the error is recorded on the failed delivery as its triage trail (no PR comment could be posted without a client). This matches the convention already merged for rollback-confirm (#1000).What
applyCommandCore/applyConfirmCommandCore: a bootstrap failure caused byerrGitHubAppResolutionreturns(retry=false, err); other bootstrap failures stay retryable.unlockCommandCore: the same classification at both the database-inference and authorization-client seams.rollbackCommandCore: the same classification at the authorization-client seam.actorAuthorizationClientnow returns(*InstallationClient, error)instead of(client, blocked bool)so durable callers can inspect the cause; it still logs and posts the best-effort authorization-unavailable comment before returning. Non-durable callers (plan, control) fail closed exactly as before.Disposition contract per core:
errGitHubAppResolution(deterministic config error)(retry=true, err)— re-drives forever(retry=false, err)— delivery fails terminally, error retained(retry=true, err)(retry=true, err)— unchangedWhy
Recovery from a bad App mapping is an operator fixing deployment config and the user re-issuing the command — not a re-drive. Leaving these deliveries retryable pinned inbox lease slots and produced permanent redelivery noise. Recording the error (rather than marking the delivery completed) preserves the only triage trail, since the command never ran and no PR comment could be posted.
Before / after