-
Notifications
You must be signed in to change notification settings - Fork 306
Description
Description
When a GitHub App (e.g., Copilot) triggers a pull_request_review event, the context.actor is the App's login (e.g., Copilot). This actor is not a GitHub user, so getCollaboratorPermissionLevel() returns a 404.
In check_membership.cjs, this 404 is returned as {authorized: false, error: "Copilot is not a user"} from checkRepositoryPermission(). The calling code then hits the error branch and exits immediately — before ever checking the GH_AW_ALLOWED_BOTS fallback.
Impact
The bots: field in workflow frontmatter is effectively broken for any GitHub App whose context.actor is not a valid GitHub user. The bot is correctly listed in GH_AW_ALLOWED_BOTS in the compiled lock file, but check_membership.cjs never evaluates it.
Example: You want to build an autonomous review pipeline where Copilot reviews a PR, and a gh-aw agent responds to the review (e.g., addresses comments, approves, or merges). You configure:
on:
pull_request_review:
types: [submitted]
bots: [Copilot]This compiles correctly — GH_AW_ALLOWED_BOTS: Copilot appears in the lock file. But when Copilot submits a review:
pre_activationrunscheck_membership.cjs- Role check calls
getCollaboratorPermissionLevel("Copilot")→ 404 →{error: "Copilot is not a user"} - The
if (result.error)branch fires → setsis_team_member=false,result=api_error→ returns - The bot allowlist check (
isAllowedBot,checkBotStatus) is never reached activatedoutput =false→activationandagentjobs are skipped- The agent never runs despite the bot being explicitly allowed
The workflow appears to work (no errors, pre_activation shows success) but silently does nothing. There is no log line indicating the bot check was attempted, making this difficult to debug.
Root Cause (in check_membership.cjs)
const result = await checkRepositoryPermission(actor, owner, repo, requiredPermissions);
if (result.error) {
// EXIT HERE — never reaches bot check below
core.setOutput("is_team_member", "false");
core.setOutput("result", "api_error");
return;
}
if (result.authorized) {
// ...
} else {
// Bot fallback lives here — unreachable when result.error is set
if (allowedBots && allowedBots.length > 0) {
if (isAllowedBot(actor, allowedBots)) {
// ...
}
}
}Repro Steps
- Create a gh-aw workflow triggered by
pull_request_review - Add a bot to the allowlist under
on::on: pull_request_review: types: [submitted] bots: [Copilot]
- Compile with
gh aw compile— lock file correctly showsGH_AW_ALLOWED_BOTS: Copilot - Have Copilot submit a review on a PR
- Observe:
pre_activationjob succeeds, butactivatedoutput isfalse→activationandagentjobs are skipped - In
pre_activationlogs:No subsequent log line about checking the bots list.GH_AW_ALLOWED_BOTS: Copilot Checking if user 'Copilot' has required permissions ⚠️ Repository permission check failed: Copilot is not a user
Expected Behavior
When checkRepositoryPermission fails with an error for an actor that IS in GH_AW_ALLOWED_BOTS, the code should fall through to the bot allowlist check instead of exiting early.
Suggested Fix
Move the bot fallback check so it runs when result.error is set AND the actor is in the allowed bots list:
const result = await checkRepositoryPermission(actor, owner, repo, requiredPermissions);
if (result.authorized) {
// ... authorized by role
} else {
// Check bot fallback (whether error or insufficient permissions)
if (allowedBots && allowedBots.length > 0 && isAllowedBot(actor, allowedBots)) {
const botStatus = await checkBotStatus(actor, owner, repo);
if (botStatus.isBot && botStatus.isActive) {
// ... authorized as bot
return;
}
}
// Not authorized by role or bot
if (result.error) {
core.setOutput("result", "api_error");
} else {
core.setOutput("result", "insufficient_permissions");
}
core.setOutput("is_team_member", "false");
}