diff --git a/.changeset/patch-activation-github-token-config.md b/.changeset/patch-activation-github-token-config.md new file mode 100644 index 0000000000..4e3d9b8fd6 --- /dev/null +++ b/.changeset/patch-activation-github-token-config.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Allow workflows to configure the activation job's GitHub token or GitHub App so reactions and status comments can run with the same credentials defined in the `on:` block. diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml index 66a5053bb1..ec9e51469c 100644 --- a/.github/workflows/archie.lock.yml +++ b/.github/workflows/archie.lock.yml @@ -119,6 +119,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1062,9 +1075,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1079,19 +1089,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index bc9b81022e..7ffbf6de85 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -105,6 +105,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1047,9 +1060,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1064,19 +1074,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index 80697a12a9..f6287fcd80 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -119,6 +119,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add rocket reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "rocket" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1103,9 +1116,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1120,19 +1130,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add rocket reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "rocket" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 8b959da8bb..c716e83393 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -148,6 +148,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1430,9 +1443,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1447,19 +1457,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml index 42cd91b3d3..05ec069005 100644 --- a/.github/workflows/craft.lock.yml +++ b/.github/workflows/craft.lock.yml @@ -102,6 +102,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1083,9 +1096,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1100,19 +1110,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/grumpy-reviewer.lock.yml b/.github/workflows/grumpy-reviewer.lock.yml index 229f1974a9..c901cdce83 100644 --- a/.github/workflows/grumpy-reviewer.lock.yml +++ b/.github/workflows/grumpy-reviewer.lock.yml @@ -115,6 +115,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1129,9 +1142,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1146,19 +1156,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml index eb1a9f2e60..b7e74889b6 100644 --- a/.github/workflows/mergefest.lock.yml +++ b/.github/workflows/mergefest.lock.yml @@ -107,6 +107,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1080,9 +1093,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1097,19 +1107,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 564859f1a7..0057959e3f 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -130,6 +130,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1156,9 +1169,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1173,19 +1183,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index a1345eb5cc..28ccf246a4 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -112,6 +112,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1119,9 +1132,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1136,19 +1146,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 92f14c9d84..ccfa09390b 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -122,6 +122,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1760,9 +1773,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1777,19 +1787,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml index 3cd78357b0..c8c7f8cd45 100644 --- a/.github/workflows/pr-nitpick-reviewer.lock.yml +++ b/.github/workflows/pr-nitpick-reviewer.lock.yml @@ -140,6 +140,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1232,9 +1245,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1249,19 +1259,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index 6e5a2e3839..5c2b7d18af 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -148,6 +148,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add rocket reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "rocket" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1291,9 +1304,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1308,19 +1318,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add rocket reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "rocket" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 2fafd7ba21..1a8c4789ef 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -167,6 +167,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1288,9 +1301,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1305,19 +1315,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/security-review.lock.yml b/.github/workflows/security-review.lock.yml index b93ea2a3d5..53844a256e 100644 --- a/.github/workflows/security-review.lock.yml +++ b/.github/workflows/security-review.lock.yml @@ -112,6 +112,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1208,9 +1221,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1225,19 +1235,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-agent.lock.yml b/.github/workflows/smoke-agent.lock.yml index 414bd4ee26..05ca52fbbd 100644 --- a/.github/workflows/smoke-agent.lock.yml +++ b/.github/workflows/smoke-agent.lock.yml @@ -51,6 +51,9 @@ jobs: runs-on: ubuntu-slim permissions: contents: read + discussions: write + issues: write + pull-requests: write outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: ${{ steps.add-comment.outputs.comment-id }} diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 6f521addc6..16a89b7199 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -124,6 +124,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add heart reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "heart" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -2655,9 +2668,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -2672,19 +2682,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add heart reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "heart" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index 37b0b64f5a..122a8a01a3 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -118,6 +118,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add hooray reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "hooray" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1552,9 +1565,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1569,19 +1579,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add hooray reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "hooray" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-copilot-arm.lock.yml b/.github/workflows/smoke-copilot-arm.lock.yml index f1356b63db..53ca60ad24 100644 --- a/.github/workflows/smoke-copilot-arm.lock.yml +++ b/.github/workflows/smoke-copilot-arm.lock.yml @@ -116,6 +116,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -2081,9 +2094,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -2098,19 +2108,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml index f00b6db4c6..af266e60eb 100644 --- a/.github/workflows/smoke-copilot.lock.yml +++ b/.github/workflows/smoke-copilot.lock.yml @@ -29,7 +29,7 @@ # - shared/github-queries-safe-input.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"d143f0ffe7b39be26e699e15f581038d7692fd3936cd0a1b7f5488e726a56405"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"73a535e5d847637934c1146674b9529b8472bda1f5f403896b1d1c8f78944ec7"} name: "Smoke Copilot" "on": @@ -118,6 +118,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + with: + github-token: ${{ secrets.GH_AW_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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -145,6 +158,7 @@ jobs: GH_AW_WORKFLOW_NAME: "Smoke Copilot" GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"\\u003e 📰 *BREAKING: Report filed by [{workflow_name}]({run_url})*{history_link}\",\"appendOnlyComments\":true,\"runStarted\":\"📰 BREAKING: [{workflow_name}]({run_url}) is now investigating this {event_type}. Sources say the story is developing...\",\"runSuccess\":\"📰 VERDICT: [{workflow_name}]({run_url}) has concluded. All systems operational. This is a developing story. 🎤\",\"runFailure\":\"📰 DEVELOPING STORY: [{workflow_name}]({run_url}) reports {status}. Our correspondents are investigating the incident...\"}" with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); setupGlobals(core, github, context, exec, io); @@ -2125,9 +2139,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -2142,19 +2153,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-copilot.md b/.github/workflows/smoke-copilot.md index db542afb0b..78900e7ad8 100644 --- a/.github/workflows/smoke-copilot.md +++ b/.github/workflows/smoke-copilot.md @@ -8,6 +8,7 @@ on: names: ["smoke"] reaction: "eyes" status-comment: true + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} permissions: contents: read pull-requests: read diff --git a/.github/workflows/smoke-create-cross-repo-pr.lock.yml b/.github/workflows/smoke-create-cross-repo-pr.lock.yml index e42e546455..ef607e9405 100644 --- a/.github/workflows/smoke-create-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-create-cross-repo-pr.lock.yml @@ -53,6 +53,9 @@ jobs: runs-on: ubuntu-slim permissions: contents: read + discussions: write + issues: write + pull-requests: write outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: ${{ steps.add-comment.outputs.comment-id }} diff --git a/.github/workflows/smoke-gemini.lock.yml b/.github/workflows/smoke-gemini.lock.yml index a3414766d4..19babdd6e3 100644 --- a/.github/workflows/smoke-gemini.lock.yml +++ b/.github/workflows/smoke-gemini.lock.yml @@ -117,6 +117,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add rocket reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "rocket" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1292,9 +1305,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1309,19 +1319,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add rocket reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "rocket" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-multi-pr.lock.yml b/.github/workflows/smoke-multi-pr.lock.yml index f885007f24..a5a36c75d0 100644 --- a/.github/workflows/smoke-multi-pr.lock.yml +++ b/.github/workflows/smoke-multi-pr.lock.yml @@ -112,6 +112,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1173,9 +1186,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1190,19 +1200,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-project.lock.yml b/.github/workflows/smoke-project.lock.yml index b2c5ec6696..5719034ce5 100644 --- a/.github/workflows/smoke-project.lock.yml +++ b/.github/workflows/smoke-project.lock.yml @@ -110,6 +110,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1566,9 +1579,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1583,19 +1593,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-temporary-id.lock.yml b/.github/workflows/smoke-temporary-id.lock.yml index a9701d4793..d48c2b1b0d 100644 --- a/.github/workflows/smoke-temporary-id.lock.yml +++ b/.github/workflows/smoke-temporary-id.lock.yml @@ -110,6 +110,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1169,9 +1182,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} matched_command: '' @@ -1186,19 +1196,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/smoke-test-tools.lock.yml b/.github/workflows/smoke-test-tools.lock.yml index 67814cbf15..be8d55698c 100644 --- a/.github/workflows/smoke-test-tools.lock.yml +++ b/.github/workflows/smoke-test-tools.lock.yml @@ -53,6 +53,9 @@ jobs: runs-on: ubuntu-slim permissions: contents: read + discussions: write + issues: write + pull-requests: write outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: ${{ steps.add-comment.outputs.comment-id }} diff --git a/.github/workflows/smoke-update-cross-repo-pr.lock.yml b/.github/workflows/smoke-update-cross-repo-pr.lock.yml index 66f6dc137d..197dd9cf4a 100644 --- a/.github/workflows/smoke-update-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-update-cross-repo-pr.lock.yml @@ -53,6 +53,9 @@ jobs: runs-on: ubuntu-slim permissions: contents: read + discussions: write + issues: write + pull-requests: write outputs: body: ${{ steps.sanitized.outputs.body }} comment_id: ${{ steps.add-comment.outputs.comment-id }} diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 51da19d99d..b53b5416d0 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -120,6 +120,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1182,9 +1195,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1199,19 +1209,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index 4f2d6943a3..fdc222084f 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -116,6 +116,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1347,9 +1360,6 @@ jobs: runs-on: ubuntu-slim permissions: contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_command_position.outputs.command_position_ok == 'true') }} matched_command: ${{ steps.check_command_position.outputs.matched_command }} @@ -1364,19 +1374,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for command workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml index 57470eb93c..6c2f0621e6 100644 --- a/.github/workflows/workflow-generator.lock.yml +++ b/.github/workflows/workflow-generator.lock.yml @@ -108,6 +108,19 @@ jobs: sparse-checkout-cone-mode: true fetch-depth: 1 persist-credentials: false + - name: Add eyes reaction for immediate feedback + id: react + if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_REACTION: "eyes" + 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/add_reaction.cjs'); + await main(); - name: Check workflow file timestamps uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: @@ -1149,9 +1162,6 @@ jobs: permissions: actions: read contents: read - discussions: write - issues: write - pull-requests: write outputs: activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_rate_limit.outputs.rate_limit_ok == 'true') }} matched_command: '' @@ -1166,19 +1176,6 @@ jobs: uses: ./actions/setup with: destination: /opt/gh-aw/actions - - name: Add eyes reaction for immediate feedback - id: react - if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id) - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 - env: - GH_AW_REACTION: "eyes" - 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/add_reaction.cjs'); - await main(); - name: Check team membership for workflow id: check_membership uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index a6e05b7ba2..c786b91391 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -1449,6 +1449,44 @@ "type": "boolean", "description": "Whether to post status comments (started/completed) on the triggering item. When true, adds a comment with workflow run link and updates it on completion. When false or not specified, no status comments are posted. Must be explicitly set to true to enable status comments - there is no automatic bundling with ai-reaction.", "examples": [true, false] + }, + "github-token": { + "type": "string", + "description": "Custom GitHub token to use for pre-activation reactions and activation status comments. When specified, overrides the default GITHUB_TOKEN for these operations.", + "examples": ["${{ secrets.MY_GITHUB_TOKEN }}"] + }, + "github-app": { + "type": "object", + "description": "GitHub App configuration for minting a token used in pre-activation reactions and activation status comments. When configured, a GitHub App installation access token is minted and used instead of the default GITHUB_TOKEN.", + "properties": { + "app-id": { + "type": "string", + "description": "GitHub App ID (e.g., '${{ vars.APP_ID }}'). Required to mint a GitHub App token." + }, + "private-key": { + "type": "string", + "description": "GitHub App private key (e.g., '${{ secrets.APP_PRIVATE_KEY }}'). Required to mint a GitHub App token." + }, + "owner": { + "type": "string", + "description": "Optional owner of the GitHub App installation (defaults to current repository owner if not specified)" + }, + "repositories": { + "type": "array", + "description": "Optional list of repositories to grant access to (defaults to current repository if not specified)", + "items": { + "type": "string" + } + } + }, + "required": ["app-id", "private-key"], + "additionalProperties": false, + "examples": [ + { + "app-id": "${{ vars.APP_ID }}", + "private-key": "${{ secrets.APP_PRIVATE_KEY }}" + } + ] } }, "additionalProperties": false, diff --git a/pkg/workflow/activation_github_token_test.go b/pkg/workflow/activation_github_token_test.go new file mode 100644 index 0000000000..c07fea2aec --- /dev/null +++ b/pkg/workflow/activation_github_token_test.go @@ -0,0 +1,328 @@ +//go:build !integration + +package workflow + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/github/gh-aw/pkg/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestActivationGitHubToken tests that on.github-token is extracted and used in the activation job +func TestActivationGitHubToken(t *testing.T) { + compiler := NewCompiler() + + t.Run("custom_token_used_in_reaction_step", func(t *testing.T) { + workflowData := &WorkflowData{ + Name: "Test Workflow", + AIReaction: "eyes", + ActivationGitHubToken: "${{ secrets.MY_GITHUB_TOKEN }}", + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + assert.Contains(t, stepsStr, "github-token: ${{ secrets.MY_GITHUB_TOKEN }}", "Reaction step should use custom token") + assert.NotContains(t, stepsStr, "github-token: ${{ secrets.GITHUB_TOKEN }}", "Reaction step should not use default GITHUB_TOKEN") + }) + + t.Run("default_token_used_when_no_custom_token", func(t *testing.T) { + workflowData := &WorkflowData{ + Name: "Test Workflow", + AIReaction: "eyes", + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + assert.Contains(t, stepsStr, "github-token: ${{ secrets.GITHUB_TOKEN }}", "Reaction step should use default GITHUB_TOKEN") + }) + + t.Run("custom_token_used_in_status_comment", func(t *testing.T) { + statusComment := true + workflowData := &WorkflowData{ + Name: "Test Workflow", + StatusComment: &statusComment, + ActivationGitHubToken: "${{ secrets.MY_GITHUB_TOKEN }}", + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + assert.Contains(t, stepsStr, "github-token: ${{ secrets.MY_GITHUB_TOKEN }}", "Add-comment step should use custom token") + }) + + t.Run("no_github_token_in_status_comment_when_using_default", func(t *testing.T) { + statusComment := true + workflowData := &WorkflowData{ + Name: "Test Workflow", + StatusComment: &statusComment, + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + // When using default token, no explicit github-token should be added to the add-comment step + commentIdx := strings.Index(stepsStr, "id: add-comment") + require.Greater(t, commentIdx, -1, "add-comment step should exist") + // Check the section around add-comment + addCommentSection := stepsStr[commentIdx:] + nextStepIdx := strings.Index(addCommentSection[10:], " - name:") + if nextStepIdx > -1 { + addCommentSection = addCommentSection[:nextStepIdx+10] + } + assert.NotContains(t, addCommentSection, "github-token:", "Add-comment step should not have explicit github-token when using default") + }) +} + +// TestActivationGitHubApp tests that on.github-app is extracted and used in the activation job +func TestActivationGitHubApp(t *testing.T) { + compiler := NewCompiler() + + t.Run("app_token_minted_before_reaction", func(t *testing.T) { + workflowData := &WorkflowData{ + Name: "Test Workflow", + AIReaction: "eyes", + ActivationGitHubApp: &GitHubAppConfig{ + AppID: "${{ vars.APP_ID }}", + PrivateKey: "${{ secrets.APP_PRIVATE_KEY }}", + }, + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + // Token mint step should appear before the reaction step + mintIdx := strings.Index(stepsStr, "id: activation-app-token") + reactIdx := strings.Index(stepsStr, "id: react") + assert.Greater(t, mintIdx, -1, "Token mint step should be present") + assert.Greater(t, reactIdx, -1, "Reaction step should be present") + assert.Less(t, mintIdx, reactIdx, "Token mint step should appear before reaction step") + + // Reaction step should use the app token + assert.Contains(t, stepsStr, "github-token: ${{ steps.activation-app-token.outputs.token }}", "Reaction step should use app token") + // App-id and private-key should be in the mint step + assert.Contains(t, stepsStr, "app-id: ${{ vars.APP_ID }}", "Mint step should contain app-id") + assert.Contains(t, stepsStr, "private-key: ${{ secrets.APP_PRIVATE_KEY }}", "Mint step should contain private-key") + }) + + t.Run("app_token_minted_before_status_comment", func(t *testing.T) { + statusComment := true + workflowData := &WorkflowData{ + Name: "Test Workflow", + StatusComment: &statusComment, + ActivationGitHubApp: &GitHubAppConfig{ + AppID: "${{ vars.APP_ID }}", + PrivateKey: "${{ secrets.APP_PRIVATE_KEY }}", + }, + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + // Token mint step should appear before the add-comment step + mintIdx := strings.Index(stepsStr, "id: activation-app-token") + commentIdx := strings.Index(stepsStr, "id: add-comment") + assert.Greater(t, mintIdx, -1, "Token mint step should be present") + assert.Greater(t, commentIdx, -1, "Add-comment step should be present") + assert.Less(t, mintIdx, commentIdx, "Token mint step should appear before add-comment step") + + // Add-comment step should use the app token + assert.Contains(t, stepsStr, "github-token: ${{ steps.activation-app-token.outputs.token }}", "Add-comment step should use app token") + }) + + t.Run("app_token_minted_once_for_both_reaction_and_comment", func(t *testing.T) { + statusComment := true + workflowData := &WorkflowData{ + Name: "Test Workflow", + AIReaction: "eyes", + StatusComment: &statusComment, + ActivationGitHubApp: &GitHubAppConfig{ + AppID: "${{ vars.APP_ID }}", + PrivateKey: "${{ secrets.APP_PRIVATE_KEY }}", + }, + } + + job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + require.NoError(t, err, "buildActivationJob should succeed") + require.NotNil(t, job) + + stepsStr := strings.Join(job.Steps, "") + // The token should be minted exactly once + mintCount := strings.Count(stepsStr, "id: activation-app-token") + assert.Equal(t, 1, mintCount, "Token mint step should appear exactly once") + + // Both steps should use the same app token + assert.Contains(t, stepsStr, "id: react", "Reaction step should be present") + assert.Contains(t, stepsStr, "id: add-comment", "Add-comment step should be present") + assert.Equal(t, 2, strings.Count(stepsStr, "github-token: ${{ steps.activation-app-token.outputs.token }}"), "Both reaction and comment steps should use app token") + }) +} + +// TestActivationGitHubTokenExtraction tests extraction of github-token and github-app from frontmatter +func TestActivationGitHubTokenExtraction(t *testing.T) { + compiler := NewCompiler() + + t.Run("extracts_github_token_from_on_section", func(t *testing.T) { + frontmatter := map[string]any{ + "on": map[string]any{ + "workflow_dispatch": nil, + "github-token": "${{ secrets.MY_TOKEN }}", + }, + } + + token := compiler.extractActivationGitHubToken(frontmatter) + assert.Equal(t, "${{ secrets.MY_TOKEN }}", token, "Should extract github-token from on section") + }) + + t.Run("returns_empty_when_no_github_token", func(t *testing.T) { + frontmatter := map[string]any{ + "on": map[string]any{ + "workflow_dispatch": nil, + }, + } + + token := compiler.extractActivationGitHubToken(frontmatter) + assert.Empty(t, token, "Should return empty string when github-token not set") + }) + + t.Run("extracts_github_app_from_on_section", func(t *testing.T) { + frontmatter := map[string]any{ + "on": map[string]any{ + "workflow_dispatch": nil, + "github-app": map[string]any{ + "app-id": "${{ vars.APP_ID }}", + "private-key": "${{ secrets.KEY }}", + }, + }, + } + + app := compiler.extractActivationGitHubApp(frontmatter) + require.NotNil(t, app, "Should extract github-app from on section") + assert.Equal(t, "${{ vars.APP_ID }}", app.AppID, "App ID should match") + assert.Equal(t, "${{ secrets.KEY }}", app.PrivateKey, "Private key should match") + }) + + t.Run("returns_nil_when_no_github_app", func(t *testing.T) { + frontmatter := map[string]any{ + "on": map[string]any{ + "workflow_dispatch": nil, + }, + } + + app := compiler.extractActivationGitHubApp(frontmatter) + assert.Nil(t, app, "Should return nil when github-app not set") + }) +} + +// TestActivationGitHubTokenCompiledWorkflow tests that github-token and github-app are +// properly handled in the generated workflow YAML +func TestActivationGitHubTokenCompiledWorkflow(t *testing.T) { + tmpDir := testutil.TempDir(t, "activation-github-token-test") + compiler := NewCompiler() + + t.Run("github_token_used_in_reaction_step", func(t *testing.T) { + workflowContent := `--- +on: + issue_comment: + types: [created] + github-token: ${{ secrets.MY_TOKEN }} + reaction: eyes +engine: copilot +--- +Do something useful. +` + mdPath := filepath.Join(tmpDir, "token-workflow.md") + err := os.WriteFile(mdPath, []byte(workflowContent), 0600) + require.NoError(t, err) + + lockPath := filepath.Join(tmpDir, "token-workflow.lock.yml") + err = compiler.CompileWorkflow(mdPath) + require.NoError(t, err, "Compilation should succeed") + + lockContent, err := os.ReadFile(lockPath) + require.NoError(t, err) + + lockStr := string(lockContent) + // github-token should NOT appear as an on: section key (it's either filtered or commented) + assert.NotContains(t, lockStr, "\n github-token: ${{ secrets.MY_TOKEN }}", "github-token should not appear as on: event key") + + // The token should be used in the reaction step + assert.Contains(t, lockStr, "github-token: ${{ secrets.MY_TOKEN }}", "Token should be used in the reaction step") + }) + + t.Run("github_token_commented_when_no_reaction", func(t *testing.T) { + workflowContent := `--- +on: + issue_comment: + types: [created] + github-token: ${{ secrets.MY_TOKEN }} +engine: copilot +--- +Do something useful. +` + mdPath := filepath.Join(tmpDir, "token-only-workflow.md") + err := os.WriteFile(mdPath, []byte(workflowContent), 0600) + require.NoError(t, err) + + lockPath := filepath.Join(tmpDir, "token-only-workflow.lock.yml") + err = compiler.CompileWorkflow(mdPath) + require.NoError(t, err, "Compilation should succeed") + + lockContent, err := os.ReadFile(lockPath) + require.NoError(t, err) + + lockStr := string(lockContent) + // github-token should be commented out in the on: section + assert.Contains(t, lockStr, "# github-token:", "github-token should be commented out in on section") + assert.NotContains(t, lockStr, "\n github-token: ${{ secrets.MY_TOKEN }}", "github-token should not appear uncommented in on section") + }) + + t.Run("github_app_token_minted_and_used_in_reaction", func(t *testing.T) { + workflowContent := `--- +on: + issue_comment: + types: [created] + github-app: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_KEY }} + reaction: eyes +engine: copilot +--- +Do something useful. +` + mdPath := filepath.Join(tmpDir, "app-workflow.md") + err := os.WriteFile(mdPath, []byte(workflowContent), 0600) + require.NoError(t, err) + + lockPath := filepath.Join(tmpDir, "app-workflow.lock.yml") + err = compiler.CompileWorkflow(mdPath) + require.NoError(t, err, "Compilation should succeed") + + lockContent, err := os.ReadFile(lockPath) + require.NoError(t, err) + + lockStr := string(lockContent) + // The token mint step should be generated + assert.Contains(t, lockStr, "id: activation-app-token", "Token mint step should be generated") + assert.Contains(t, lockStr, "app-id: ${{ vars.APP_ID }}", "Token mint step should use app-id") + assert.Contains(t, lockStr, "github-token: ${{ steps.activation-app-token.outputs.token }}", "Reaction step should use app token") + }) +} diff --git a/pkg/workflow/compiler_activation_job.go b/pkg/workflow/compiler_activation_job.go index bc29817a2f..e9b110d4eb 100644 --- a/pkg/workflow/compiler_activation_job.go +++ b/pkg/workflow/compiler_activation_job.go @@ -66,6 +66,41 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate checkoutSteps := c.generateCheckoutGitHubFolderForActivation(data) steps = append(steps, checkoutSteps...) + // Mint a single activation app token upfront if a GitHub App is configured and either + // the reaction or status-comment step will need it. This avoids minting multiple tokens. + hasReaction := data.AIReaction != "" && data.AIReaction != "none" + hasStatusComment := data.StatusComment != nil && *data.StatusComment + if data.ActivationGitHubApp != nil && (hasReaction || hasStatusComment) { + // Build the combined permissions needed for reactions and/or status comments + appPerms := NewPermissions() + appPerms.Set(PermissionIssues, PermissionWrite) + appPerms.Set(PermissionPullRequests, PermissionWrite) + appPerms.Set(PermissionDiscussions, PermissionWrite) + steps = append(steps, c.buildActivationAppTokenMintStep(data.ActivationGitHubApp, appPerms)...) + } + + // Add reaction step for immediate feedback. + // This runs in the activation job so it can use any configured github-token or github-app. + if hasReaction { + reactionCondition := BuildReactionCondition() + + steps = append(steps, fmt.Sprintf(" - name: Add %s reaction for immediate feedback\n", data.AIReaction)) + steps = append(steps, " id: react\n") + steps = append(steps, fmt.Sprintf(" if: %s\n", reactionCondition.Render())) + steps = append(steps, fmt.Sprintf(" uses: %s\n", GetActionPin("actions/github-script"))) + + // Add environment variables + steps = append(steps, " env:\n") + // Quote the reaction value to prevent YAML interpreting +1/-1 as integers + steps = append(steps, fmt.Sprintf(" GH_AW_REACTION: %q\n", data.AIReaction)) + + steps = append(steps, " with:\n") + // Use configured github-token or app-minted token; fall back to GITHUB_TOKEN + steps = append(steps, fmt.Sprintf(" github-token: %s\n", c.resolveActivationToken(data))) + steps = append(steps, " script: |\n") + steps = append(steps, generateGitHubScriptWithRequire("add_reaction.cjs")) + } + // Add timestamp check for lock file vs source file using GitHub API // No checkout step needed - uses GitHub API to check commit times steps = append(steps, " - name: Check workflow file timestamps\n") @@ -104,7 +139,6 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate } // Add comment with workflow run link if status comments are explicitly enabled - // Note: The reaction was already added in the pre-activation job for immediate feedback if data.StatusComment != nil && *data.StatusComment { reactionCondition := BuildReactionCondition() @@ -139,10 +173,15 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate } steps = append(steps, " with:\n") + // Use configured github-token or app-minted token if set; omit to use default GITHUB_TOKEN + commentToken := c.resolveActivationToken(data) + if commentToken != "${{ secrets.GITHUB_TOKEN }}" { + steps = append(steps, fmt.Sprintf(" github-token: %s\n", commentToken)) + } steps = append(steps, " script: |\n") steps = append(steps, generateGitHubScriptWithRequire("add_workflow_run_comment.cjs")) - // Add comment outputs (no reaction_id since reaction was added in pre-activation) + // Add comment outputs outputs["comment_id"] = "${{ steps.add-comment.outputs.comment-id }}" outputs["comment_url"] = "${{ steps.add-comment.outputs.comment-url }}" outputs["comment_repo"] = "${{ steps.add-comment.outputs.comment-repo }}" @@ -287,13 +326,22 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate steps = append(steps, " retention-days: 1\n") // Set permissions - activation job always needs contents:read for GitHub API access - // Also add reaction permissions if reaction is configured and not "none" + // Also add reaction/comment permissions if reaction or status-comment is configured // Also add issues:write permission if lock-for-agent is enabled (for locking issues) permsMap := map[PermissionScope]PermissionLevel{ PermissionContents: PermissionRead, // Always needed for GitHub API access to check file commits } - if data.AIReaction != "" && data.AIReaction != "none" { + if hasReaction { + permsMap[PermissionDiscussions] = PermissionWrite + permsMap[PermissionIssues] = PermissionWrite + permsMap[PermissionPullRequests] = PermissionWrite + } + + // Add write permissions if status comments are enabled (even without a reaction). + // Status comments post to issues, PRs, and discussions, so write access is required. + // Assigning write to the map is safe here - it does not downgrade existing permissions. + if hasStatusComment { permsMap[PermissionDiscussions] = PermissionWrite permsMap[PermissionIssues] = PermissionWrite permsMap[PermissionPullRequests] = PermissionWrite diff --git a/pkg/workflow/compiler_activation_jobs_test.go b/pkg/workflow/compiler_activation_jobs_test.go index 855f7902ae..79d414443e 100644 --- a/pkg/workflow/compiler_activation_jobs_test.go +++ b/pkg/workflow/compiler_activation_jobs_test.go @@ -83,7 +83,7 @@ func TestBuildPreActivationJob_WithStopTime(t *testing.T) { "Steps should include the actual stop-time value") } -// TestBuildPreActivationJob_WithReaction tests building pre-activation job with reaction +// TestBuildPreActivationJob_WithReaction tests that reaction step is NOT in pre-activation (it moved to activation) func TestBuildPreActivationJob_WithReaction(t *testing.T) { compiler := NewCompiler() @@ -122,26 +122,34 @@ func TestBuildPreActivationJob_WithReaction(t *testing.T) { AIReaction: tt.reaction, } - job, err := compiler.buildPreActivationJob(workflowData, false) + // Pre-activation job should NOT contain the reaction step any more + preJob, err := compiler.buildPreActivationJob(workflowData, false) require.NoError(t, err) - require.NotNil(t, job) + require.NotNil(t, preJob) + preStepsStr := strings.Join(preJob.Steps, "\n") + assert.NotContains(t, preStepsStr, "GH_AW_REACTION", + "Pre-activation job should not contain reaction step") - stepsStr := strings.Join(job.Steps, "\n") + // Activation job should contain the reaction step + activationJob, err := compiler.buildActivationJob(workflowData, true, "", "test.lock.yml") + require.NoError(t, err) + require.NotNil(t, activationJob) + stepsStr := strings.Join(activationJob.Steps, "\n") if tt.shouldHaveReaction { assert.Contains(t, stepsStr, "Add "+tt.reaction+" reaction", - "Steps should include reaction step for %s", tt.reaction) + "Activation job steps should include reaction step for %s", tt.reaction) assert.Contains(t, stepsStr, "GH_AW_REACTION", - "Steps should include reaction environment variable") + "Activation job steps should include reaction environment variable") - // Check permissions include reaction permissions - assert.Contains(t, job.Permissions, "issues: write", - "Permissions should include issues: write for reactions") + // Check activation job permissions include reaction permissions + assert.Contains(t, activationJob.Permissions, "issues: write", + "Activation job permissions should include issues: write for reactions") } else { // When reaction is "none" or empty, no reaction step should be added if tt.reaction == "none" || tt.reaction == "" { assert.NotContains(t, stepsStr, "GH_AW_REACTION", - "Steps should not include reaction for %s", tt.reaction) + "Activation job steps should not include reaction for %s", tt.reaction) } } }) @@ -389,15 +397,15 @@ func TestBuildPreActivationJob_Integration(t *testing.T) { stepsStr := strings.Join(job.Steps, "\n") - // Should have all features + // Should have membership check and stop-time check (reaction moved to activation job) assert.Contains(t, stepsStr, "setup", "Should include setup step") assert.Contains(t, stepsStr, constants.CheckMembershipStepID.String(), "Should include membership check") assert.Contains(t, stepsStr, constants.CheckStopTimeStepID.String(), "Should include stop-time check") - assert.Contains(t, stepsStr, "eyes", "Should include reaction") + // Reaction step is in activation job now, not pre-activation + assert.NotContains(t, stepsStr, "GH_AW_REACTION", "Reaction step should NOT be in pre-activation job") - // Should have proper permissions - assert.Contains(t, job.Permissions, "issues: write", "Should have issues write permission") - assert.Contains(t, job.Permissions, "pull-requests: write", "Should have PR write permission") + // Pre-activation job should NOT have reaction write permissions (reaction moved to activation) + assert.NotContains(t, job.Permissions, "issues: write", "Pre-activation should not have issues write for reaction") // Should have activated output _, hasActivated := job.Outputs["activated"] diff --git a/pkg/workflow/compiler_orchestrator_workflow.go b/pkg/workflow/compiler_orchestrator_workflow.go index f2c6eb922e..5919d87d39 100644 --- a/pkg/workflow/compiler_orchestrator_workflow.go +++ b/pkg/workflow/compiler_orchestrator_workflow.go @@ -491,6 +491,8 @@ func (c *Compiler) extractAdditionalConfigurations( workflowData.RateLimit = c.extractRateLimitConfig(frontmatter) workflowData.SkipRoles = c.mergeSkipRoles(c.extractSkipRoles(frontmatter), importsResult.MergedSkipRoles) workflowData.SkipBots = c.mergeSkipBots(c.extractSkipBots(frontmatter), importsResult.MergedSkipBots) + workflowData.ActivationGitHubToken = c.extractActivationGitHubToken(frontmatter) + workflowData.ActivationGitHubApp = c.extractActivationGitHubApp(frontmatter) // Use the already extracted output configuration workflowData.SafeOutputs = safeOutputs diff --git a/pkg/workflow/compiler_pre_activation_job.go b/pkg/workflow/compiler_pre_activation_job.go index 8dc2b6e931..334ee2509f 100644 --- a/pkg/workflow/compiler_pre_activation_job.go +++ b/pkg/workflow/compiler_pre_activation_job.go @@ -47,17 +47,6 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec perms = NewPermissionsContentsRead() } - // Add reaction permissions if reaction is configured (reactions added in pre-activation for immediate feedback) - if data.AIReaction != "" && data.AIReaction != "none" { - if perms == nil { - perms = NewPermissions() - } - // Add write permissions for reactions - perms.Set(PermissionIssues, PermissionWrite) - perms.Set(PermissionPullRequests, PermissionWrite) - perms.Set(PermissionDiscussions, PermissionWrite) - } - // Add actions: read permission if rate limiting is configured (needed to query workflow runs) if data.RateLimit != nil { if perms == nil { @@ -71,29 +60,6 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec permissions = perms.RenderToYAML() } - // Add reaction step immediately after setup for instant user feedback - // This happens BEFORE any checks, so users see progress immediately - if data.AIReaction != "" && data.AIReaction != "none" { - reactionCondition := BuildReactionCondition() - - steps = append(steps, fmt.Sprintf(" - name: Add %s reaction for immediate feedback\n", data.AIReaction)) - steps = append(steps, " id: react\n") - steps = append(steps, fmt.Sprintf(" if: %s\n", reactionCondition.Render())) - steps = append(steps, fmt.Sprintf(" uses: %s\n", GetActionPin("actions/github-script"))) - - // Add environment variables - steps = append(steps, " env:\n") - // Quote the reaction value to prevent YAML interpreting +1/-1 as integers - steps = append(steps, fmt.Sprintf(" GH_AW_REACTION: %q\n", data.AIReaction)) - - steps = append(steps, " with:\n") - // Explicitly use the GitHub Actions token (GITHUB_TOKEN) for reactions - // This ensures proper authentication for adding reactions - steps = append(steps, " github-token: ${{ secrets.GITHUB_TOKEN }}\n") - steps = append(steps, " script: |\n") - steps = append(steps, generateGitHubScriptWithRequire("add_reaction.cjs")) - } - // Add team member check if permission checks are needed if needsPermissionCheck { steps = c.generateMembershipCheck(data, steps) diff --git a/pkg/workflow/compiler_safe_outputs.go b/pkg/workflow/compiler_safe_outputs.go index efc5414f0c..59f5e0394b 100644 --- a/pkg/workflow/compiler_safe_outputs.go +++ b/pkg/workflow/compiler_safe_outputs.go @@ -140,7 +140,7 @@ func (c *Compiler) parseOnSection(frontmatter map[string]any, workflowData *Work workflowData.On = "" } // Extract other (non-conflicting) events excluding slash_command, command, reaction, status-comment, and stop-after - otherEvents = filterMapKeys(onMap, "slash_command", "command", "reaction", "status-comment", "stop-after") + otherEvents = filterMapKeys(onMap, "slash_command", "command", "reaction", "status-comment", "stop-after", "github-token", "github-app") } } diff --git a/pkg/workflow/compiler_types.go b/pkg/workflow/compiler_types.go index 9ee0dc7c32..bf7618b1d0 100644 --- a/pkg/workflow/compiler_types.go +++ b/pkg/workflow/compiler_types.go @@ -399,6 +399,8 @@ type WorkflowData struct { CommandOtherEvents map[string]any // for merging command with other events AIReaction string // AI reaction type like "eyes", "heart", etc. StatusComment *bool // whether to post status comments (default: true when ai-reaction is set, false otherwise) + ActivationGitHubToken string // custom github token from on.github-token for reactions/comments + ActivationGitHubApp *GitHubAppConfig // github app config from on.github-app for minting activation tokens LockForAgent bool // whether to lock the issue during agent workflow execution Jobs map[string]any // custom job configurations with dependencies Cache string // cache configuration diff --git a/pkg/workflow/frontmatter_extraction_yaml.go b/pkg/workflow/frontmatter_extraction_yaml.go index 96ecf00b6d..a7cb6428ea 100644 --- a/pkg/workflow/frontmatter_extraction_yaml.go +++ b/pkg/workflow/frontmatter_extraction_yaml.go @@ -161,6 +161,7 @@ func (c *Compiler) commentOutProcessedFieldsInOnSection(yamlStr string, frontmat inSkipBotsArray := false inRolesArray := false inBotsArray := false + inGitHubApp := false currentSection := "" // Track which section we're in ("issues", "pull_request", "discussion", or "issue_comment") for _, line := range lines { @@ -272,6 +273,15 @@ func (c *Compiler) commentOutProcessedFieldsInOnSection(yamlStr string, frontmat } } + // Check if we're entering github-app object + if !inPullRequest && !inIssues && !inDiscussion && !inIssueComment && !inGitHubApp { + // Check both uncommented and commented forms + if (strings.HasPrefix(trimmedLine, "github-app:") && trimmedLine == "github-app:") || + (strings.HasPrefix(trimmedLine, "# github-app:") && strings.Contains(trimmedLine, "pre-activation job")) { + inGitHubApp = true + } + } + // Check if we're leaving skip-if-match object (encountering another top-level field) // Skip this check if we just entered skip-if-match on this line if inSkipIfMatch && strings.TrimSpace(line) != "" && @@ -298,6 +308,19 @@ func (c *Compiler) commentOutProcessedFieldsInOnSection(yamlStr string, frontmat } } + // Check if we're leaving github-app object (encountering another top-level field) + // Skip this check if we just entered github-app on this line + if inGitHubApp && strings.TrimSpace(line) != "" && + !strings.HasPrefix(trimmedLine, "github-app:") && + !strings.HasPrefix(trimmedLine, "# github-app:") { + // Get the indentation of the current line + lineIndent := len(line) - len(strings.TrimLeft(line, " \t")) + // If this is a field at same level as github-app (2 spaces) and not a comment, we're out of github-app + if lineIndent == 2 && !strings.HasPrefix(trimmedLine, "#") { + inGitHubApp = false + } + } + // Check if we're leaving the forks array by encountering another top-level field at the same level if inForksArray && inPullRequest && strings.TrimSpace(line) != "" { // Get the indentation of the current line @@ -410,6 +433,16 @@ func (c *Compiler) commentOutProcessedFieldsInOnSection(yamlStr string, frontmat } else if strings.HasPrefix(trimmedLine, "reaction:") { shouldComment = true commentReason = " # Reaction processed as activation job step" + } else if strings.HasPrefix(trimmedLine, "github-token:") { + shouldComment = true + commentReason = " # GitHub token used for reactions and status comments in activation" + } else if strings.HasPrefix(trimmedLine, "github-app:") { + shouldComment = true + commentReason = " # GitHub App used to mint token for reactions and status comments in activation" + } else if inGitHubApp && isGitHubAppNestedField(trimmedLine) { + // Comment out nested fields and array items in github-app object + shouldComment = true + commentReason = "" } } @@ -679,3 +712,16 @@ func (c *Compiler) extractCommandConfig(frontmatter map[string]any) (commandName return nil, nil } + +// isGitHubAppNestedField returns true if the trimmed YAML line represents a known +// nested field or array item inside an on.github-app object. +func isGitHubAppNestedField(trimmedLine string) bool { + githubAppFields := []string{"app-id:", "private-key:", "owner:", "repositories:"} + for _, field := range githubAppFields { + if strings.HasPrefix(trimmedLine, field) { + return true + } + } + // Array items (repositories list) + return strings.HasPrefix(trimmedLine, "-") +} diff --git a/pkg/workflow/reaction_none_test.go b/pkg/workflow/reaction_none_test.go index 4bc37754ee..a79021387e 100644 --- a/pkg/workflow/reaction_none_test.go +++ b/pkg/workflow/reaction_none_test.go @@ -161,25 +161,31 @@ Test command workflow with default (eyes) reaction. } compiled := string(compiledBytes) - // Verify that pre-activation job HAS reaction step (moved for immediate feedback) + // Verify that activation job HAS reaction step (moved from pre-activation) if !strings.Contains(compiled, "Add eyes reaction for immediate feedback") { - t.Error("Pre-activation job should have reaction step when reaction defaults to 'eyes'") + t.Error("Activation job should have reaction step when reaction defaults to 'eyes'") } - // Verify that pre-activation job HAS reaction permissions - preActivationJobSection := extractJobSection(compiled, string(constants.PreActivationJobName)) - if !strings.Contains(preActivationJobSection, "issues: write") { - t.Error("Pre-activation job should have 'issues: write' permission when reaction is enabled") + // Verify that activation job HAS reaction permissions + activationJobSection := extractJobSection(compiled, string(constants.ActivationJobName)) + if !strings.Contains(activationJobSection, "issues: write") { + t.Error("Activation job should have 'issues: write' permission when reaction is enabled") } - if !strings.Contains(preActivationJobSection, "pull-requests: write") { - t.Error("Pre-activation job should have 'pull-requests: write' permission when reaction is enabled") + if !strings.Contains(activationJobSection, "pull-requests: write") { + t.Error("Activation job should have 'pull-requests: write' permission when reaction is enabled") } - if !strings.Contains(preActivationJobSection, "discussions: write") { - t.Error("Pre-activation job should have 'discussions: write' permission when reaction is enabled") + if !strings.Contains(activationJobSection, "discussions: write") { + t.Error("Activation job should have 'discussions: write' permission when reaction is enabled") + } + + // Verify that pre-activation job does NOT have reaction permissions + preActivationJobSection := extractJobSection(compiled, string(constants.PreActivationJobName)) + if strings.Contains(preActivationJobSection, "issues: write") { + t.Error("Pre-activation job should NOT have 'issues: write' permission (reaction moved to activation)") } - // Verify that pre-activation job also has contents: read permission for checkout - if !strings.Contains(preActivationJobSection, "contents: read") { + // Verify that activation job has contents: read permission for checkout + if !strings.Contains(activationJobSection, "contents: read") { t.Error("Activation job should have 'contents: read' permission for checkout step") } @@ -245,9 +251,9 @@ Test command workflow with explicit rocket reaction. } compiled := string(compiledBytes) - // Verify that pre-activation job HAS rocket reaction step (moved for immediate feedback) + // Verify that activation job HAS rocket reaction step (moved from pre-activation) if !strings.Contains(compiled, "Add rocket reaction for immediate feedback") { - t.Error("Pre-activation job should have rocket reaction step") + t.Error("Activation job should have rocket reaction step") } // Verify that conclusion job IS created @@ -327,15 +333,15 @@ Test workflow triggered by issue template with "eyes" reaction. } compiled := string(compiledBytes) - // Verify that pre-activation job HAS eyes reaction step (moved for immediate feedback) + // Verify that activation job HAS eyes reaction step (moved from pre-activation) if !strings.Contains(compiled, "Add eyes reaction for immediate feedback") { - t.Error("Pre-activation job should have eyes reaction step for issue template workflow") + t.Error("Activation job should have eyes reaction step for issue template workflow") } - // Verify that pre-activation job HAS reaction permissions - preActivationJobSection := extractJobSection(compiled, string(constants.PreActivationJobName)) - if !strings.Contains(preActivationJobSection, "issues: write") { - t.Error("Pre-activation job should have 'issues: write' permission when reaction is enabled") + // Verify that activation job HAS reaction permissions + activationJobSection := extractJobSection(compiled, string(constants.ActivationJobName)) + if !strings.Contains(activationJobSection, "issues: write") { + t.Error("Activation job should have 'issues: write' permission when reaction is enabled") } // Verify that lock issue step is present (due to lock-for-agent: true) diff --git a/pkg/workflow/role_checks.go b/pkg/workflow/role_checks.go index 7cfa2b8c96..bb2611b4d2 100644 --- a/pkg/workflow/role_checks.go +++ b/pkg/workflow/role_checks.go @@ -630,3 +630,35 @@ func (c *Compiler) mergeSkipBots(topSkipBots []string, importedSkipBots []string return result } + +// extractActivationGitHubToken extracts the 'github-token' field from the 'on:' section of frontmatter. +// This token is used for pre-activation reactions and activation status comments. +func (c *Compiler) extractActivationGitHubToken(frontmatter map[string]any) string { + if onValue, exists := frontmatter["on"]; exists { + if onMap, ok := onValue.(map[string]any); ok { + if tokenValue, hasToken := onMap["github-token"]; hasToken { + if tokenStr, ok := tokenValue.(string); ok { + roleLog.Printf("Extracted activation github-token from on section") + return tokenStr + } + } + } + } + return "" +} + +// extractActivationGitHubApp extracts the 'github-app' field from the 'on:' section of frontmatter. +// When configured, a GitHub App installation access token is minted for use in reactions and status comments. +func (c *Compiler) extractActivationGitHubApp(frontmatter map[string]any) *GitHubAppConfig { + if onValue, exists := frontmatter["on"]; exists { + if onMap, ok := onValue.(map[string]any); ok { + if appValue, hasApp := onMap["github-app"]; hasApp { + if appMap, ok := appValue.(map[string]any); ok { + roleLog.Printf("Extracted activation github-app from on section") + return parseAppConfig(appMap) + } + } + } + } + return nil +} diff --git a/pkg/workflow/safe_outputs_app.go b/pkg/workflow/safe_outputs_app.go index 476e70607a..c327227238 100644 --- a/pkg/workflow/safe_outputs_app.go +++ b/pkg/workflow/safe_outputs_app.go @@ -267,3 +267,67 @@ func (c *Compiler) buildGitHubAppTokenInvalidationStep() []string { return steps } + +// ======================================== +// Activation Token Steps Generation +// ======================================== + +// buildActivationAppTokenMintStep generates the step to mint a GitHub App installation access token +// for use in the pre-activation (reaction) and activation (status comment) jobs. +func (c *Compiler) buildActivationAppTokenMintStep(app *GitHubAppConfig, permissions *Permissions) []string { + safeOutputsAppLog.Printf("Building activation GitHub App token mint step: owner=%s", app.Owner) + var steps []string + + steps = append(steps, " - name: Generate GitHub App token for activation\n") + steps = append(steps, " id: activation-app-token\n") + steps = append(steps, fmt.Sprintf(" uses: %s\n", GetActionPin("actions/create-github-app-token"))) + steps = append(steps, " with:\n") + steps = append(steps, fmt.Sprintf(" app-id: %s\n", app.AppID)) + steps = append(steps, fmt.Sprintf(" private-key: %s\n", app.PrivateKey)) + + // Add owner - default to current repository owner if not specified + owner := app.Owner + if owner == "" { + owner = "${{ github.repository_owner }}" + } + steps = append(steps, fmt.Sprintf(" owner: %s\n", owner)) + + // Default to current repository + steps = append(steps, " repositories: ${{ github.event.repository.name }}\n") + + // Always add github-api-url from environment variable + steps = append(steps, " github-api-url: ${{ github.api_url }}\n") + + // Add permission-* fields automatically computed from job permissions + if permissions != nil { + permissionFields := convertPermissionsToAppTokenFields(permissions) + + keys := make([]string, 0, len(permissionFields)) + for key := range permissionFields { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + steps = append(steps, fmt.Sprintf(" %s: %s\n", key, permissionFields[key])) + } + } + + return steps +} + +// resolveActivationToken returns the GitHub token to use for activation steps (reactions, status comments). +// Priority: GitHub App minted token > custom github-token > GITHUB_TOKEN (default) +// +// When returning the app token reference, callers MUST ensure that buildActivationAppTokenMintStep +// has already been called to generate the 'activation-app-token' step, since this function returns +// a reference to that step's output (${{ steps.activation-app-token.outputs.token }}). +func (c *Compiler) resolveActivationToken(data *WorkflowData) string { + if data.ActivationGitHubApp != nil { + return "${{ steps.activation-app-token.outputs.token }}" + } + if data.ActivationGitHubToken != "" { + return data.ActivationGitHubToken + } + return "${{ secrets.GITHUB_TOKEN }}" +} diff --git a/pkg/workflow/task_and_reaction_permissions_test.go b/pkg/workflow/task_and_reaction_permissions_test.go index 0bbcb46025..5c9ba42519 100644 --- a/pkg/workflow/task_and_reaction_permissions_test.go +++ b/pkg/workflow/task_and_reaction_permissions_test.go @@ -101,9 +101,8 @@ The activation job references text output: "${{ steps.sanitized.outputs.text }}" t.Error("Activation job should have pull-requests: write permission") } - // Test 6: Verify reaction step is in pre-activation job (moved for immediate feedback) - preActivationJobSection := extractJobSection(lockContentStr, string(constants.PreActivationJobName)) - if !strings.Contains(preActivationJobSection, "Add eyes reaction for immediate feedback") { - t.Error("Pre-activation job should contain the reaction step") + // Test 6: Verify reaction step is in activation job (moved from pre-activation) + if !strings.Contains(activationJobSection, "Add eyes reaction for immediate feedback") { + t.Error("Activation job should contain the reaction step") } }