Skip to content

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

Merged
pelikhan merged 3 commits intomainfrom
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 intomainfrom
copilot/fix-slash-command-reaction-permission

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 28, 2026

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:

    // Before
    if reactionIncludesPullRequests && (hasPullRequestEvent || hasPullRequestReviewCommentEvent) {
    
    // After
    if reactionIncludesPullRequests && (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).

Copilot AI and 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>
Copilot AI changed the title [WIP] Fix missing pull-requests:write permission for slash_command reactions fix: grant pull-requests: write for issue_comment reactions (slash_command PR comment fix) Apr 28, 2026
Copilot AI requested a review from pelikhan April 28, 2026 05:30
@pelikhan pelikhan marked this pull request as ready for review April 28, 2026 05:32
Copilot AI review requested due to automatic review settings April 28, 2026 05:32
@pelikhan pelikhan merged commit 115b573 into main Apr 28, 2026
29 checks passed
@pelikhan pelikhan deleted the copilot/fix-slash-command-reaction-permission branch April 28, 2026 05:32
@github-actions github-actions Bot 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.

Metric Value
New/modified tests analyzed 14
✅ Design tests (behavioral contracts) 14 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 11 (79%)
Duplicate test clusters 0
Test inflation detected ⚠️ Yes (61 test lines / 4 production lines ≈ 15:1)
🚨 Coding-guideline violations None

Test Classification Details

View all 14 test classifications
Test File Classification Notes
TestActivationPermissionsIssueOnlyReactionAndStatusComment activation_permissions_scope_test.go ✅ Design E2E compile; asserts issues:write, excludes PR/discussion
TestActivationPermissionsPRReviewReactionOnly activation_permissions_scope_test.go ✅ Design E2E compile; asserts pull-requests:write for PR review events
TestActivationPermissionsPullRequestReactionRequiresPullRequestsWrite activation_permissions_scope_test.go ✅ Design E2E; asserts both issues:write and pull-requests:write
TestActivationPermissionsReactionPullRequestsDisabled activation_permissions_scope_test.go ✅ Design Edge case: reaction.pull-requests=false disables scopes
TestActivationPermissionsStatusCommentDiscussionsDisabled activation_permissions_scope_test.go ✅ Design Edge case: status-comment.discussions=false
TestAddActivationInteractionPermissionsMapFallsBackOnInvalidOnYAML activation_permissions_scope_test.go ✅ Design Edge case: invalid YAML triggers safe fallback
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentDiscussionsToggle activation_permissions_scope_test.go ✅ Design Edge case: unit-level toggle verification
TestActivationPermissionsStatusCommentIssuesDisabled activation_permissions_scope_test.go ✅ Design Edge case: status-comment.issues=false
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentIssuesToggle activation_permissions_scope_test.go ✅ Design Edge case: unit-level toggle verification
TestStatusCommentObjectRejectsAllTargetsDisabled activation_permissions_scope_test.go ✅ Design Error path: all targets disabled → compile error
TestActivationPermissionsStatusCommentPullRequestsDisabled activation_permissions_scope_test.go ✅ Design Edge case: status-comment.pull-requests=false
TestAddActivationInteractionPermissionsMapFallbackRespectsStatusCommentPullRequestsToggle activation_permissions_scope_test.go ✅ Design Edge case: unit-level toggle verification
TestActivationPermissionsIssueCommentReactionRequiresPullRequestsWrite activation_permissions_scope_test.go ✅ Design Core fix: issue_comment event grants pull-requests:write
TestActivationPermissionsSlashCommandPRCommentReactionRequiresPullRequestsWrite activation_permissions_scope_test.go ✅ Design E2E 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 ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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
File Description
pkg/workflow/compiler_activation_job.go Extends pull-requests: write derivation to include issue_comment when PR reactions are enabled.
pkg/workflow/activation_permissions_scope_test.go Adds regression tests for issue_comment and slash-command PR-comment compilation behavior.
docs/adr/26535-event-scoped-activation-permission-derivation.md Updates 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.
Copy link

Copilot AI Apr 28, 2026

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.)
Copy link

Copilot AI Apr 28, 2026

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) {
Copy link

Copilot AI Apr 28, 2026

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.
if reactionIncludesPullRequests && (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.
if reactionIncludesPullRequests && (hasPullRequestEvent || hasPullRequestReviewCommentEvent || (reactionIncludesIssues && hasIssueCommentEvent)) {

Copilot uses AI. Check for mistakes.
Sign up for free to 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