Skip to content

fix: grant pull-requests: write for issue_comment reactions (slash_command PR comment fix) - #28854

Merged
pelikhan merged 3 commits into
mainfrom
copilot/fix-slash-command-reaction-permission
Apr 28, 2026
Merged

fix: grant pull-requests: write for issue_comment reactions (slash_command PR comment fix)#28854
pelikhan merged 3 commits into
mainfrom
copilot/fix-slash-command-reaction-permission

Conversation

CopilotAI commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

slash_command: events: [pull_request_comment] compiles to issue_comment (the actual GitHub event). The activation job permission derivation only checked for pull_request and pull_request_review_comment when deciding to grant pull-requests: write — missing issue_comment. GitHub requires pull-requests: write to react to PR-associated comments even though the API path is /issues/comments/{id}/reactions, causing 403 failures at the reaction step.

Changes

  • pkg/workflow/compiler_activation_job.go: Add hasIssueCommentEvent to the pull-requests: write condition — issue_comment fires for both issue and PR comments, so PR reactions require this permission whenever that event is present:

    // BeforeifreactionIncludesPullRequests&& (hasPullRequestEvent||hasPullRequestReviewCommentEvent) {
    // AfterifreactionIncludesPullRequests&& (hasPullRequestEvent||hasPullRequestReviewCommentEvent||hasIssueCommentEvent) {
  • pkg/workflow/activation_permissions_scope_test.go: Two new tests — a unit test against addActivationInteractionPermissionsMap directly with issue_comment, and an end-to-end compilation test for slash_command: events: [pull_request_comment].

  • docs/adr/26535-event-scoped-activation-permission-derivation.md: Correct the normative spec (point 2 was wrong — issue_comment also mandates pull-requests: write when PR reactions are enabled).

CopilotAIand others added 2 commits April 28, 2026 05:27
…mand PR comments)
When a workflow uses `slash_command: events: [pull_request_comment]`, it compiles to
an `issue_comment` GitHub event. GitHub requires `pull-requests: write` to add
reactions to comments associated with pull requests, even though the API path is
`/issues/comments/{id}/reactions`.
The previous fix (#26720) only added `pull-requests: write` for `pull_request` and
`pull_request_review_comment` events, missing the `issue_comment` case.
This fix extends the condition to also include `hasIssueCommentEvent` when
`reactionIncludesPullRequests` is true, so that slash_command workflows with
`events: [pull_request_comment]` (and any workflow using issue_comment) correctly
grant `pull-requests: write` in the activation job.
Fixes #26727"
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/134eab02-7006-4c28-abf0-a5d0ac484eec
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAI changed the title [WIP] Fix missing pull-requests:write permission for slash_command reactionsfix: grant pull-requests: write for issue_comment reactions (slash_command PR comment fix)Apr 28, 2026
CopilotAI requested a review from pelikhanApril 28, 2026 05:30
@pelikhan
pelikhan marked this pull request as ready for review April 28, 2026 05:32
CopilotAI review requested due to automatic review settings April 28, 2026 05:32
@pelikhan
pelikhan merged commit 115b573 into mainApr 28, 2026
29 checks passed
@pelikhan
pelikhan deleted the copilot/fix-slash-command-reaction-permission branch April 28, 2026 05:32
@github-actionsgithub-actionsBot mentioned this pull request Apr 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 83/100

Excellent — tests comprehensively cover behavioral contracts for the permission-scoping fix.

MetricValue
New/modified tests analyzed14
✅ Design tests (behavioral contracts)14 (100%)
⚠️ Implementation tests (low value)0 (0%)
Tests with error/edge cases11 (79%)
Duplicate test clusters0
Test inflation detected⚠️ Yes (61 test lines / 4 production lines ≈ 15:1)
🚨 Coding-guideline violationsNone

Test Classification Details

View all 14 test classifications
TestFileClassificationNotes
TestActivationPermissionsIssueOnlyReactionAndStatusCommentactivation_permissions_scope_test.go✅ DesignE2E compile; asserts issues:write, excludes PR/discussion
TestActivationPermissionsPRReviewReactionOnlyactivation_permissions_scope_test.go✅ DesignE2E compile; asserts pull-requests:write for PR review events
TestActivationPermissionsPullRequestReactionRequiresPullRequestsWriteactivation_permissions_scope_test.go✅ DesignE2E; asserts both issues:write and pull-requests:write
TestActivationPermissionsReactionPullRequestsDisabledactivation_permissions_scope_test.go✅ DesignEdge case: reaction.pull-requests=false disables scopes
TestActivationPermissionsStatusCommentDiscussionsDisabledactivation_permissions_scope_test.go✅ DesignEdge case: status-comment.discussions=false
TestAddActivationInteractionPermissionsMapFallsBackOnInvalidOnYAMLactivation_permissions_scope_test.go✅ DesignEdge case: invalid YAML triggers safe fallback
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentDiscussionsToggleactivation_permissions_scope_test.go✅ DesignEdge case: unit-level toggle verification
TestActivationPermissionsStatusCommentIssuesDisabledactivation_permissions_scope_test.go✅ DesignEdge case: status-comment.issues=false
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentIssuesToggleactivation_permissions_scope_test.go✅ DesignEdge case: unit-level toggle verification
TestStatusCommentObjectRejectsAllTargetsDisabledactivation_permissions_scope_test.go✅ DesignError path: all targets disabled → compile error
TestActivationPermissionsStatusCommentPullRequestsDisabledactivation_permissions_scope_test.go✅ DesignEdge case: status-comment.pull-requests=false
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentPullRequestsToggleactivation_permissions_scope_test.go✅ DesignEdge case: unit-level toggle verification
TestActivationPermissionsIssueCommentReactionRequiresPullRequestsWriteactivation_permissions_scope_test.go✅ DesignCore fix: issue_comment event grants pull-requests:write
TestActivationPermissionsSlashCommandPRCommentReactionRequiresPullRequestsWriteactivation_permissions_scope_test.go✅ DesignE2E fix test: slash_command PR comment grants pull-requests:write

Test Inflation Note

The ratio of test lines added (61) to production lines added (4) is ≈ 15:1, which exceeds the 2:1 threshold — resulting in a 10-point deduction. However, this is entirely appropriate here: the PR fixes a narrow bug and the tests provide comprehensive regression coverage of all permission-scoping scenarios (9 E2E compile tests + 5 unit tests of the internal helper). The inflation is intentional and adds real safety.


Language Support

Tests analyzed:

  • 🟨 JavaScript (*.test.cjs, *.test.js): 0 tests

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All 14 tests verify observable behavioral contracts — permission scopes in compiled workflow output. The two key tests (TestActivationPermissionsIssueCommentReactionRequiresPullRequestsWrite and TestActivationPermissionsSlashCommandPRCommentReactionRequiresPullRequestsWrite) directly exercise the bug fix end-to-end.

📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

References:§25035755025

🧪 Test quality analysis by Test Quality Sentinel · ● 629.2K ·

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 83/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 14 new tests verify observable behavioral contracts for permission scoping.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adjusts activation-job permission derivation so workflows reacting to PR-associated comments (which arrive via the issue_comment GitHub event) receive pull-requests: write, avoiding 403s when adding reactions.

Changes:

  • Update activation permission derivation to consider issue_comment when deciding whether to grant pull-requests: write for reactions.
  • Add unit + end-to-end tests covering issue_comment and slash_command: events: [pull_request_comment].
  • Update ADR-26535 to correct the documented/normative permission rule.
Show a summary per file
FileDescription
pkg/workflow/compiler_activation_job.goExtends pull-requests: write derivation to include issue_comment when PR reactions are enabled.
pkg/workflow/activation_permissions_scope_test.goAdds regression tests for issue_comment and slash-command PR-comment compilation behavior.
docs/adr/26535-event-scoped-activation-permission-derivation.mdUpdates the ADR narrative + normative spec to reflect the corrected permission requirements.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3

### Decision

We will derive activation job permissions by parsing the `on:` section YAML at compile time, filtering out known metadata trigger fields, and granting only the write scopes required by the real GitHub event types that are configured. `issues: write` is granted only when `issues`, `issue_comment`, or `pull_request` events are present (since reactions and status comments on issues/PRs use the Issues REST API). `pull-requests: write` is granted only when `pull_request_review_comment` events are present. `discussions: write` is granted only when `discussion` or `discussion_comment` events are present. A fallback to the previous broad-grant behavior is preserved for synthetic or test `WorkflowData` instances where the `on:` section is empty.
We will derive activation job permissions by parsing the `on:` section YAML at compile time, filtering out known metadata trigger fields, and granting only the write scopes required by the real GitHub event types that are configured. `issues: write` is granted only when `issues`, `issue_comment`, or `pull_request` events are present (since reactions and status comments on issues/PRs use the Issues REST API). `pull-requests: write` is granted when `pull_request` or `pull_request_review_comment` events are present, or when `issue_comment` is present with PR reactions enabled (because `issue_comment` fires for PR comments and GitHub requires `pull-requests: write` to react to PR comments). `discussions: write` is granted only when `discussion` or `discussion_comment` events are present. A fallback to the previous broad-grant behavior is preserved for synthetic or test `WorkflowData` instances where the `on:` section is empty.

CopilotAIApr 28, 2026

Copy link

Choose a reason for hiding this comment

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

In the Decision paragraph, the wording implies pull-requests: write is granted whenever pull_request/pull_request_review_comment events are present. In the implementation, that permission is only added when reactions are enabled for pull requests (and now also for issue_comment in a PR-comment context). Consider tightening this text to explicitly include the reaction target gating so the ADR matches the current behavior.

Suggested change
We will derive activation job permissions by parsing the `on:` section YAML at compile time, filtering out known metadata trigger fields, and granting only the write scopes required by the real GitHub event types that are configured. `issues: write` is granted only when `issues`, `issue_comment`, or `pull_request` events are present (since reactions and status comments on issues/PRs use the Issues REST API). `pull-requests: write` is granted when `pull_request` or `pull_request_review_comment` events are present, or when`issue_comment`is present with PR reactions enabled (because `issue_comment` fires for PR comments and GitHub requires `pull-requests: write` to react to PR comments). `discussions: write` is granted only when `discussion` or `discussion_comment` events are present. A fallback to the previous broad-grant behavior is preserved for synthetic or test `WorkflowData` instances where the `on:` section is empty.
We will derive activation job permissions by parsing the `on:` section YAML at compile time, filtering out known metadata trigger fields, and granting only the write scopes required by the real GitHub event types that are configured. `issues: write` is granted only when `issues`, `issue_comment`, or `pull_request` events are present (since reactions and status comments on issues/PRs use the Issues REST API). `pull-requests: write` is granted only when reactions are enabled for pull-request targets: for `pull_request` or `pull_request_review_comment` events, or for`issue_comment`when it applies to a PR comment (because `issue_comment` fires for PR comments and GitHub requires `pull-requests: write` to react to PR comments). `discussions: write` is granted only when `discussion` or `discussion_comment` events are present. A fallback to the previous broad-grant behavior is preserved for synthetic or test `WorkflowData` instances where the `on:` section is empty.

Copilot uses AI. Check for mistakes.

1. Implementations **MUST** derive activation job write permissions from the set of real GitHub event types present in the `on:` section, not from the presence of `reaction` or `status-comment` configuration alone.
2. Implementations **MUST NOT** grant `pull-requests: write` in the activation job unless `pull_request_review_comment`is among the configured trigger events.
2. Implementations **MUST NOT** grant `pull-requests: write` in the activation job unless `pull_request`, `pull_request_review_comment`, or `issue_comment` is among the configured trigger events and the reaction/status-comment configuration includes pull requests. (`issue_comment` events fire for both issue comments and PR comments; since PR comments require `pull-requests: write` for reactions, the presence of `issue_comment` with PR reactions enabled mandates this permission.)

CopilotAIApr 28, 2026

Copy link

Choose a reason for hiding this comment

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

Normative spec point (2) says the reaction/status-comment configuration includes pull requests, but the current code only ever grants pull-requests: write in the reaction branch (status comments only add issues: write). To avoid a spec/implementation mismatch, consider rewording this requirement to reference reaction configuration specifically (or update the implementation if status-comment is intended to require pull-requests: write).

Suggested change
2. Implementations **MUST NOT** grant `pull-requests: write` in the activation job unless `pull_request`, `pull_request_review_comment`, or `issue_comment` is among the configured trigger events and the reaction/status-comment configuration includes pull requests. (`issue_comment` events fire for both issue comments and PR comments; since PR comments require `pull-requests: write` for reactions, the presence of `issue_comment` with PR reactions enabled mandates this permission.)
2. Implementations **MUST NOT** grant `pull-requests: write` in the activation job unless `pull_request`, `pull_request_review_comment`, or `issue_comment` is among the configured trigger events and the reaction configuration includes pull requests. (`issue_comment` events fire for both issue comments and PR comments; since PR comments require `pull-requests: write` for reactions, the presence of `issue_comment` with PR reactions enabled mandates this permission.)

Copilot uses AI. Check for mistakes.
Comment on lines +169 to +170
// compiles to issue_comment), so pull-requests: write is also needed when issue_comment is present.
if reactionIncludesPullRequests && (hasPullRequestEvent || hasPullRequestReviewCommentEvent || hasIssueCommentEvent) {

CopilotAIApr 28, 2026

Copy link

Choose a reason for hiding this comment

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

The new hasIssueCommentEvent branch is gated only by reactionIncludesPullRequests, but the reaction step itself only runs on issue_comment when reactionIncludesIssues is true (see BuildReactionConditionForTargets/buildReactionLikeCondition). With reaction.issues: false and reaction.pull-requests: true, this will grant pull-requests: write even though the activation reaction step can never execute for issue_comment, weakening least-privilege. Consider additionally requiring reactionIncludesIssues for the hasIssueCommentEvent part of this condition (or otherwise aligning permission derivation to the actual reaction condition).

Suggested change
// compiles to issue_comment), so pull-requests: write is also needed when issue_comment is present.
ifreactionIncludesPullRequests&& (hasPullRequestEvent||hasPullRequestReviewCommentEvent||hasIssueCommentEvent) {
// compiles to issue_comment), but the reaction step only runs for issue_comment when
// issue reactions are enabled, so permission derivation must match that gating.
ifreactionIncludesPullRequests&& (hasPullRequestEvent||hasPullRequestReviewCommentEvent|| (reactionIncludesIssues&&hasIssueCommentEvent)) {

Copilot uses AI. Check for mistakes.
rolfbjarne added a commit to dotnet/macios that referenced this pull request May 5, 2026
The activation job in the `macios-reviewer` workflow was missing `pull-requests: write` permission, causing the 'Add eyes reaction for immediate feedback' step to fail with a 403 when triggered by `/review` on a PR comment.
This was a known gh-aw bug ([github/gh-aw#28767](github/gh-aw#28767)), fixed in v0.71.2 via [github/gh-aw#28854](github/gh-aw#28854).
This PR recompiles the lock file with gh-aw v0.71.2, which adds `pull-requests: write` to the activation job.
🤖 Pull request created by Copilot
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Activation job missing pull-requests:write for slash_command reactions on PR comments

3 participants

@pelikhan