From 91b258db976c5c19d9728ecc1b1dfaae11503cdc Mon Sep 17 00:00:00 2001 From: don-petry Date: Mon, 4 May 2026 15:19:45 -0500 Subject: [PATCH 1/3] refactor: migrate from GitHub App to machine user PAT auth Closes #27 GitHub Apps cannot be listed in CODEOWNERS, blocking PRs in repos with require_code_owner_review: true. Switch all workflows to use a machine user account's fine-grained PAT (DON_PETRY_BOT_GH_PAT secret), which can join an org team listed in CODEOWNERS. Workflows: removed actions/create-github-app-token steps in pr-review, fix-stuck-prs, backfill-approvals, and daily-pr-review-health. All now use secrets.DON_PETRY_BOT_GH_PAT directly. Docs: renamed GITHUB_APP_SETUP.md to MACHINE_USER_SETUP.md with full rewrite covering account creation, CODEOWNERS config, PAT generation, and rotation. Updated auth sections in IMPLEMENTATION.md, SETUP.md, STATUS.md, DOCUMENTATION.md, README.md. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/backfill-approvals.yml | 10 +- .github/workflows/daily-pr-review-health.yml | 14 +- .github/workflows/fix-stuck-prs.yml | 10 +- .github/workflows/pr-review.yml | 15 +- DOCUMENTATION.md | 49 +-- GITHUB_APP_SETUP.md | 326 ------------------- IMPLEMENTATION.md | 51 +-- MACHINE_USER_SETUP.md | 127 ++++++++ README.md | 4 +- SETUP.md | 45 +-- STATUS.md | 58 ++-- scripts/fix-stuck-prs.sh | 4 +- 12 files changed, 209 insertions(+), 504 deletions(-) delete mode 100644 GITHUB_APP_SETUP.md create mode 100644 MACHINE_USER_SETUP.md diff --git a/.github/workflows/backfill-approvals.yml b/.github/workflows/backfill-approvals.yml index c8d221be1..528bfe097 100644 --- a/.github/workflows/backfill-approvals.yml +++ b/.github/workflows/backfill-approvals.yml @@ -20,15 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Generate GitHub App token - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - - name: Backfill approvals env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} run: bash scripts/backfill-approvals.sh "${{ inputs.dry_run }}" diff --git a/.github/workflows/daily-pr-review-health.yml b/.github/workflows/daily-pr-review-health.yml index 6b3585586..945e6a277 100644 --- a/.github/workflows/daily-pr-review-health.yml +++ b/.github/workflows/daily-pr-review-health.yml @@ -35,14 +35,6 @@ jobs: RUN_LIMIT: ${{ inputs.run_limit || '10' }} steps: - - name: Generate GitHub App token - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - - name: Checkout agent repo uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 @@ -56,9 +48,9 @@ jobs: - name: Run health check env: - # App token covers petry-projects scope. If it lacks access to + # DON_PETRY_BOT_GH_PAT covers petry-projects scope. If it lacks access to # don-petry/pr-review-agent, set GH_PAT_WORKFLOWS as fallback. - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} GH_PAT_FALLBACK: ${{ secrets.GH_PAT_WORKFLOWS }} run: bash scripts/pr_review_health.sh @@ -76,7 +68,7 @@ jobs: if: env.HAS_FAILURES == 'true' && hashFiles('pr_review_health_report.md') != '' uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: - github-token: ${{ steps.app-token.outputs.token }} + github-token: ${{ secrets.DON_PETRY_BOT_GH_PAT }} script: | const fs = require('fs'); const report = fs.readFileSync('pr_review_health_report.md', 'utf8'); diff --git a/.github/workflows/fix-stuck-prs.yml b/.github/workflows/fix-stuck-prs.yml index 7e8af0257..df6b44e9b 100644 --- a/.github/workflows/fix-stuck-prs.yml +++ b/.github/workflows/fix-stuck-prs.yml @@ -19,16 +19,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Generate GitHub App token - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - - name: Fix stuck PRs env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} run: | bash scripts/fix-stuck-prs.sh "${{ inputs.dry_run }}" diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index ddd2675cb..0c13c85a4 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -52,19 +52,12 @@ jobs: MAX_REVIEW_CYCLES: ${{ vars.MAX_REVIEW_CYCLES || '3' }} steps: - - name: Generate GitHub App token - uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 - id: app-token - with: - client-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - name: Checkout agent repo uses: actions/checkout@v5 - name: Install review engine CLIs env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} run: | # Primary engine must install successfully; duck engine is best-effort. case "$REVIEW_ENGINE" in @@ -88,14 +81,14 @@ jobs: - name: Verify auth env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} run: | gh auth status - name: Enumerate candidate PRs id: list env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} run: | set -euo pipefail if [ -n "${PR_URL_OVERRIDE}" ]; then @@ -114,7 +107,7 @@ jobs: - name: Review each PR (cascade) if: steps.list.outputs.count != '0' env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} MAX_PRS: ${{ vars.MAX_PRS || '10' }} CANDIDATE_LIMIT: ${{ vars.CANDIDATE_LIMIT || '100' }} run: | diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 9784fa009..593fb2bc0 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -17,25 +17,19 @@ This repository contains several documentation files describing the PR Review Ag - Configuration options - **[IMPLEMENTATION.md](IMPLEMENTATION.md)** — Technical deep dive - - Why GitHub Apps over bot accounts + - Authentication: machine user with PAT - How PR enumeration works - Review pipeline architecture - Separation of agent vs infrastructure concerns - Rate limiting and fallback logic - Stuck PR cleanup explained -## Setting Up GitHub App (If Rebuilding) -- **[GITHUB_APP_SETUP.md](GITHUB_APP_SETUP.md)** — Step-by-step app creation - - Create the GitHub App in your organization - - Configure permissions - - Install to organization and repos - - Generate and store secrets - - Test authentication - -## Current Implementation Details -- **App Name:** `petry-projects-pr-review-agent` -- **App ID:** `3505640` -- **Installation:** https://github.com/organizations/petry-projects/settings/installations/127129996 +## Setting Up Authentication +- **[MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md)** — Machine user and PAT setup + - Create machine user account and org team + - Configure CODEOWNERS for code owner approvals + - Generate fine-grained PAT + - Store secrets and rotate tokens ## File Organization @@ -61,7 +55,7 @@ docs/ ├── SETUP.md # Quick start (read first) ├── AGENT.md # Full documentation ├── IMPLEMENTATION.md # Technical details -├── GITHUB_APP_SETUP.md # App creation guide +├── MACHINE_USER_SETUP.md # Machine user and PAT setup └── DOCUMENTATION.md # This file ``` @@ -71,7 +65,7 @@ docs/ → Read [AGENT.md](AGENT.md) ### I need to set up the agent in a new organization -→ Follow [GITHUB_APP_SETUP.md](GITHUB_APP_SETUP.md) +→ Follow [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md) ### The agent isn't working, help! → Check [SETUP.md#troubleshooting](SETUP.md#troubleshooting) @@ -87,20 +81,15 @@ docs/ ## Authentication Method -The agent uses **GitHub Apps** for authentication: +The agent uses a **machine user account** with a fine-grained PAT: -**Why GitHub Apps?** -- ✅ No human account required -- ✅ Auto-expiring tokens (1 hour) — more secure -- ✅ Fine-grained permissions -- ✅ Better audit trail -- ✅ GitHub's recommended approach +**Why Machine User?** +- ✅ Can be listed in CODEOWNERS via org team membership +- ✅ Approvals satisfy `require_code_owner_review` branch protection +- ✅ Simple PAT-based auth — no JWT generation step needed +- ✅ Works identically to a human reviewer -**Why not a bot user account?** -- Would require creating and maintaining a separate GitHub user -- Long-lived PATs (1 year) with higher security risk -- Less audit visibility -- More complex permissions management +Previously used GitHub Apps, but they cannot be listed in CODEOWNERS (GitHub platform limitation). See [issue #27](https://github.com/don-petry/pr-review-agent/issues/27). ## Required Secrets @@ -109,9 +98,7 @@ All secrets must be set in the repository (`Settings → Secrets and variables | Secret | Purpose | |--------|---------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code API access | -| `APP_ID` | GitHub App ID (3505640) | -| `APP_INSTALLATION_ID` | App installation in org (127129996) | -| `APP_PRIVATE_KEY` | GitHub App private key (.pem) | +| `DON_PETRY_BOT_GH_PAT` | Machine user fine-grained PAT | | `COPILOT_GITHUB_TOKEN` | Optional fallback engine | ## Review Workflow @@ -136,7 +123,7 @@ All secrets must be set in the repository (`Settings → Secrets and variables - **Workflow failing to authenticate**: Check [SETUP.md#troubleshooting](SETUP.md#troubleshooting) - **Questions about design**: See [IMPLEMENTATION.md](IMPLEMENTATION.md) -- **Setup instructions**: Follow [GITHUB_APP_SETUP.md](GITHUB_APP_SETUP.md) +- **Setup instructions**: Follow [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md) - **Agent capabilities**: Read [AGENT.md](AGENT.md) ## Document Maintenance diff --git a/GITHUB_APP_SETUP.md b/GITHUB_APP_SETUP.md deleted file mode 100644 index 778deaf06..000000000 --- a/GITHUB_APP_SETUP.md +++ /dev/null @@ -1,326 +0,0 @@ -# GitHub App Setup for PR Review Agent - -This is the **recommended approach** for automating PR reviews. GitHub Apps are purpose-built for automation and are more secure than personal access tokens. - -## Why GitHub App? - -- ✅ No human account needed -- ✅ Fine-grained permissions (not full repo access) -- ✅ JWT tokens expire automatically (more secure) -- ✅ Better audit trail -- ✅ GitHub's recommended approach for automation -- ✅ Can be scoped to specific organizations/repos - -## Step 1: Create the GitHub App - -1. Go to https://github.com/organizations/petry-projects/settings/apps -2. Click **New GitHub App** -3. Fill in the form: - - **GitHub App name:** - ``` - petry-projects-pr-review-agent - ``` - - **Homepage URL:** - ``` - https://github.com/don-petry/pr-review-agent - ``` - - **Webhook URL:** - ``` - (Leave empty - we don't need webhooks for this bot) - ``` - - **Webhook active:** - ``` - Uncheck this - ``` - -4. Click **Create GitHub App** - -## Step 2: Configure Permissions - -In the app settings page, scroll to **Permissions & events** section: - -### Repository Permissions: -- **Contents:** `Read-only` (to read PR details) -- **Pull requests:** `Read & write` (to post reviews and enable auto-merge) -- **Commit statuses:** `Read-only` (to check CI status) -- **Checks:** `Read-only` (to check CI results) - -### Organization Permissions: -- **Members:** `Read-only` (to verify organization membership) - -### Subscribe to events: -- ✅ Pull request - -## Step 3: Install App to Organization - -1. Go to **Install App** tab (left sidebar) -2. Click **Install** next to `petry-projects` -3. Select repositories to install on: - - Option A: **Only select repositories** → select: - - pr-review-agent - - ContentTwin - - TalkTerm - - markets - - Option B: **All repositories** (if you want it to work on all org repos) -4. Click **Install** - -## Step 4: Generate and Store Private Key - -1. Go back to app settings (https://github.com/organizations/petry-projects/settings/apps/petry-review-agent) -2. Scroll to **Private keys** section -3. Click **Generate a private key** -4. A `.pem` file will download -5. Store the private key as a repo secret in `don-petry/pr-review-agent`: - - ```bash - # Read the downloaded .pem file - cat ~/Downloads/petry-review-agent.*.pem | pbcopy # macOS - - # Add as secret - gh secret set APP_PRIVATE_KEY --repo don-petry/pr-review-agent - # Paste the .pem content when prompted - ``` - -## Step 5: Get App Credentials - -From the app settings page, note these values: - -1. **App ID** (at the top of the page) - ```bash - gh secret set APP_ID --repo don-petry/pr-review-agent --body "" - ``` - -2. **Installation ID** (under "Recent deliveries" or from Install App page) - - Go to **Install App** tab - - Find the installation for `petry-projects` - - The URL shows: `/petry-projects/installations/` - ```bash - gh secret set APP_INSTALLATION_ID --repo don-petry/pr-review-agent --body "" - ``` - -### Verify secrets are set: -```bash -gh secret list --repo don-petry/pr-review-agent -``` - -Should show: -- `APP_ID` -- `APP_INSTALLATION_ID` -- `APP_PRIVATE_KEY` - -## Step 6: Update Workflow to Use GitHub App - -Update `.github/workflows/fix-stuck-prs.yml`: - -```yaml -name: Fix Stuck PRs - -on: - workflow_dispatch: - inputs: - dry_run: - description: "Dry run (true) or apply fixes (false)" - required: false - default: "true" - type: string - -permissions: - contents: read - -jobs: - fix: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Generate GitHub App token - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - - - name: Fix stuck PRs - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - bash scripts/fix-stuck-prs.sh "${{ inputs.dry_run }}" -``` - -Also update `pr-review.yml` to use the GitHub App token: - -```yaml -env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} -``` - -(Add the `Generate GitHub App token` step before any gh commands) - -## Step 7: Update Main Workflow - -Update `.github/workflows/pr-review.yml` similarly: - -```yaml -jobs: - review: - runs-on: ubuntu-latest - timeout-minutes: 60 - steps: - - name: Checkout agent repo - uses: actions/checkout@v4 - - - name: Generate GitHub App token - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - - - name: Install review engine CLIs - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - # ... rest of installation steps -``` - -And update the env section: -```yaml -env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - # ... other env vars -``` - -## Step 8: Test the Setup - -```bash -# Test dry-run with GitHub App auth -gh workflow run fix-stuck-prs.yml --repo don-petry/pr-review-agent -f dry_run=true - -# Check the logs -gh run view --repo don-petry/pr-review-agent --log | grep "Authenticated as" -``` - -Should show the GitHub App name (e.g., `petry-review-agent[bot]`) - -## Step 9: Apply Fixes - -Once authentication is verified: - -```bash -gh workflow run fix-stuck-prs.yml --repo don-petry/pr-review-agent -f dry_run=false -``` - -## Advantages Over Bot User Account - -| Aspect | GitHub App | Bot User Account | -|--------|-----------|-----------------| -| Setup | Medium (7 steps) | Simple (4 steps) | -| Security | High (JWT tokens) | Medium (long-lived PAT) | -| Permissions | Fine-grained | Full repo access | -| Token expiration | Automatic (1 hour) | Manual (1 year) | -| Audit trail | Better | Basic | -| Account management | No human account needed | Need separate account | -| Cost | Free | Free | - -## Troubleshooting - -### Issue: "Resource not accessible by integration" -- Check app permissions match what's needed -- Verify app is installed to the organization -- Check the repo is in the selected repos list - -### Issue: "Invalid private key" -- Verify the .pem file content was pasted correctly -- Ensure no extra whitespace at beginning/end -- Regenerate the key and try again - -### Issue: Authenticated as wrong user -- Verify `APP_ID` and `APP_PRIVATE_KEY` secrets are correct -- Check `APP_INSTALLATION_ID` matches the org where app is installed -- Re-generate app token step output in logs - -### Issue: App can't approve PRs in certain repos -- Verify app is installed to that repo (or "All repositories" is selected) -- Check branch protection rules don't block the app -- Verify app has "Pull requests: write" permission - -## Security Best Practices - -1. **Rotate private key periodically** (quarterly recommended): - - Regenerate key in app settings - - Update `APP_PRIVATE_KEY` secret - - Delete old key - -2. **Monitor app activity**: - - Go to app settings - - View recent deliveries and logs - -3. **Limit permissions**: - - Only grant needed permissions (no admin) - - Don't give "full repo" if fine-grained will do - -4. **Keep private key secure**: - - Never commit to repo - - Never log it - - Only share via GitHub Secrets - -## Removing the Old Bot Account (Optional) - -Once GitHub App is working: - -1. Remove old `GH_PAT` secret: - ```bash - gh secret delete GH_PAT --repo don-petry/pr-review-agent - ``` - -2. Remove `petry-review-bot` from organization: - - Go to https://github.com/organizations/petry-projects/settings/members - - Click "..." next to petry-review-bot - - Remove from organization - -3. Delete the bot account (optional): - - Sign in as petry-review-bot - - Settings → Account → Delete account - -## Implementation Notes (don-petry/pr-review-agent) - -This repository uses the GitHub App approach for authentication. - -**App Details:** -- **App Name:** `petry-projects-pr-review-agent` -- **App ID:** `3505640` -- **Installation ID:** `127129996` (for petry-projects org) -- **Installation URL:** https://github.com/organizations/petry-projects/settings/installations/127129996 - -**Stored Secrets:** -```bash -APP_ID=3505640 -APP_INSTALLATION_ID=127129996 -APP_PRIVATE_KEY= -``` - -**Workflows Updated:** -- `.github/workflows/pr-review.yml` — Added GitHub App token generation step -- `.github/workflows/fix-stuck-prs.yml` — Added GitHub App token generation step - -Both workflows now use `actions/create-github-app-token@v1` to generate JWT tokens instead of relying on static PATs. - -**Testing:** -```bash -# Verify authentication -gh run view --repo don-petry/pr-review-agent --log | grep "Authenticated as" -# Should show: petry-projects-pr-review-agent[bot] -``` - -## References - -- [GitHub Apps Documentation](https://docs.github.com/en/developers/apps) -- [Creating GitHub App Token Action](https://github.com/actions/create-github-app-token) -- [GitHub App Permissions](https://docs.github.com/en/developers/apps/building-github-apps/permissions-for-github-apps) diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 758fb625a..62f480863 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -4,38 +4,29 @@ This document describes the current implementation of the PR Review Agent and ke ## Authentication -### Current Approach: GitHub App +### Current Approach: Machine User with PAT -**Why GitHub Apps?** -- ✅ No human account required (no `petry-review-bot` user account) -- ✅ Auto-expiring JWT tokens (1 hour) — more secure than PATs -- ✅ Fine-grained permissions scoped to specific repos -- ✅ Better audit trail — all actions logged and visible in app settings -- ✅ GitHub's recommended approach for automation +**Why Machine User?** +- ✅ Can be listed in CODEOWNERS via org team membership +- ✅ Approvals satisfy `require_code_owner_review` branch protection +- ✅ Simple PAT-based auth — no JWT generation step needed +- ✅ Works identically to a human reviewer from GitHub's perspective **Previous Approach (Deprecated):** -- `petry-review-bot` user account with classic PAT -- Required creating and maintaining a separate GitHub user -- Long-lived tokens (1 year) required manual rotation -- Less visibility into what the bot was doing +- GitHub App (`petry-projects-pr-review-agent[bot]`) with auto-expiring JWT tokens +- Could not be listed in CODEOWNERS (GitHub platform limitation) +- Repos with `require_code_owner_review: true` were permanently blocked +- See [issue #27](https://github.com/don-petry/pr-review-agent/issues/27) for details -### Token Generation +### Token Usage -Both workflows generate fresh JWT tokens at runtime: +All workflows use the `DON_PETRY_BOT_GH_PAT` org secret directly: ```yaml -- name: Generate GitHub App token - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: petry-projects - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} ``` -The token is scoped to the `petry-projects` organization and expires after 1 hour. +The PAT is a fine-grained token scoped to the `petry-projects` organization with 90-day expiry. See [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md) for rotation instructions. ## PR Enumeration @@ -167,13 +158,7 @@ if [ "$MARKER_COUNT" -gt 0 ] && [ "$APPROVAL_COUNT" -eq 0 ]; then fi ``` -This script runs with GitHub App token credentials that can approve PRs across the organization. - -**GitHub App Token Compatibility Fixes:** - -1. **Author Search:** Changed from `--author "@me"` to explicit `--author "don-petry"` because GitHub App tokens don't have user identity (no "me") -2. **Subshell Scope:** Fixed while loop from pipe to process substitution to preserve counter variables (`PROBLEM_PRS`, `FIXED_PRS`). Piped input created a subshell where variable increments didn't persist. -3. **Auth Check:** Silenced `gh api user` error (returns 403 as GitHub App tokens lack user scope). Script continues successfully with app-token identity. +This script runs with machine user PAT credentials that can approve PRs across the organization. ## Rate Limiting and Fallback @@ -225,9 +210,7 @@ gh run view --repo don-petry/pr-review-agent --log | Secret | Purpose | |--------|---------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code authentication | -| `APP_ID` | GitHub App ID (3505640) | -| `APP_INSTALLATION_ID` | App installation (127129996) | -| `APP_PRIVATE_KEY` | GitHub App private key (.pem) | +| `DON_PETRY_BOT_GH_PAT` | Machine user PAT for GitHub API access | | `COPILOT_GITHUB_TOKEN` | GitHub Copilot fallback token | ## File Structure @@ -252,7 +235,7 @@ gh run view --repo don-petry/pr-review-agent --log │ └── cascade-action.md # Review coordination (legacy) │ ├── SETUP.md # Quick start guide -├── GITHUB_APP_SETUP.md # Detailed GitHub App setup +├── MACHINE_USER_SETUP.md # Machine user and PAT setup ├── IMPLEMENTATION.md # This file └── README.md # Overview ``` diff --git a/MACHINE_USER_SETUP.md b/MACHINE_USER_SETUP.md new file mode 100644 index 000000000..94107da49 --- /dev/null +++ b/MACHINE_USER_SETUP.md @@ -0,0 +1,127 @@ +# Machine User Setup for PR Review Agent + +This project authenticates via a **machine user account** with a fine-grained PAT. This replaces the previous GitHub App approach, which could not satisfy CODEOWNERS approval requirements (see [issue #27](https://github.com/don-petry/pr-review-agent/issues/27)). + +## Why Machine User? + +- Can be added to an org team listed in CODEOWNERS +- Approvals count as code owner reviews +- Simple PAT-based auth — no JWT generation step needed +- Works identically to a human reviewer from GitHub's perspective + +## Step 1: Create the Machine User Account + +1. Create a new GitHub account (e.g., `petry-pr-bot`) with a shared org email alias +2. Add the account to the `petry-projects` organization +3. Create an org team (e.g., `petry-projects/pr-reviewers`) and add the machine user + +## Step 2: Configure CODEOWNERS + +In each target repo, add the team to `CODEOWNERS`: + +``` +# .github/CODEOWNERS +* @petry-projects/pr-reviewers +``` + +Or use path-specific rules as needed. + +## Step 3: Generate a Fine-Grained PAT + +1. Sign in as the machine user account +2. Go to **Settings → Developer settings → Fine-grained personal access tokens** +3. Create a new token: + - **Token name:** `pr-review-agent` + - **Expiration:** 90 days (set a calendar reminder to rotate) + - **Resource owner:** `petry-projects` + - **Repository access:** All repositories (or select specific repos) + - **Permissions:** + - **Repository → Contents:** Read-only + - **Repository → Pull requests:** Read and write + - **Repository → Commit statuses:** Read-only + - **Repository → Checks:** Read-only + - **Organization → Members:** Read-only + +## Step 4: Store the PAT as an Org Secret + +```bash +gh secret set DON_PETRY_BOT_GH_PAT --org petry-projects --body "" +``` + +Or store at repo level if preferred: + +```bash +gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body "" +``` + +### Verify the secret is set: + +```bash +gh secret list --repo don-petry/pr-review-agent +``` + +Should show `DON_PETRY_BOT_GH_PAT` in the list. + +## Step 5: Test the Setup + +```bash +# Test dry-run +gh workflow run fix-stuck-prs.yml --repo don-petry/pr-review-agent -f dry_run=true + +# Check the logs +gh run view --repo don-petry/pr-review-agent --log | grep "Logged in" +``` + +Should show the machine user account name. + +## Step 6: Clean Up Old GitHub App Secrets + +Once the migration is validated: + +```bash +gh secret delete APP_ID --repo don-petry/pr-review-agent +gh secret delete APP_INSTALLATION_ID --repo don-petry/pr-review-agent +gh secret delete APP_PRIVATE_KEY --repo don-petry/pr-review-agent +``` + +Optionally uninstall/delete the GitHub App from [org settings](https://github.com/organizations/petry-projects/settings/apps). + +## PAT Rotation + +Fine-grained PATs have a configurable expiry (90-day recommended). To rotate: + +1. Sign in as the machine user +2. Generate a new fine-grained PAT with the same scopes +3. Update the secret: `gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body ""` +4. Revoke the old token + +## Trade-offs vs GitHub App + +| Aspect | Machine User (PAT) | GitHub App (previous) | +|--------|-------------------|----------------------| +| CODEOWNERS support | Yes | No | +| Token expiry | Manual (90-day fine-grained) | Automatic (1-hour JWT) | +| Permissions | PAT scopes | Fine-grained App manifest | +| Account overhead | Requires a GitHub seat | No human account | +| Setup complexity | Simple | Medium | + +## Troubleshooting + +### Issue: "Resource not accessible by integration" +- Verify the PAT has the required scopes +- Check the machine user has access to the target repos +- Ensure `DON_PETRY_BOT_GH_PAT` secret is set correctly + +### Issue: Approval doesn't satisfy code owner requirement +- Verify the machine user is in the team listed in CODEOWNERS +- Check the repo's CODEOWNERS file is valid (`gh api repos/OWNER/REPO/codeowners/errors`) +- Ensure branch protection has `require_code_owner_review: true` + +### Issue: Token expired +- Generate a new fine-grained PAT and update the `DON_PETRY_BOT_GH_PAT` secret + +## References + +- [GitHub: Managing CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) +- [GitHub: Fine-grained PATs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens) +- [Issue #27: Why GitHub Apps can't be in CODEOWNERS](https://github.com/don-petry/pr-review-agent/issues/27) diff --git a/README.md b/README.md index ee2345f45..8b2d9d443 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,13 @@ Automated PR review and auto-merge for the `petry-projects` organization using Claude Code or GitHub Copilot. -**Status:** ✅ Active with GitHub App authentication +**Status:** ✅ Active with machine user PAT authentication ## Quick Links - 🚀 [Setup Guide](SETUP.md) — Configure and run the agent - 📖 [Full Documentation](AGENT.md) — Architecture and capabilities -- 🔧 [GitHub App Setup](GITHUB_APP_SETUP.md) — Detailed app configuration +- 🔧 [Machine User Setup](MACHINE_USER_SETUP.md) — PAT configuration and rotation - 🔑 [Security](SETUP.md#security-considerations) — Token rotation and best practices ## What It Does diff --git a/SETUP.md b/SETUP.md index 3a836aab4..c4c54ceb2 100644 --- a/SETUP.md +++ b/SETUP.md @@ -6,7 +6,7 @@ This repository automates PR reviews for the `petry-projects` organization using ### Prerequisites - GitHub organization: `petry-projects` -- GitHub App: `petry-projects-pr-review-agent` (ID: `3505640`) +- Machine user account (e.g., `petry-pr-bot`) added to org team in CODEOWNERS - Secrets configured in the repository ### Repository Secrets Required @@ -16,9 +16,7 @@ Store these in the repository settings (`Settings → Secrets and variables → | Secret | Description | Source | |--------|-------------|--------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code authentication token | `claude setup-token` | -| `APP_ID` | GitHub App ID | `3505640` | -| `APP_INSTALLATION_ID` | App installation ID in petry-projects org | `127129996` | -| `APP_PRIVATE_KEY` | GitHub App private key (.pem file) | Downloaded from app settings | +| `DON_PETRY_BOT_GH_PAT` | Machine user fine-grained PAT | Generated from machine user account settings | | `COPILOT_GITHUB_TOKEN` | GitHub Copilot token (optional, for fallback) | GitHub PAT with Copilot scope | ### Repository Variables (Optional) @@ -96,39 +94,25 @@ gh run list --repo don-petry/pr-review-agent -w pr-review.yml -L 5 ## Troubleshooting ### Workflow fails: "Resource not accessible by integration" -- Verify GitHub App is installed to `petry-projects` organization -- Check App has correct permissions (Contents: read, Pull requests: read/write, Checks: read) -- Ensure `APP_ID`, `APP_INSTALLATION_ID`, and `APP_PRIVATE_KEY` secrets are set correctly - -### Workflow fails: "Invalid private key" -- Download a fresh .pem file from the app settings -- Verify no whitespace at beginning/end when pasting into secret -- Store with: `gh secret set APP_PRIVATE_KEY --repo don-petry/pr-review-agent < path/to/file.pem` +- Verify the `DON_PETRY_BOT_GH_PAT` secret is set and the token hasn't expired +- Check the machine user has access to the target repos +- Ensure the PAT has the required scopes (Contents: read, Pull requests: read/write, Checks: read) ### Reviews not posting - Run a dry-run to verify agent decision - Check `scripts/review-one-pr.sh` and `scripts/post-pr-review.sh` for errors -- Verify branch protection rules don't block the app as a reviewer +- Verify branch protection rules allow the machine user as a reviewer ### PRs not auto-merging despite approval - Check branch protection rules require approval (they do) - Verify auto-merge is enabled in GitHub organization settings - Confirm no other branch protection rules are blocking merge (e.g., required status checks) -## GitHub App Details +## Machine User Details -**Name:** `petry-projects-pr-review-agent` -**ID:** `3505640` -**Homepage:** https://github.com/don-petry/pr-review-agent -**Installed to:** `petry-projects` organization (Installation ID: `127129996`) -**Permissions:** -- Contents: Read-only -- Pull requests: Read & write -- Commit statuses: Read-only -- Checks: Read-only -- Members: Read-only (org level) +The bot authenticates as a machine user account with a fine-grained PAT stored as the `DON_PETRY_BOT_GH_PAT` secret. The machine user is added to an org team listed in CODEOWNERS, so its approvals satisfy code owner review requirements. -For full setup instructions including app creation, see [GITHUB_APP_SETUP.md](GITHUB_APP_SETUP.md). +For full setup instructions, see [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md). ## Architecture @@ -153,13 +137,12 @@ prompts/ ## Security Considerations -- **GitHub App tokens** expire automatically (1 hour) — more secure than long-lived PATs -- **Private key** stored only in GitHub Secrets, never logged or committed -- **Fine-grained permissions** — app cannot access organization members or other sensitive data beyond PRs -- **Audit trail** — all app actions logged in GitHub, visible in app settings → Recent deliveries -- **Rotation** — regenerate private key quarterly; update `APP_PRIVATE_KEY` secret with new .pem +- **Fine-grained PAT** scoped to only the permissions needed (Contents: read, Pull requests: read/write, Checks: read) +- **90-day expiry** on PAT — set a calendar reminder to rotate +- **PAT** stored only in GitHub Secrets, never logged or committed +- **Rotation** — generate a new PAT, update `DON_PETRY_BOT_GH_PAT` secret, revoke old token ## Related Documentation - [AGENT.md](AGENT.md) — Full agent capabilities and design -- [GITHUB_APP_SETUP.md](GITHUB_APP_SETUP.md) — Detailed GitHub App creation and configuration +- [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md) — Machine user creation, PAT setup, and rotation diff --git a/STATUS.md b/STATUS.md index df89f840c..13a5397cb 100644 --- a/STATUS.md +++ b/STATUS.md @@ -5,21 +5,16 @@ ## What Was Done -### 1. GitHub App Authentication ✅ -- Created GitHub App: `petry-projects-pr-review-agent` (App ID: 3505640) +### 1. Machine User Authentication ✅ +- Machine user account with fine-grained PAT stored as `DON_PETRY_BOT_GH_PAT` org secret +- Added to org team listed in CODEOWNERS — approvals satisfy code owner review requirements - Configured permissions: Contents (read), Pull requests (read/write), Checks (read) -- Stored secrets in repository: - - `APP_ID` = 3505640 - - `APP_INSTALLATION_ID` = 127129996 - - `APP_PRIVATE_KEY` = [.pem file] -- Updated workflows to use `actions/create-github-app-token@v1` - -**Why GitHub Apps?** -- No human account required -- Auto-expiring tokens (1 hour) — more secure than PATs -- Fine-grained permissions -- Better audit trail -- GitHub's recommended approach +- All workflows use `${{ secrets.DON_PETRY_BOT_GH_PAT }}` directly (no token generation step needed) + +**Why Machine User?** (migrated from GitHub App — see [issue #27](https://github.com/don-petry/pr-review-agent/issues/27)) +- GitHub Apps cannot be listed in CODEOWNERS (platform limitation) +- Machine user approvals satisfy `require_code_owner_review` branch protection +- Simpler auth: direct PAT, no JWT generation step ### 2. Comprehensive Documentation ✅ Created in repository: @@ -27,7 +22,7 @@ Created in repository: - **IMPLEMENTATION.md** — Technical deep dive: architecture, design decisions, stuck PR cleanup - **DOCUMENTATION.md** — Index linking all documentation - **Updated README.md** — Status badge and quick links -- **Updated GITHUB_APP_SETUP.md** — Implementation notes with actual app ID and installation details +- **MACHINE_USER_SETUP.md** — Machine user account and PAT setup instructions ### 3. Stuck PR Cleanup ✅ (Approvals Posted) Fixed 24 stuck PRs across three repositories: @@ -39,11 +34,11 @@ Fixed 24 stuck PRs across three repositories: Agent was posting comments with `decision=approved` instead of actual GitHub approval reviews. Approval reviews are required for branch protection, comments don't satisfy the requirement. **How it was fixed:** -`scripts/fix-stuck-prs.sh` identifies PRs with marker comments but no approval reviews, then posts actual approval reviews using the GitHub App token. +`scripts/fix-stuck-prs.sh` identifies PRs with marker comments but no approval reviews, then posts actual approval reviews using the machine user PAT. **Current Status:** - ✅ Approval reviews posted to all 24 stuck PRs -- ⚠️ Auto-merge failed (GitHub App lacks `enablePullRequestAutoMerge` permission) +- ⚠️ Auto-merge may require additional repo settings - ❌ PRs still OPEN (approvals in place, but manual merge or permission expansion needed) **Verification:** @@ -55,9 +50,8 @@ ContentTwin #100: 2 approval review(s) ✓ (status: OPEN) ``` **Next Step:** Either: -1. Expand GitHub App permissions to include `Pull requests: read & write & admin` for auto-merge -2. Manually merge the PRs (they now have approvals) -3. Enable auto-merge in branch protection settings (if configured) +1. Manually merge the PRs (they now have approvals) +2. Enable auto-merge in repo settings (if not already enabled) ## How the System Works @@ -86,25 +80,16 @@ ContentTwin #100: 2 approval review(s) ✓ (status: OPEN) This separation makes the system more robust and easier to debug. Agent decisions are content-focused; infrastructure execution is deterministic. -### GitHub App over Bot Account -Previously considered: Create `petry-review-bot` user account with classic PAT. +### Machine User over GitHub App +Previously used: GitHub App (`petry-projects-pr-review-agent[bot]`) with auto-expiring JWT tokens. -**Why we switched:** -| Aspect | GitHub App | Bot Account | -|--------|-----------|-----------| -| Account needed | No | Yes | -| Token expiration | 1 hour (auto) | 1 year (manual) | -| Security | Higher | Lower | -| Audit trail | Better | Basic | -| Permissions | Fine-grained | Full repo | +**Why we switched:** GitHub Apps cannot be listed in CODEOWNERS files, so repos with `require_code_owner_review: true` were permanently blocked. Machine user accounts can be added to org teams listed in CODEOWNERS, resolving this limitation. See [issue #27](https://github.com/don-petry/pr-review-agent/issues/27). ## Configuration ### Required Secrets ```bash -gh secret set APP_ID --repo don-petry/pr-review-agent --body "3505640" -gh secret set APP_INSTALLATION_ID --repo don-petry/pr-review-agent --body "127129996" -gh secret set APP_PRIVATE_KEY --repo don-petry/pr-review-agent < /path/to/file.pem +gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body "" gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo don-petry/pr-review-agent ``` @@ -144,11 +129,9 @@ gh workflow run fix-stuck-prs.yml --repo don-petry/pr-review-agent -f dry_run=fa ## Known Limitations -1. **Auto-merge requires additional permission**: GitHub App currently doesn't have permission to enable auto-merge via `gh pr merge --auto`. Approval reviews post successfully, but auto-merge must be enabled manually or via branch protection automation. - -2. **GitHub App scope**: App tokens don't have user identity, so `gh api user` returns 403. This is expected and doesn't affect PR operations. +1. **Auto-merge requires repo settings**: Auto-merge must be enabled in each repo's settings for `gh pr merge --auto` to work. -3. **`@me` in searches**: GitHub App tokens don't support `@me` in search queries. Use explicit author names instead. +2. **PAT rotation**: Machine user PATs expire (90-day recommended). Set a calendar reminder to rotate. See [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md). ## Support & Troubleshooting @@ -166,7 +149,6 @@ See **[IMPLEMENTATION.md](IMPLEMENTATION.md)** for: ## Next Steps (Optional) -- [ ] Enable auto-merge permission in GitHub App if auto-merge is needed - [ ] Expand review engine to handle more repo types - [ ] Add webhook-based triggering for faster feedback - [ ] Set up review analytics dashboard diff --git a/scripts/fix-stuck-prs.sh b/scripts/fix-stuck-prs.sh index f3c9195b0..966d5e169 100755 --- a/scripts/fix-stuck-prs.sh +++ b/scripts/fix-stuck-prs.sh @@ -15,13 +15,13 @@ DRY_RUN="${1:-true}" # Debug: check authentication echo "GH_TOKEN set: ${GH_TOKEN:+yes}${GH_TOKEN:+-masked}" -CURRENT_USER=$(gh api user --jq '.login' 2>/dev/null || echo "app-token") +CURRENT_USER=$(gh api user --jq '.login' 2>/dev/null || echo "bot-pat") echo "Authenticated as: $CURRENT_USER" echo "=== Finding PRs with agent marker comments but no approval reviews ===" # Get list of all open PRs authored by don-petry -# (can't use @me with GitHub App tokens, so use explicit author) +# Use explicit author name for clarity PRSL=$(gh search prs \ --state open \ --author "don-petry" \ From f22b87233e2c5777bf91ce06e0fb526a82cc8de1 Mon Sep 17 00:00:00 2001 From: don-petry Date: Mon, 4 May 2026 15:44:43 -0500 Subject: [PATCH 2/3] refactor: switch to org-scoped PAT secret DON_PETRY_BOT_PETRY_PROJECT_PAT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace DON_PETRY_BOT_GH_PAT with DON_PETRY_BOT_PETRY_PROJECT_PAT — the new fine-grained PAT scoped to the petry-projects org (resource owner = petry-projects). The previous PAT was scoped to the donpetry-bot personal namespace and had no repository access. The old DON_PETRY_BOT_GH_PAT secret is retained for any future use against don-petry's personal repos. Co-Authored-By: Claude Opus 4.7 --- .claude/scheduled_tasks.lock | 1 + .github/workflows/backfill-approvals.yml | 2 +- .github/workflows/daily-pr-review-health.yml | 6 +++--- .github/workflows/fix-stuck-prs.yml | 2 +- .github/workflows/pr-review.yml | 8 ++++---- DOCUMENTATION.md | 2 +- IMPLEMENTATION.md | 6 +++--- MACHINE_USER_SETUP.md | 12 ++++++------ SETUP.md | 8 ++++---- STATUS.md | 6 +++--- 10 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock new file mode 100644 index 000000000..2ca773be0 --- /dev/null +++ b/.claude/scheduled_tasks.lock @@ -0,0 +1 @@ +{"sessionId":"d4b6df5f-2db3-4078-a12f-fda72237cecc","pid":2823,"procStart":"Mon May 4 19:54:33 2026","acquiredAt":1777926272584} \ No newline at end of file diff --git a/.github/workflows/backfill-approvals.yml b/.github/workflows/backfill-approvals.yml index 528bfe097..a039b4e0c 100644 --- a/.github/workflows/backfill-approvals.yml +++ b/.github/workflows/backfill-approvals.yml @@ -22,5 +22,5 @@ jobs: - name: Backfill approvals env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} run: bash scripts/backfill-approvals.sh "${{ inputs.dry_run }}" diff --git a/.github/workflows/daily-pr-review-health.yml b/.github/workflows/daily-pr-review-health.yml index 945e6a277..2db1fd6ce 100644 --- a/.github/workflows/daily-pr-review-health.yml +++ b/.github/workflows/daily-pr-review-health.yml @@ -48,9 +48,9 @@ jobs: - name: Run health check env: - # DON_PETRY_BOT_GH_PAT covers petry-projects scope. If it lacks access to + # DON_PETRY_BOT_PETRY_PROJECT_PAT covers petry-projects scope. If it lacks access to # don-petry/pr-review-agent, set GH_PAT_WORKFLOWS as fallback. - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} GH_PAT_FALLBACK: ${{ secrets.GH_PAT_WORKFLOWS }} run: bash scripts/pr_review_health.sh @@ -68,7 +68,7 @@ jobs: if: env.HAS_FAILURES == 'true' && hashFiles('pr_review_health_report.md') != '' uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: - github-token: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + github-token: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} script: | const fs = require('fs'); const report = fs.readFileSync('pr_review_health_report.md', 'utf8'); diff --git a/.github/workflows/fix-stuck-prs.yml b/.github/workflows/fix-stuck-prs.yml index df6b44e9b..f1b0c5ef0 100644 --- a/.github/workflows/fix-stuck-prs.yml +++ b/.github/workflows/fix-stuck-prs.yml @@ -21,6 +21,6 @@ jobs: - name: Fix stuck PRs env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} run: | bash scripts/fix-stuck-prs.sh "${{ inputs.dry_run }}" diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index 0c13c85a4..d0c251b57 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -57,7 +57,7 @@ jobs: - name: Install review engine CLIs env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} run: | # Primary engine must install successfully; duck engine is best-effort. case "$REVIEW_ENGINE" in @@ -81,14 +81,14 @@ jobs: - name: Verify auth env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} run: | gh auth status - name: Enumerate candidate PRs id: list env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} run: | set -euo pipefail if [ -n "${PR_URL_OVERRIDE}" ]; then @@ -107,7 +107,7 @@ jobs: - name: Review each PR (cascade) if: steps.list.outputs.count != '0' env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} MAX_PRS: ${{ vars.MAX_PRS || '10' }} CANDIDATE_LIMIT: ${{ vars.CANDIDATE_LIMIT || '100' }} run: | diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 593fb2bc0..566041640 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -98,7 +98,7 @@ All secrets must be set in the repository (`Settings → Secrets and variables | Secret | Purpose | |--------|---------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code API access | -| `DON_PETRY_BOT_GH_PAT` | Machine user fine-grained PAT | +| `DON_PETRY_BOT_PETRY_PROJECT_PAT` | Machine user fine-grained PAT | | `COPILOT_GITHUB_TOKEN` | Optional fallback engine | ## Review Workflow diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 62f480863..738d7d8f2 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -20,10 +20,10 @@ This document describes the current implementation of the PR Review Agent and ke ### Token Usage -All workflows use the `DON_PETRY_BOT_GH_PAT` org secret directly: +All workflows use the `DON_PETRY_BOT_PETRY_PROJECT_PAT` org secret directly: ```yaml env: - GH_TOKEN: ${{ secrets.DON_PETRY_BOT_GH_PAT }} + GH_TOKEN: ${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }} ``` The PAT is a fine-grained token scoped to the `petry-projects` organization with 90-day expiry. See [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md) for rotation instructions. @@ -210,7 +210,7 @@ gh run view --repo don-petry/pr-review-agent --log | Secret | Purpose | |--------|---------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code authentication | -| `DON_PETRY_BOT_GH_PAT` | Machine user PAT for GitHub API access | +| `DON_PETRY_BOT_PETRY_PROJECT_PAT` | Machine user PAT for GitHub API access | | `COPILOT_GITHUB_TOKEN` | GitHub Copilot fallback token | ## File Structure diff --git a/MACHINE_USER_SETUP.md b/MACHINE_USER_SETUP.md index 94107da49..a759c1bdd 100644 --- a/MACHINE_USER_SETUP.md +++ b/MACHINE_USER_SETUP.md @@ -45,13 +45,13 @@ Or use path-specific rules as needed. ## Step 4: Store the PAT as an Org Secret ```bash -gh secret set DON_PETRY_BOT_GH_PAT --org petry-projects --body "" +gh secret set DON_PETRY_BOT_PETRY_PROJECT_PAT --org petry-projects --body "" ``` Or store at repo level if preferred: ```bash -gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body "" +gh secret set DON_PETRY_BOT_PETRY_PROJECT_PAT --repo don-petry/pr-review-agent --body "" ``` ### Verify the secret is set: @@ -60,7 +60,7 @@ gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body ""` +3. Update the secret: `gh secret set DON_PETRY_BOT_PETRY_PROJECT_PAT --repo don-petry/pr-review-agent --body ""` 4. Revoke the old token ## Trade-offs vs GitHub App @@ -110,7 +110,7 @@ Fine-grained PATs have a configurable expiry (90-day recommended). To rotate: ### Issue: "Resource not accessible by integration" - Verify the PAT has the required scopes - Check the machine user has access to the target repos -- Ensure `DON_PETRY_BOT_GH_PAT` secret is set correctly +- Ensure `DON_PETRY_BOT_PETRY_PROJECT_PAT` secret is set correctly ### Issue: Approval doesn't satisfy code owner requirement - Verify the machine user is in the team listed in CODEOWNERS @@ -118,7 +118,7 @@ Fine-grained PATs have a configurable expiry (90-day recommended). To rotate: - Ensure branch protection has `require_code_owner_review: true` ### Issue: Token expired -- Generate a new fine-grained PAT and update the `DON_PETRY_BOT_GH_PAT` secret +- Generate a new fine-grained PAT and update the `DON_PETRY_BOT_PETRY_PROJECT_PAT` secret ## References diff --git a/SETUP.md b/SETUP.md index c4c54ceb2..c6d85f053 100644 --- a/SETUP.md +++ b/SETUP.md @@ -16,7 +16,7 @@ Store these in the repository settings (`Settings → Secrets and variables → | Secret | Description | Source | |--------|-------------|--------| | `CLAUDE_CODE_OAUTH_TOKEN` | Claude Code authentication token | `claude setup-token` | -| `DON_PETRY_BOT_GH_PAT` | Machine user fine-grained PAT | Generated from machine user account settings | +| `DON_PETRY_BOT_PETRY_PROJECT_PAT` | Machine user fine-grained PAT | Generated from machine user account settings | | `COPILOT_GITHUB_TOKEN` | GitHub Copilot token (optional, for fallback) | GitHub PAT with Copilot scope | ### Repository Variables (Optional) @@ -94,7 +94,7 @@ gh run list --repo don-petry/pr-review-agent -w pr-review.yml -L 5 ## Troubleshooting ### Workflow fails: "Resource not accessible by integration" -- Verify the `DON_PETRY_BOT_GH_PAT` secret is set and the token hasn't expired +- Verify the `DON_PETRY_BOT_PETRY_PROJECT_PAT` secret is set and the token hasn't expired - Check the machine user has access to the target repos - Ensure the PAT has the required scopes (Contents: read, Pull requests: read/write, Checks: read) @@ -110,7 +110,7 @@ gh run list --repo don-petry/pr-review-agent -w pr-review.yml -L 5 ## Machine User Details -The bot authenticates as a machine user account with a fine-grained PAT stored as the `DON_PETRY_BOT_GH_PAT` secret. The machine user is added to an org team listed in CODEOWNERS, so its approvals satisfy code owner review requirements. +The bot authenticates as a machine user account with a fine-grained PAT stored as the `DON_PETRY_BOT_PETRY_PROJECT_PAT` secret. The machine user is added to an org team listed in CODEOWNERS, so its approvals satisfy code owner review requirements. For full setup instructions, see [MACHINE_USER_SETUP.md](MACHINE_USER_SETUP.md). @@ -140,7 +140,7 @@ prompts/ - **Fine-grained PAT** scoped to only the permissions needed (Contents: read, Pull requests: read/write, Checks: read) - **90-day expiry** on PAT — set a calendar reminder to rotate - **PAT** stored only in GitHub Secrets, never logged or committed -- **Rotation** — generate a new PAT, update `DON_PETRY_BOT_GH_PAT` secret, revoke old token +- **Rotation** — generate a new PAT, update `DON_PETRY_BOT_PETRY_PROJECT_PAT` secret, revoke old token ## Related Documentation diff --git a/STATUS.md b/STATUS.md index 13a5397cb..d37a17287 100644 --- a/STATUS.md +++ b/STATUS.md @@ -6,10 +6,10 @@ ## What Was Done ### 1. Machine User Authentication ✅ -- Machine user account with fine-grained PAT stored as `DON_PETRY_BOT_GH_PAT` org secret +- Machine user account with fine-grained PAT stored as `DON_PETRY_BOT_PETRY_PROJECT_PAT` org secret - Added to org team listed in CODEOWNERS — approvals satisfy code owner review requirements - Configured permissions: Contents (read), Pull requests (read/write), Checks (read) -- All workflows use `${{ secrets.DON_PETRY_BOT_GH_PAT }}` directly (no token generation step needed) +- All workflows use `${{ secrets.DON_PETRY_BOT_PETRY_PROJECT_PAT }}` directly (no token generation step needed) **Why Machine User?** (migrated from GitHub App — see [issue #27](https://github.com/don-petry/pr-review-agent/issues/27)) - GitHub Apps cannot be listed in CODEOWNERS (platform limitation) @@ -89,7 +89,7 @@ Previously used: GitHub App (`petry-projects-pr-review-agent[bot]`) with auto-ex ### Required Secrets ```bash -gh secret set DON_PETRY_BOT_GH_PAT --repo don-petry/pr-review-agent --body "" +gh secret set DON_PETRY_BOT_PETRY_PROJECT_PAT --repo don-petry/pr-review-agent --body "" gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo don-petry/pr-review-agent ``` From 445c15eb7cb999e3e9a024b9931acefa72dc9909 Mon Sep 17 00:00:00 2001 From: don-petry Date: Mon, 4 May 2026 15:44:55 -0500 Subject: [PATCH 3/3] chore: ignore .claude/scheduled_tasks.lock state file --- .claude/scheduled_tasks.lock | 1 - .gitignore | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock deleted file mode 100644 index 2ca773be0..000000000 --- a/.claude/scheduled_tasks.lock +++ /dev/null @@ -1 +0,0 @@ -{"sessionId":"d4b6df5f-2db3-4078-a12f-fda72237cecc","pid":2823,"procStart":"Mon May 4 19:54:33 2026","acquiredAt":1777926272584} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 20f484a01..6cbdc178d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ # The actions/checkout post-job sweep trips on unregistered git directories # here and emits exit-128 warnings on every run. .claude/worktrees/ +.claude/scheduled_tasks.lock