Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
-X PUT \
-f message="deploy: add pr-review.yml workflow" \
-f content="$CONTENT_B64" 2>&1 | tee deploy.log

# Check if successful
if grep -q '"commit"' deploy.log; then
echo "✅ Deployed to ${{ matrix.repo }}"
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/force-deploy-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ jobs:
matrix:
repo: [bmad-bgreat-suite, google-app-scripts]
max-parallel: 1

steps:
- uses: actions/checkout@v4

- name: Deploy pr-review.yml to ${{ matrix.repo }} via Actions
run: |
# Clone target repo
git clone https://${{ secrets.GITHUB_TOKEN }}@github.com/petry-projects/${{ matrix.repo }}.git target_repo
cd target_repo

# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

# Copy pr-review.yml
mkdir -p .github/workflows
cp ../.github/workflows/pr-review.yml .github/workflows/

# Commit and push
git add .github/workflows/pr-review.yml
if git commit -m "deploy: add pr-review.yml workflow [skip ci]"; then
Expand Down
24 changes: 17 additions & 7 deletions .github/workflows/pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,23 @@ jobs:
echo "$auth_status"
scopes_line="$(printf '%s\n' "$auth_status" | grep 'Token scopes:' || true)"
normalized_scopes="$(printf '%s' "$scopes_line" | sed "s/[',]/ /g")"
required_scopes=(repo read:org)
for required_scope in "${required_scopes[@]}"; do
if ! grep -qE "(^|[[:space:]])${required_scope}([[:space:]]|$)" <<< "$normalized_scopes"; then
echo "::error::GH_TOKEN is missing required scope: ${required_scope}"
exit 1
fi
done

# Check for required scopes. Accept either:
# - Classic PAT: 'repo' scope (grants full repo access)
Comment on lines 204 to +208
# - Fine-grained: 'contents' + 'pull_requests' (minimal permissions)
if grep -qE "(^|[[:space:]])repo([[:space:]]|$)" <<< "$normalized_scopes"; then
# Classic PAT with repo scope — sufficient
:
else
# Fine-grained token — verify minimal scopes
for required_scope in contents pull_requests; do
if ! grep -qE "(^|[[:space:]])${required_scope}([[:space:]]|$)" <<< "$normalized_scopes"; then
Comment on lines +215 to +216

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don’t validate fine-grained PATs as OAuth scopes

For runs using the newly recommended fine-grained PAT, this loop still looks for contents and pull_requests in the Token scopes: line from gh auth status. GitHub distinguishes fine-grained PAT permissions from classic PAT OAuth scopes, and gh auth status surfaces OAuth scopes from the token headers, so a valid fine-grained token with Contents read and Pull requests write can still have no literal contents/pull_requests scopes and fail here before any review starts. Probe the required endpoints/permissions instead, or only scope-check classic PATs.

Useful? React with 👍 / 👎.

echo "::error::GH_TOKEN is missing required scope: ${required_scope}"
echo "::error::Token must have either 'repo' scope (classic) or both 'contents' and 'pull_requests' (fine-grained)"
exit 1
fi
done
fi

- name: Install review engine CLIs
run: |
Expand Down
15 changes: 15 additions & 0 deletions agents/pr-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ tools: ["read", "edit", "search", "execute", "web"]

You are the PR Review Agent for the petry-projects organization.

## Required GitHub token scopes

The agent requires a GitHub personal access token (PAT) with these minimum permissions:

**Repository permissions:**
- `contents:read` — read file contents and diffs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Since the agent is configured to rebase branches that are behind their base branch, it requires write access to the repository contents. Using contents:read will cause the rebase push to fail. Please update this permission to contents:write (read file contents, diffs, and push rebase commits).

- `pull_requests:write` — post reviews and comments on PRs
- `actions:read` — check CI status and workflow results
- `metadata:read` — read repository metadata

**Organization permissions:**
- `members:read` — read organization members for code owner routing

These are fine-grained token scopes. The legacy `repo` scope (which grants full repository control) is NOT required.

## Your role

You review pull requests using a cascading tier system that minimizes token spend
Expand Down
60 changes: 35 additions & 25 deletions docs/pr-review-agent/pr-review-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,39 +129,49 @@ authored by `don-petry`; the bot approves them.
**Invite member** → enter `donpetry-bot` → Role: **Member**.
6. Accept the invite from the bot account.

### 2. Create a **classic** PAT for the bot

> [!IMPORTANT]
> **Fine-grained PATs do not work for this workflow.** Use a classic PAT only.
>
> Fine-grained tokens are blocked by org policy gates: even after the org owner
> approves the token request and the bot has Write collaborator access, the
> GraphQL `addPullRequestReview` mutation fails with:
>
> ```
> failed to create review: GraphQL: Resource not accessible by personal access token (addPullRequestReview)
> ```
>
> If you see that error in a workflow run, the secret holds a fine-grained
> token. Replace it with a classic PAT generated as below. The same gate also
> blocks the rulesets bypass that branch protections rely on.
### 2. Create a PAT for the bot (classic or fine-grained)

You can use either a **classic** or **fine-grained** PAT. Fine-grained tokens are
recommended for better security (principle of least privilege).

#### Option A: Fine-grained PAT (recommended)

1. Sign in as the bot account (e.g. `donpetry-bot`) — sign out of `don-petry`
first, or use a private window. The PAT must be created **from the bot's
account**, not yours.
2. Go to **Settings → Developer settings → Personal access tokens →
Tokens (classic)** → **Generate new token (classic)**.
Fine-grained tokens** → **Generate new token**.
3. Settings:
- **Note:** `pr-review-agent`
- **Expiration:** 1 year (set a calendar reminder to rotate)
- **Scopes:** ✅ `repo`, ✅ `workflow`, ✅ `read:org`
- **Token name:** `pr-review-agent`
- **Expiration:** 90 days (auto-rotate for security)
- **Resource owner:** select your organization (e.g. `petry-projects`)
- **Repository access:** All repositories (or specific repos if preferred)
- **Repository permissions:**
- `contents:read` — read files and diffs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Since the agent rebases branches when they are behind the base branch, it requires write access to the repository contents. contents:read is insufficient for pushing the rebased commits back to the branch. Please update this permission to contents:write (read files/diffs and push rebase commits).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Grant contents write for auto-merge

When someone follows the new recommended fine-grained PAT setup, approvals can be posted but auto-merge will not be enabled because scripts/post-pr-review.sh later runs gh pr merge "$PR_URL" --auto --squash, and GitHub requires the fine-grained token to have Contents write for PR merges. With only contents:read, that command is swallowed by || true, so the log can still say the review was posted and auto-merge enabled while the approved PR remains unmerged.

Useful? React with 👍 / 👎.

- `pull_requests:write` — post reviews and comments
- `actions:read` — check CI status
- `metadata:read` — read repo metadata
- **Organization permissions:**
- `members:read` — read org members for code owner routing
4. Generate and copy the token immediately.
5. Sign back in as `don-petry` and store the token in the agent repo's secret
(the secret name is `DON_PETRY_BOT_GH_PAT` in `petry-projects/.github-private`).

After saving, trigger a workflow run and confirm the install step's
`gh auth status` reports the bot's login (not yours) and lists the three
scopes above.
#### Option B: Classic PAT (legacy)

If you prefer classic PATs or need broader scopes:

1. Sign in as the bot account, go to **Settings → Developer settings →
Personal access tokens → Tokens (classic)** → **Generate new token (classic)**.
2. Settings:
- **Note:** `pr-review-agent`
- **Expiration:** 1 year
- **Scopes:** ✅ `repo`, ✅ `workflow`, ✅ `read:org`
3. Generate and store as `DON_PETRY_BOT_GH_PAT` (same as above).

After saving either token type, trigger a workflow run and confirm the
`gh auth status` output reports the bot's login (not yours) and lists the
required scopes.
Comment on lines +172 to +174

> **Branch protection / rulesets:** add `donpetry-bot` as an allowed
> approver on each protected repo. In the repo ruleset or branch protection
Expand Down Expand Up @@ -291,8 +301,8 @@ PR comment "@donpetry-bot please review"
`petry-projects/.github` as `.github/workflows/pr-review-mention.yml`.

2. Add the `DON_PETRY_BOT_GH_PAT` secret to `petry-projects/.github`
(org-level secret or repo secret on `.github`). Use a classic PAT from
`donpetry-bot` with scopes: ✅ `repo`, ✅ `workflow`, ✅ `read:org`
(org-level secret or repo secret on `.github`). Use the same PAT created above
in [step 2](#2-create-a-pat-for-the-bot-classic-or-fine-grained).
Comment on lines +304 to +305

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don’t reuse the read-only PAT for mention dispatch

For mention-triggered reviews, this now tells operators to put the same fine-grained PAT into petry-projects/.github, but that recommended token only has contents:read. The mention listener dispatches to .github-private via POST /repos/.../dispatches, and GitHub documents that creating a repository dispatch event with a fine-grained token requires Contents write, so @donpetry-bot mentions configured this way will acknowledge/resolve the PR but fail to start the review run.

Useful? React with 👍 / 👎.


3. Ensure `donpetry-bot` has at least **Read** collaborator access on
`petry-projects/.github-private`.
Expand Down