diff --git a/.github/workflows/quality-gate.lock.yml b/.github/workflows/quality-gate.lock.yml index d179e3d..9a68d18 100644 --- a/.github/workflows/quality-gate.lock.yml +++ b/.github/workflows/quality-gate.lock.yml @@ -22,7 +22,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"a1696b9b859e92c3a49a62d624589e0502fade0bcb86788830eb84fe9c9f2280","compiler_version":"v0.58.1","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"665fba115b8bc11ce02ad0f3427588792c3030249a1bd43d7bf5872814d625c2","compiler_version":"v0.58.1","strict":true} name: "Quality Gate" "on": @@ -32,6 +32,7 @@ name: "Quality Gate" pull_request_review: types: - submitted + # roles: all # Roles processed as role check in pre-activation job permissions: {} @@ -43,8 +44,6 @@ run-name: "Quality Gate" jobs: activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' runs-on: ubuntu-slim permissions: contents: read @@ -210,7 +209,6 @@ jobs: GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_IS_PR_COMMENT: ${{ github.event.issue.pull_request && 'true' || '' }} - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -230,8 +228,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, - GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT, - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT } }); - name: Validate prompt placeholders @@ -1099,30 +1096,6 @@ jobs: const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); await main(); - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - matched_command: '' - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@fa061e89469ef007881d22d3af5a8c9e62363a0d # v0.58.1 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: Copilot,copilot-pull-request-reviewer - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); - await main(); - safe_outputs: needs: agent if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true') diff --git a/.github/workflows/quality-gate.md b/.github/workflows/quality-gate.md index f35a019..35dcafc 100644 --- a/.github/workflows/quality-gate.md +++ b/.github/workflows/quality-gate.md @@ -2,6 +2,7 @@ on: pull_request_review: types: [submitted] + roles: all bots: [Copilot, copilot-pull-request-reviewer] permissions: diff --git a/.github/workflows/review-responder.lock.yml b/.github/workflows/review-responder.lock.yml index 3105c6f..e08e607 100644 --- a/.github/workflows/review-responder.lock.yml +++ b/.github/workflows/review-responder.lock.yml @@ -22,7 +22,7 @@ # For more information: https://github.github.com/gh-aw/introduction/overview/ # # -# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"9caa2f1aad768faa9d9a4ea6399a4c318cd0930174038c8e166debeb9d0ccd2a","compiler_version":"v0.58.1","strict":true} +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"e1defa99f6997703c92f43de1a3dcd3fcc7661ead5eb63b2ac8f1023f3db57be","compiler_version":"v0.58.1","strict":true} name: "Review Responder" "on": @@ -32,6 +32,7 @@ name: "Review Responder" pull_request_review: types: - submitted + # roles: all # Roles processed as role check in pre-activation job permissions: {} @@ -43,8 +44,6 @@ run-name: "Review Responder" jobs: activation: - needs: pre_activation - if: needs.pre_activation.outputs.activated == 'true' runs-on: ubuntu-slim permissions: contents: read @@ -213,7 +212,6 @@ jobs: GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} GH_AW_IS_PR_COMMENT: ${{ github.event.issue.pull_request && 'true' || '' }} - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -233,8 +231,7 @@ jobs: GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, - GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT, - GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + GH_AW_IS_PR_COMMENT: process.env.GH_AW_IS_PR_COMMENT } }); - name: Validate prompt placeholders @@ -1199,30 +1196,6 @@ jobs: const { main } = require('/opt/gh-aw/actions/handle_noop_message.cjs'); await main(); - pre_activation: - runs-on: ubuntu-slim - outputs: - activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} - matched_command: '' - steps: - - name: Setup Scripts - uses: github/gh-aw/actions/setup@fa061e89469ef007881d22d3af5a8c9e62363a0d # v0.58.1 - with: - destination: /opt/gh-aw/actions - - name: Check team membership for workflow - id: check_membership - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REQUIRED_ROLES: admin,maintainer,write - GH_AW_ALLOWED_BOTS: Copilot,copilot-pull-request-reviewer - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io); - const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); - await main(); - safe_outputs: needs: - activation diff --git a/.github/workflows/review-responder.md b/.github/workflows/review-responder.md index 85ba2fa..d3a876e 100644 --- a/.github/workflows/review-responder.md +++ b/.github/workflows/review-responder.md @@ -2,6 +2,7 @@ on: pull_request_review: types: [submitted] + roles: all bots: [Copilot, copilot-pull-request-reviewer] permissions: diff --git a/docs/agentic-workflows.md b/docs/agentic-workflows.md index 743594b..83dcdb9 100644 --- a/docs/agentic-workflows.md +++ b/docs/agentic-workflows.md @@ -208,22 +208,23 @@ The `check_membership.cjs` script (in `github/gh-aw`) works as follows: 2. Check actor's repo permission against `GH_AW_REQUIRED_ROLES` → approve if match 3. **Fallback**: Check if actor is in `GH_AW_ALLOWED_BOTS` AND bot is active/installed on repo → approve as `authorized_bot` -### Allowing bot triggers +> **⚠️ KNOWN BUG ([github/gh-aw#21098](https://github.com/github/gh-aw/issues/21098))**: Step 3 is unreachable for GitHub App actors. When a bot like `Copilot` triggers a workflow, step 2 calls `getCollaboratorPermissionLevel("Copilot")` which returns a 404 ("not a user"). This error causes `check_membership.cjs` to exit immediately via the `if (result.error)` branch — **before ever reaching the bot fallback in step 3**. The `bots:` field compiles correctly but the runtime never evaluates it. -For workflows triggered by bot events (e.g., Copilot reviewer submitting a review): +### Allowing bot triggers (WORKAROUND) + +Due to the upstream bug above, the `bots:` field alone is insufficient. The current workaround is `roles: all`, which tells the compiler to skip the permission check entirely (`check_membership.cjs` is not included in the `pre_activation` job): ```yaml on: pull_request_review: types: [submitted] - bots: [Copilot, copilot-pull-request-reviewer] # MUST be under on: + roles: all + bots: [Copilot, copilot-pull-request-reviewer] # keep for when upstream is fixed ``` -This compiles to `GH_AW_ALLOWED_BOTS: Copilot,copilot-pull-request-reviewer` in the lock file, which `check_membership.cjs` checks as a fallback. - -> **IMPORTANT**: The event **actor** for Copilot reviews is `Copilot` (the GitHub App), NOT `copilot-pull-request-reviewer` (the review author login). `check_membership.cjs` matches `context.actor` against the bots list, so `Copilot` is the identity that matters. Include both for safety. +This is overly permissive — any actor can trigger the workflow. Track removal via issue #74. -**DO NOT use `roles: all` just to allow bots.** It opens the workflow to any actor. Use `bots:` instead. +> **Actor identity note**: The event **actor** for Copilot reviews is `Copilot` (the GitHub App), NOT `copilot-pull-request-reviewer` (the review author login). `context.actor` returns `Copilot`. Keep both in the bots list for when the upstream bug is fixed. ### GitHub's `action_required` gate @@ -399,8 +400,8 @@ The workflow definition always comes from the default branch, not the PR branch. ### 7. GitHub's `action_required` is separate from gh-aw's `pre_activation` `action_required` means GitHub itself blocked the run (first-time contributor approval). No jobs run at all. `pre_activation` is gh-aw's role/bot check within the workflow. -### 8. Copilot has TWO identities — actor vs reviewer -The `pull_request_review` event actor (`context.actor`) is `Copilot`, but the review author login is `copilot-pull-request-reviewer`. `check_membership.cjs` matches against `context.actor`, so the `bots:` list MUST include `Copilot`. If you only list `copilot-pull-request-reviewer`, `pre_activation` will pass (job succeeds) but `activated` output will be `false` and the agent job gets skipped. +### 8. `bots:` field is broken due to upstream bug (gh-aw#21098) +The `bots:` field compiles correctly into `GH_AW_ALLOWED_BOTS` in the lock file, but `check_membership.cjs` never evaluates it for GitHub App actors. The role check fails with a 404 error and the `error` branch exits before the bot fallback. Use `roles: all` as a workaround (see #74 to track removal). ### 9. Always use merge commits Never squash merge — it loses commit history and the user gets angry. Set merge method preference explicitly. @@ -427,8 +428,7 @@ No jobs ran → GitHub's first-time contributor approval gate. Check repo Action The `pre_activation` job ran but the actor failed the role/bot check. Check: - Is `bots:` under `on:` in the `.md` file? - Does the lock file contain `GH_AW_ALLOWED_BOTS`? -- Does `GH_AW_ALLOWED_BOTS` contain the correct **actor** name? (For Copilot, the actor is `Copilot`, not `copilot-pull-request-reviewer`) -- Is the bot installed/active on the repo? +- **Known bug**: Even if the above are correct, `check_membership.cjs` never reaches the bot check for GitHub App actors (see [gh-aw#21098](https://github.com/github/gh-aw/issues/21098)). Use `roles: all` as a workaround. ### Check if Copilot reviewed ```bash @@ -520,7 +520,11 @@ gh run view --log-failed # View failed job logs - Two blockers remain: (1) GitHub Actions approval setting for bot actors, (2) PR #65 for correct `bots:` placement - Lesson: stop guessing, read the source code before making changes - After PR #65 merge: `pre_activation` passes (job succeeds) but `activated` output still `false` — agent jobs skipped -- Root cause: `context.actor` is `Copilot` (GitHub App identity) but bots list had `copilot-pull-request-reviewer` (reviewer login) — name mismatch -- Fix: PR #72 adds both `Copilot` and `copilot-pull-request-reviewer` to bots list +- PR #72: Added `Copilot` to bots list (correct actor name) — still didn't fix it +- Read actual `check_membership.cjs` source: the `error` branch from 404 exits BEFORE the bot fallback is ever reached +- **Three PRs merged to main (#64, #65, #72) based on guessing from logs. None fixed the problem.** +- Filed upstream bug: [github/gh-aw#21098](https://github.com/github/gh-aw/issues/21098) +- Workaround: `roles: all` skips `check_membership.cjs` entirely — tracked for removal in issue #74 +- Issue #75 documents the full root cause and links all previous failed attempts diff --git a/docs/changelog.md b/docs/changelog.md index 70101dd..d94578f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -10,6 +10,16 @@ Append-only history of repo-level changes (CI, infra, shared config). Tool-speci **Fix**: Added both `Copilot` and `copilot-pull-request-reviewer` to `bots:` in review-responder and quality-gate workflows. (PR #72, closes #73) +**Note**: This fix alone was insufficient — see the `roles: all` workaround entry below. The bot check is never reached due to upstream bug [github/gh-aw#21098](https://github.com/github/gh-aw/issues/21098). + +--- + +## workaround: roles: all for bot activation — 2026-03-15 + +**Problem**: Agent workflows (review-responder, quality-gate) never activate when triggered by Copilot reviews. Root cause is an upstream bug in gh-aw's `check_membership.cjs` ([github/gh-aw#21098](https://github.com/github/gh-aw/issues/21098)) — the `error` branch exits before the bot allowlist fallback is evaluated. Three previous PRs (#64, #65, #72) failed to fix this. + +**Workaround**: Added `roles: all` to skip the permission check entirely. Overly permissive but the only option until the upstream bug is fixed. (PR #76, closes #75, tracked for removal in #74) + --- ## ci: enable free GitHub security features — 2026-03-13