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
2 changes: 2 additions & 0 deletions .github/workflows/agent-performance-analyzer.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/archie.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/brave.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/ci-doctor.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/daily-assign-issue-to-user.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/daily-cli-performance.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/daily-fact.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/dev-hawk.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/discussion-task-miner.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/issue-monster.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/pdf-summary.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/scout.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/smoke-agent.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/smoke-temporary-id.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/smoke-test-tools.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/sub-issue-closer.lock.yml

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

2 changes: 2 additions & 0 deletions .github/workflows/workflow-health-manager.lock.yml

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

10 changes: 9 additions & 1 deletion pkg/parser/schemas/main_workflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5023,7 +5023,15 @@
},
"discussions": {
"type": "boolean",
"description": "Controls whether the workflow requests discussions:write permission for add-comment. Default: true (includes discussions:write). Set to false if your GitHub App lacks Discussions permission to prevent 422 errors during token generation."
"description": "Controls whether the workflow requests discussions:write permission for add-comment and includes discussions in the event trigger condition. Default: true (includes discussions:write). Set to false if your GitHub App lacks Discussions permission to prevent 422 errors during token generation."
},
"issues": {
"type": "boolean",
"description": "Controls whether the workflow requests issues:write permission for add-comment and includes issues in the event trigger condition. Default: true (includes issues:write). Set to false to disable issue commenting."
},
"pull-requests": {
"type": "boolean",
"description": "Controls whether the workflow requests pull-requests:write permission for add-comment and includes pull requests in the event trigger condition. Default: true (includes pull-requests:write). Set to false to disable pull request commenting."
}
},
"additionalProperties": false,
Expand Down
60 changes: 42 additions & 18 deletions pkg/workflow/add_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ type AddCommentsConfig struct {
Discussion *bool `yaml:"discussion,omitempty"` // Target discussion comments instead of issue/PR comments. Must be true if present.
HideOlderComments *string `yaml:"hide-older-comments,omitempty"` // When true, minimizes/hides all previous comments from the same workflow before creating the new comment
AllowedReasons []string `yaml:"allowed-reasons,omitempty"` // List of allowed reasons for hiding older comments (default: all reasons allowed)
Discussions *bool `yaml:"discussions,omitempty"` // When false, excludes discussions:write permission. Default (nil or true) includes discussions:write for GitHub Apps with Discussions permission.
Issues *bool `yaml:"issues,omitempty"` // When false, excludes issues:write permission and issues from event condition. Default (nil or true) includes issues:write.
PullRequests *bool `yaml:"pull-requests,omitempty"` // When false, excludes pull-requests:write permission and PRs from event condition. Default (nil or true) includes pull-requests:write.
Discussions *bool `yaml:"discussions,omitempty"` // When false, excludes discussions:write permission and discussions from event condition. Default (nil or true) includes discussions:write.
}

// buildCreateOutputAddCommentJob creates the add_comment job
Expand Down Expand Up @@ -91,14 +93,20 @@ func (c *Compiler) buildCreateOutputAddCommentJob(data *WorkflowData, mainJobNam
// Build job condition with event check if target is not specified
jobCondition := BuildSafeOutputType("add_comment")
if data.SafeOutputs.AddComments != nil && data.SafeOutputs.AddComments.Target == "" {
eventCondition := BuildOr(
BuildOr(
BuildPropertyAccess("github.event.issue.number"),
BuildPropertyAccess("github.event.pull_request.number"),
),
BuildPropertyAccess("github.event.discussion.number"),
)
jobCondition = BuildAnd(jobCondition, eventCondition)
var eventTerms []ConditionNode
if data.SafeOutputs.AddComments.Issues == nil || *data.SafeOutputs.AddComments.Issues {
eventTerms = append(eventTerms, BuildPropertyAccess("github.event.issue.number"))
}
if data.SafeOutputs.AddComments.PullRequests == nil || *data.SafeOutputs.AddComments.PullRequests {
eventTerms = append(eventTerms, BuildPropertyAccess("github.event.pull_request.number"))
}
if data.SafeOutputs.AddComments.Discussions == nil || *data.SafeOutputs.AddComments.Discussions {
eventTerms = append(eventTerms, BuildPropertyAccess("github.event.discussion.number"))
}
if len(eventTerms) > 0 {
eventCondition := &DisjunctionNode{Terms: eventTerms}
jobCondition = BuildAnd(jobCondition, eventCondition)
}
}

// Build the needs list - always depend on mainJobName, and conditionally on the other jobs
Expand All @@ -113,15 +121,11 @@ func (c *Compiler) buildCreateOutputAddCommentJob(data *WorkflowData, mainJobNam
needs = append(needs, createPullRequestJobName)
}

// Determine permissions based on discussions field
// Default (nil or true) includes discussions:write for GitHub Apps with Discussions permission
// Note: PR comments are issue comments, so only issues:write is needed, not pull_requests:write
var permissions *Permissions
if data.SafeOutputs.AddComments.Discussions != nil && !*data.SafeOutputs.AddComments.Discussions {
permissions = NewPermissionsContentsReadIssuesWrite()
} else {
permissions = NewPermissionsContentsReadIssuesWriteDiscussionsWrite()
}
// Determine permissions based on Issues, PullRequests, and Discussions fields.
// Issues: nil or true → issues:write (default: true)
// PullRequests: nil or true → pull-requests:write (default: true)
// Discussions: nil or true → discussions:write (default: true)
permissions := buildAddCommentPermissions(data.SafeOutputs.AddComments)

// Use the shared builder function to create the job
return c.buildSafeOutputJob(data, SafeOutputJobConfig{
Expand Down Expand Up @@ -191,3 +195,23 @@ func (c *Compiler) parseCommentsConfig(outputMap map[string]any) *AddCommentsCon

return &config
}

// buildAddCommentPermissions computes the permissions for the add_comment job based on config.
// Issues: nil or true → issues:write (default: true)
// PullRequests: nil or true → pull-requests:write (default: true)
// Discussions: nil or true → discussions:write (default: true)
func buildAddCommentPermissions(config *AddCommentsConfig) *Permissions {
permMap := map[PermissionScope]PermissionLevel{
PermissionContents: PermissionRead,
}
if config == nil || config.Issues == nil || *config.Issues {
permMap[PermissionIssues] = PermissionWrite
}
if config == nil || config.PullRequests == nil || *config.PullRequests {
permMap[PermissionPullRequests] = PermissionWrite
}
if config == nil || config.Discussions == nil || *config.Discussions {
permMap[PermissionDiscussions] = PermissionWrite
}
return NewPermissionsFromMap(permMap)
}
9 changes: 1 addition & 8 deletions pkg/workflow/safe_outputs_permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,7 @@ func ComputePermissionsForSafeOutputs(safeOutputs *SafeOutputsConfig) *Permissio
}
if safeOutputs.AddComments != nil {
safeOutputsPermissionsLog.Print("Adding permissions for add-comment")
// Check if discussions permission should be excluded (discussions: false)
// Default (nil or true) includes discussions:write for GitHub Apps with Discussions permission
// Note: PR comments are issue comments, so only issues:write is needed, not pull_requests:write
if safeOutputs.AddComments.Discussions != nil && !*safeOutputs.AddComments.Discussions {
permissions.Merge(NewPermissionsContentsReadIssuesWrite())
} else {
permissions.Merge(NewPermissionsContentsReadIssuesWriteDiscussionsWrite())
}
permissions.Merge(buildAddCommentPermissions(safeOutputs.AddComments))
}
if safeOutputs.CloseIssues != nil {
safeOutputsPermissionsLog.Print("Adding permissions for close-issue")
Expand Down
Loading
Loading