Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/smoke-copilot.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions pkg/workflow/activation_permissions_scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,37 @@ engine: copilot
assert.NotContains(t, activationJobSection, "discussions: write", "activation job should not include discussions: write for PR review comment reactions")
}

func TestActivationPermissionsPullRequestReactionRequiresPullRequestsWrite(t *testing.T) {
tmpDir := testutil.TempDir(t, "activation-perms-pull-request-reaction")
testFile := filepath.Join(tmpDir, "pull-request-reaction.md")
testContent := `---
on:
reaction: eyes
status-comment: false
pull_request:
types: [opened]
engine: copilot
---

# Pull request reaction permissions
`

err := os.WriteFile(testFile, []byte(testContent), 0644)
require.NoError(t, err, "failed to write test workflow")

compiler := NewCompiler()
err = compiler.CompileWorkflow(testFile)
require.NoError(t, err, "failed to compile workflow")

lockContent, err := os.ReadFile(stringutil.MarkdownToLockFile(testFile))
require.NoError(t, err, "failed to read generated lock file")

activationJobSection := extractJobSection(string(lockContent), string(constants.ActivationJobName))
assert.Contains(t, activationJobSection, "issues: write", "activation job should include issues: write for pull_request reactions")
assert.Contains(t, activationJobSection, "pull-requests: write", "activation job should include pull-requests: write for pull_request reactions")
assert.NotContains(t, activationJobSection, "discussions: write", "activation job should not include discussions: write for pull_request reactions")
}

func TestActivationPermissionsReactionPullRequestsDisabled(t *testing.T) {
tmpDir := testutil.TempDir(t, "activation-perms-reaction-pr-disabled")
testFile := filepath.Join(tmpDir, "reaction-pr-disabled.md")
Expand Down
8 changes: 3 additions & 5 deletions pkg/workflow/compiler_activation_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,17 +744,15 @@ func addActivationInteractionPermissionsMap(
hasDiscussionCommentEvent := eventSet["discussion_comment"]

if hasReaction {
// Reactions on issues, issue comments, and pull requests all use issues endpoints.
// Both issue and pull request reactions require issues:write because PR reactions
// are created via /issues/{number}/reactions.
// Reactions on issues, issue comments, and pull requests use issues endpoints.
needsIssuesWriteForIssueEvents := reactionIncludesIssues && (hasIssuesEvent || hasIssueCommentEvent)
needsIssuesWriteForPullRequestEvents := reactionIncludesPullRequests && hasPullRequestEvent
needsIssuesWriteForReaction := needsIssuesWriteForIssueEvents || needsIssuesWriteForPullRequestEvents
if needsIssuesWriteForReaction {
permsMap[PermissionIssues] = PermissionWrite
}
// Reactions on PR review comments use pull request review comment endpoints.
if reactionIncludesPullRequests && hasPullRequestReviewCommentEvent {
// Reactions on pull requests and PR review comments require pull-requests:write.
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

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

The new comment/logic adds pull-requests: write for pull_request reactions, but it’s not obvious why that scope is required given PR reactions are posted via the /issues/{number}/reactions endpoint. Consider adding a brief rationale (e.g., GitHub permission model requires pull-requests: write for PR reaction writes despite the issues endpoint) to avoid future refactors removing one of the scopes.

Suggested change
// Reactions on pull requests and PR review comments require pull-requests:write.
// GitHub's permission model still requires pull-requests:write when the reaction target is a
// pull request or PR review comment, even though the reaction is created via issues endpoints.

Copilot uses AI. Check for mistakes.
if reactionIncludesPullRequests && (hasPullRequestEvent || hasPullRequestReviewCommentEvent) {
permsMap[PermissionPullRequests] = PermissionWrite
}
// Reactions on discussions use GraphQL discussion APIs.
Expand Down
Loading