Problem
When the GitHub Action runs on a pull_request event whose triggering actor is a GitHub App bot, assertPermissions() fails hard:
Asserting permissions for user my-app[bot]...
permission: none
##[error]User my-app[bot] does not have write permissions
This happens for any PR opened by a bot, or a human PR whose latest push (synchronize) came from a bot — the actor is then the bot.
Cause
In packages/opencode/src/cli/cmd/github.handler.ts, all USER_EVENTS (including pull_request) run:
if (isUserEvent) {
await assertPermissions()
await addReaction(commentType)
}
and assertPermissions() calls repos.getCollaboratorPermissionLevel({ username: actor }), requiring admin/write. A GitHub App bot user is never a repo collaborator, so the API returns none and it throws. There's no bypass — use_github_token: true only changes token acquisition, not the actor check (confirmed through v1.18.18).
Use case
We auto-run PR review on every PR via on: pull_request. Some PRs are opened by our own GitHub App bots; we drive the action with our own installation token (use_github_token: true), so gating on the human actor's collaborator level doesn't fit — the token, not the actor, is what should be authorized.
Proposed fix (any of)
- Skip
assertPermissions() when use_github_token: true (the caller is vouching for the token they pass).
- Add an allowlist env (e.g.
ALLOWED_ACTORS) so trusted bot actors pass.
- Fall back to checking the token's installation permissions instead of the actor's collaborator level.
Problem
When the GitHub Action runs on a
pull_requestevent whose triggering actor is a GitHub App bot,assertPermissions()fails hard:This happens for any PR opened by a bot, or a human PR whose latest push (
synchronize) came from a bot — the actor is then the bot.Cause
In
packages/opencode/src/cli/cmd/github.handler.ts, allUSER_EVENTS(includingpull_request) run:and
assertPermissions()callsrepos.getCollaboratorPermissionLevel({ username: actor }), requiringadmin/write. A GitHub App bot user is never a repo collaborator, so the API returnsnoneand it throws. There's no bypass —use_github_token: trueonly changes token acquisition, not the actor check (confirmed through v1.18.18).Use case
We auto-run PR review on every PR via
on: pull_request. Some PRs are opened by our own GitHub App bots; we drive the action with our own installation token (use_github_token: true), so gating on the human actor's collaborator level doesn't fit — the token, not the actor, is what should be authorized.Proposed fix (any of)
assertPermissions()whenuse_github_token: true(the caller is vouching for the token they pass).ALLOWED_ACTORS) so trusted bot actors pass.