Skip to content

Re-architect: migrate from GitHub App to machine user account (PAT) to support CODEOWNERS approval #27

Description

@don-petry

Problem

The current bot authenticates as a GitHub App (petry-projects-pr-review-agent[bot]). GitHub Apps have a hard platform limitation: they cannot be listed in CODEOWNERS files and their approvals are never recognized as code owner reviews, regardless of what's in the CODEOWNERS file.

This means any repo with require_code_owner_review: true on branch protection is permanently blocked — the bot can review but can never unblock the PR. Approvals from the app count toward required_approving_review_count but not toward the code owner requirement.

Reference: GitHub community discussion #23064 — GitHub staff confirmed: "GitHub Apps can't be used in CODEOWNERS — that's not supported." Feature request #108490 has been open 5+ years with no ETA.

Observed impact:

  • ContentTwin (require_code_owner_review: false) — bot approvals work, PRs merge ✅
  • TalkTerm (require_code_owner_review: true) — bot approvals post but do not unblock PRs ❌

A temporary workaround was added in scripts/post-pr-review.sh to detect this condition and post an explanatory comment instead of a useless approval, but that doesn't solve the underlying problem.

Solution

Migrate the bot from a GitHub App to a machine user account (a second GitHub user account) with a PAT.

A machine user account:

  • Can be added to an org team (e.g., petry-projects/pr-reviewers)
  • That team can be listed in CODEOWNERS: * @petry-projects/pr-reviewers
  • The bot's approvals then count as code owner approvals ✅

What changes

Area Current (App) Target (Machine user)
Auth JWT via actions/create-github-app-token PAT stored as org secret
Identity petry-projects-pr-review-agent[bot] e.g. petry-pr-bot (human account)
CODEOWNERS Cannot be listed Listed via team membership
Token rotation Auto (1hr JWT) Manual PAT rotation (or fine-grained PAT with expiry)
Permissions Fine-grained via App manifest Scoped to PAT scopes (repo, pull_requests)

Migration steps

  1. Create a new GitHub user account (e.g. petry-pr-bot with a shared org email alias)
  2. Add it to a new org team: petry-projects/pr-reviewers
  3. Repo admins add * @petry-projects/pr-reviewers (or path-specific rules) to their CODEOWNERS
  4. Generate a fine-grained PAT for the machine user scoped to the org repos needed
  5. Store the PAT as an org secret (e.g. BOT_PAT)
  6. Update all workflows to use GH_TOKEN: ${{ secrets.BOT_PAT }} instead of generating an App token via actions/create-github-app-token
  7. Remove the CODEOWNERS pre-flight workaround from scripts/post-pr-review.sh (lines 162–195)
  8. Remove the GitHub App secrets (APP_ID, APP_PRIVATE_KEY, APP_INSTALLATION_ID) once migration is validated

Trade-offs to accept

  • Lose auto-expiring JWT tokens — PATs need manual rotation (mitigate with fine-grained PATs with 90-day expiry + calendar reminder)
  • Human-style account overhead — requires a separate GitHub seat and email alias
  • Slightly broader permission surface — PAT scopes are less granular than App manifest permissions

These are worth accepting to get full code owner approval support across all repos.

Affected files

  • .github/workflows/pr-review.yml — replace App token generation
  • .github/workflows/backfill-approvals.yml — replace App token generation
  • .github/workflows/fix-stuck-prs.yml — replace App token generation
  • .github/workflows/daily-pr-review-health.yml — replace App token generation
  • scripts/post-pr-review.sh — remove CODEOWNERS pre-flight workaround (lines 162–195)
  • GITHUB_APP_SETUP.md → replace with machine user setup doc
  • IMPLEMENTATION.md — update authentication section

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions