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
21 changes: 21 additions & 0 deletions docs/src/content/docs/reference/safe-outputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,8 +551,29 @@ safe-outputs:
- github.com # Default GitHub domains are always included
- api.github.com # Additional trusted domains can be specified
- trusted-domain.com # URIs from unlisted domains are replaced with "(redacted)"
github-token: ${{ secrets.CUSTOM_PAT }} # Optional: custom GitHub token for safe output jobs
```

## Global Configuration Options

### Custom GitHub Token (`github-token:`)

By default, safe output jobs use the standard `GITHUB_TOKEN` provided by GitHub Actions. You can specify a custom GitHub token for all safe output jobs:

```yaml
safe-outputs:
create-issue:
add-issue-comment:
github-token: ${{ secrets.CUSTOM_PAT }} # Use custom PAT instead of GITHUB_TOKEN
```

This is useful when:
- You need additional permissions beyond what `GITHUB_TOKEN` provides
- You want to perform actions across multiple repositories
- You need to bypass GitHub Actions token restrictions

**Note:** The custom `github-token` is applied to all safe output jobs (create-issue, add-issue-comment, create-pull-request, etc.). Individual safe output types cannot have different tokens.

## Related Documentation

- [Frontmatter Options](frontmatter.md) - All configuration options for workflows
Expand Down
12 changes: 11 additions & 1 deletion pkg/cli/templates/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,17 @@ The YAML frontmatter supports these fields:
body: true # Optional: allow updating issue body
max: 3 # Optional: maximum number of issues to update (default: 1)
```
When using `safe-outputs.update-issue`, the main job does **not** need `issues: write` permission since issue updates are handled by a separate job with appropriate permissions.
When using `safe-outputs.update-issue`, the main job does **not** need `issues: write` permission since issue updates are handled by a separate job with appropriate permissions.

**Global Safe Output Configuration:**
- `github-token:` - Custom GitHub token for all safe output jobs
```yaml
safe-outputs:
create-issue:
add-issue-comment:
github-token: ${{ secrets.CUSTOM_PAT }} # Use custom PAT instead of GITHUB_TOKEN
```
Useful when you need additional permissions or want to perform actions across repositories.

- **`alias:`** - Alternative workflow name (string)
- **`cache:`** - Cache configuration for workflow dependencies (object or array)
Expand Down
15 changes: 15 additions & 0 deletions pkg/parser/schemas/main_workflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,21 @@
"staged": {
"type": "boolean",
"description": "If true, emit step summary messages instead of making GitHub API calls (preview mode)"
},
"env": {
"type": "object",
"description": "Environment variables to pass to safe output jobs",
"patternProperties": {
"^[A-Za-z_][A-Za-z0-9_]*$": {
"type": "string",
"description": "Environment variable value, typically a secret reference like ${{ secrets.TOKEN_NAME }}"
}
},
"additionalProperties": false
},
"github-token": {
"type": "string",
"description": "GitHub token to use for safe output jobs. Typically a secret reference like ${{ secrets.GITHUB_TOKEN }} or ${{ secrets.CUSTOM_PAT }}"
}
},
"additionalProperties": false
Expand Down
69 changes: 68 additions & 1 deletion pkg/workflow/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ type SafeOutputsConfig struct {
PushToPullRequestBranch *PushToPullRequestBranchConfig `yaml:"push-to-pr-branch,omitempty"`
MissingTool *MissingToolConfig `yaml:"missing-tool,omitempty"` // Optional for reporting missing functionality
AllowedDomains []string `yaml:"allowed-domains,omitempty"`
Staged *bool `yaml:"staged,omitempty"` // If true, emit step summary messages instead of making GitHub API calls
Staged *bool `yaml:"staged,omitempty"` // If true, emit step summary messages instead of making GitHub API calls
Env map[string]string `yaml:"env,omitempty"` // Environment variables to pass to safe output jobs
GitHubToken string `yaml:"github-token,omitempty"` // GitHub token for safe output jobs
}

// CreateIssuesConfig holds configuration for creating GitHub issues from agent output
Expand Down Expand Up @@ -2204,7 +2206,12 @@ func (c *Compiler) buildCreateOutputIssueJob(data *WorkflowData, mainJobName str
steps = append(steps, " GITHUB_AW_SAFE_OUTPUTS_STAGED: \"true\"\n")
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -2281,7 +2288,12 @@ func (c *Compiler) buildCreateOutputDiscussionJob(data *WorkflowData, mainJobNam
steps = append(steps, " GITHUB_AW_SAFE_OUTPUTS_STAGED: \"true\"\n")
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -2338,7 +2350,12 @@ func (c *Compiler) buildCreateOutputAddIssueCommentJob(data *WorkflowData, mainJ
steps = append(steps, fmt.Sprintf(" GITHUB_AW_COMMENT_TARGET: %q\n", data.SafeOutputs.AddIssueComments.Target))
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -2415,7 +2432,12 @@ func (c *Compiler) buildCreateOutputPullRequestReviewCommentJob(data *WorkflowDa
steps = append(steps, fmt.Sprintf(" GITHUB_AW_PR_REVIEW_COMMENT_SIDE: %q\n", data.SafeOutputs.CreatePullRequestReviewComments.Side))
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -2491,7 +2513,12 @@ func (c *Compiler) buildCreateOutputCodeScanningAlertJob(data *WorkflowData, mai
// Pass the workflow filename for rule ID prefix
steps = append(steps, fmt.Sprintf(" GITHUB_AW_WORKFLOW_FILENAME: %s\n", workflowFilename))

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -2611,7 +2638,12 @@ func (c *Compiler) buildCreateOutputPullRequestJob(data *WorkflowData, mainJobNa
steps = append(steps, " GITHUB_AW_SAFE_OUTPUTS_STAGED: \"true\"\n")
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down Expand Up @@ -3719,12 +3751,47 @@ func (c *Compiler) extractSafeOutputsConfig(frontmatter map[string]any) *SafeOut
config.Staged = &stagedBool
}
}

// Handle env configuration
if env, exists := outputMap["env"]; exists {
if envMap, ok := env.(map[string]any); ok {
config.Env = make(map[string]string)
for key, value := range envMap {
if valueStr, ok := value.(string); ok {
config.Env[key] = valueStr
}
}
}
}

// Handle github-token configuration
if githubToken, exists := outputMap["github-token"]; exists {
if githubTokenStr, ok := githubToken.(string); ok {
config.GitHubToken = githubTokenStr
}
}
}
}

return config
}

// addCustomSafeOutputEnvVars adds custom environment variables to safe output job steps
func (c *Compiler) addCustomSafeOutputEnvVars(steps *[]string, data *WorkflowData) {
if data.SafeOutputs != nil && len(data.SafeOutputs.Env) > 0 {
for key, value := range data.SafeOutputs.Env {
*steps = append(*steps, fmt.Sprintf(" %s: %s\n", key, value))
}
}
}

// addSafeOutputGitHubToken adds github-token to the with section of github-script actions
func (c *Compiler) addSafeOutputGitHubToken(steps *[]string, data *WorkflowData) {
if data.SafeOutputs != nil && data.SafeOutputs.GitHubToken != "" {
*steps = append(*steps, fmt.Sprintf(" github-token: %s\n", data.SafeOutputs.GitHubToken))
}
}

// extractCacheMemoryConfig extracts cache-memory configuration from tools section
func (c *Compiler) extractCacheMemoryConfig(tools map[string]any) *CacheMemoryConfig {
cacheMemoryValue, exists := tools["cache-memory"]
Expand Down
5 changes: 5 additions & 0 deletions pkg/workflow/output_labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ func (c *Compiler) buildCreateOutputLabelJob(data *WorkflowData, mainJobName str
steps = append(steps, " GITHUB_AW_SAFE_OUTPUTS_STAGED: \"true\"\n")
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down
5 changes: 5 additions & 0 deletions pkg/workflow/output_missing_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ func (c *Compiler) buildCreateOutputMissingToolJob(data *WorkflowData, mainJobNa
steps = append(steps, fmt.Sprintf(" GITHUB_AW_MISSING_TOOL_MAX: %d\n", data.SafeOutputs.MissingTool.Max))
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down
5 changes: 5 additions & 0 deletions pkg/workflow/output_push_to_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ func (c *Compiler) buildCreateOutputPushToPullRequestBranchJob(data *WorkflowDat
// Pass the if-no-changes configuration
steps = append(steps, fmt.Sprintf(" GITHUB_AW_PUSH_IF_NO_CHANGES: %q\n", data.SafeOutputs.PushToPullRequestBranch.IfNoChanges))

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down
5 changes: 5 additions & 0 deletions pkg/workflow/output_update_issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ func (c *Compiler) buildCreateOutputUpdateIssueJob(data *WorkflowData, mainJobNa
steps = append(steps, fmt.Sprintf(" GITHUB_AW_UPDATE_TARGET: %q\n", data.SafeOutputs.UpdateIssues.Target))
}

// Add custom environment variables from safe-outputs.env
c.addCustomSafeOutputEnvVars(&steps, data)

steps = append(steps, " with:\n")
// Add github-token if specified
c.addSafeOutputGitHubToken(&steps, data)
steps = append(steps, " script: |\n")

// Add each line of the script with proper indentation
Expand Down
Loading