Skip to content

fix(webhook): treat GitHub App resolution failures as terminal in command cores - #1095

Draft
Kiran01bm wants to merge 1 commit into
mainfrom
kiran01bm/wh-9b-v-a-ii-app-resolution-terminal
Draft

fix(webhook): treat GitHub App resolution failures as terminal in command cores#1095
Kiran01bm wants to merge 1 commit into
mainfrom
kiran01bm/wh-9b-v-a-ii-app-resolution-terminal

Conversation

@Kiran01bm

Copy link
Copy Markdown
Collaborator

Summary

A GitHub App resolution failure (errGitHubAppResolution) is deterministic per deployment config — a re-drive only reproduces it. The four durable issue_comment command 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 by errGitHubAppResolution returns (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.
  • actorAuthorizationClient now 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.
  • Contract tests for each core's App-resolution seam, plus an authorization-enabled test helper.

Disposition contract per core:

Failure at the App-resolution seam Before After
errGitHubAppResolution (deterministic config error) (retry=true, err) — re-drives forever (retry=false, err) — delivery fails terminally, error retained
Any other client/bootstrap failure (e.g. token fetch) (retry=true, err) (retry=true, err) — unchanged

Why

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

Before:
issue_comment delivery ──▶ command core ──▶ App resolution fails
                                              │
                                              ▼
                                       (retry=true, err)
                                              │
                                              ▼
                              re-drive ──▶ same failure ──▶ re-drive … (never settles)

After:
issue_comment delivery ──▶ command core ──▶ App resolution fails
                                              │
                              ┌───────────────┴───────────────┐
                              ▼                               ▼
                    errGitHubAppResolution            other failure (transient)
                              │                               │
                              ▼                               ▼
                     (retry=false, err)                (retry=true, err)
                delivery fails terminally,             re-drive as before
                error recorded for triage

Copilot AI lite review requested due to automatic review settings August 19, 2026 09:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 errGitHubAppResolution as (retry=false, err) in apply/apply-confirm bootstrap and in unlock/rollback authorization-client creation paths.
  • Refactors actorAuthorizationClient to 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 thread pkg/webhook/actor_authorization.go Outdated
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
Kiran01bm force-pushed the kiran01bm/wh-9b-v-a-ii-app-resolution-terminal branch from ea44438 to e22a4e0 Compare August 19, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants