Skip to content

feat(agent/pr-reviewer): migrate to GitHub App auth (spec 033, Base F1)#6

Merged
bborbe merged 18 commits into
masterfrom
feature/pr-reviewer-github-app
May 23, 2026
Merged

feat(agent/pr-reviewer): migrate to GitHub App auth (spec 033, Base F1)#6
bborbe merged 18 commits into
masterfrom
feature/pr-reviewer-github-app

Conversation

@bborbe
Copy link
Copy Markdown
Owner

@bborbe bborbe commented May 21, 2026

Summary

Migrates agent/pr-reviewer from PAT-on-user authentication (pr-review-of-ben, flagged "Spammy" by GitHub Trust & Safety → reviews invisible via REST /reviews) to GitHub App authentication.

Two Apps registered, installed, smoke-tested end-to-end (Phase A + B, commit c1a105d, cmd/mint-iat):

Env App App ID Install ID PEM (Teamvault) Scope
prod Ben's Pull Request Reviewer 3798945 134414316 kLoejw all bborbe/*
dev Ben's Pull Request Reviewer Dev 3800041 134435225 eqKj8L bborbe/go-skeleton only

Phase B verified prod review id 4340102652 POSTed and visible via REST API as ben-s-pull-request-reviewer[bot].

What's in this PR

Rung Change
Pre-flight cmd/mint-iat smoke-test tool (stdlib-only) + docs/github-app-setup.md reference
R1 (lib/githubapp) New shared package wrapping bradleyfalzon/ghinstallation/v2; NewClient returns auth-injecting http.Client; MintIAT returns the IAT for GH_TOKEN callers. 95.5% test coverage.
R2 (agent wiring) New env vars APP_ID, INSTALLATION_ID, PEM_KEY_FILE, BOT_GITHUB_LOGIN. Pod startup mints IAT and assigns to a.GHToken so downstream code (githubposter, githubauth, Claude subprocess) is unchanged. pkg/authmode.go resolver: App auth wins over GH_TOKEN; pod refuses to start if neither is set. DefaultBotLogin flipped to ben-s-pull-request-reviewer[bot]. checkBotIdentity reworked (no more GET /user). steps_gh_token.go error messages no longer say "rotate teamvault entry".
R3 (k8s) Secret YAML gains PEM via teamvaultPassword template. Config CR env: exposes APP_ID, INSTALLATION_ID, BOT_GITHUB_LOGIN, PEM_KEY_FILE. dev.env/prod.env updated with AGENT_PR_REVIEWER_APP_ID / INSTALLATION_ID / BOT_LOGIN / PEM_KEY exports. Legacy GH_TOKEN Secret key retained as fallback.

Out of scope (sibling specs)

  • PR Watcher migration → goal F2
  • Build Watcher migration → goal F3
  • Removing the legacy GH_TOKEN env (kept as fallback)
  • Auto-merge gate behavior with App APPROVE — observed in Rung 3, documented, not changed

Test plan

  • cd lib && make precommit → green (95.5% cov on lib/githubapp)
  • cd agent/pr-reviewer && make precommit → green (87 tests, 86.2% avg cov, 0 lint/sec issues)
  • Deploy to dev cluster → real PR on bborbe/go-skeleton → confirm review visible via REST as ben-s-pull-request-reviewer-dev[bot]
  • Soak ≥1 day on dev
  • Deploy to prod cluster → real PR on any bborbe/* → confirm review visible via REST as ben-s-pull-request-reviewer[bot]
  • After ≥3 clean prod cycles, retire pr-review-of-ben PAT

Related

  • Spec: specs/in-progress/033-migrate-pr-reviewer-to-github-app.md
  • Setup reference: agent/pr-reviewer/docs/github-app-setup.md
  • Goal F1: GitHub Code Reviewer Agent - Base

bborbe added 18 commits May 21, 2026 22:06
Validates the GitHub App migration path end-to-end before refactoring
production code. Mints a JWT with the App's private key, exchanges it
for an installation access token, and verifies App identity via /app.

Stdlib-only — no new production deps. Throwaway tool that documents the
auth flow; production integration will use ghinstallation/v2.

Phase A + B verified against #2 on 2026-05-21:
- POST review as ben-s-pull-request-reviewer[bot] → id 4340102652
- GET /reviews returns the review (Spammy filter no longer applies)

Adds docs/github-app-setup.md with App identity table, auth-flow
explanation, mint-iat usage (teamvault-pipe / file / env), rotation
procedure, and gotchas (no GET /user, bot login has brackets,
required-approvals gates need testing).

Tracks F1 of [[GitHub Code Reviewer Agent - Base]].
Dev and prod must use distinct App identities so dev test verdicts
cannot be mistaken for prod verdicts by auto-merge gates, and so a
dev compromise cannot reach prod. Same permission set, different
scope:

- Prod: ben-s-pull-request-reviewer (all bborbe/* repos)
- Dev:  ben-s-pull-request-reviewer-dev (bborbe/go-skeleton only)

Both Apps verified end-to-end via cmd/mint-iat on 2026-05-21.
The agent task controller mounts Secret keys via envFrom: secretRef:
(agent_configuration.go), not as files. The previous Config CR had
PEM_KEY_FILE=/etc/github-app/pem pointing at a non-existent path, and
the Secret used teamvaultPassword (which returns empty for file-type
Teamvault entries) instead of teamvaultFileBase64.

Fixes:
- Secret YAML: PEM (teamvaultPassword) -> PEM_KEY (teamvaultFileBase64)
  so envFrom exposes the PEM content as env var \$PEM_KEY directly.
- Config CR: drop PEM_KEY_FILE; main.go's PEMKey field reads \$PEM_KEY
  from the Secret-derived env. Comment updated.
- cmd/{cli,mint-iat,run-task}/Makefile: add no-op buca/apply stubs so
  Makefile.folder's recursion succeeds (cmd binaries are CLI tools
  installed via go install, not k8s services).

Verified end-to-end on dev cluster:
- kubectlquant -n dev get secret maintainer-agent-pr-reviewer
  shows PEM_KEY=1679 decoded bytes (valid RSA key)
- Config CR has APP_ID=3800041, INSTALLATION_ID=134435225,
  BOT_GITHUB_LOGIN=ben-s-pull-request-reviewer-dev[bot]
@bborbe bborbe merged commit beecd5f into master May 23, 2026
1 check passed
@bborbe bborbe deleted the feature/pr-reviewer-github-app branch May 23, 2026 08:52
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.

1 participant