Skip to content
34 changes: 29 additions & 5 deletions pkg/workflow/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (
// MaxPromptChunks is the maximum number of chunks allowed when splitting prompt text
// This prevents excessive step generation for extremely large prompt texts
MaxPromptChunks = 5 // Maximum number of chunks

// missingPermissionsDefaultToolsetWarning explains why strict mode was downgraded to warning.
missingPermissionsDefaultToolsetWarning = "Some of the GitHub tools will not be available until the missing permissions are granted."
)

//go:embed schemas/github-workflow.json
Expand Down Expand Up @@ -330,14 +333,20 @@ func (c *Compiler) validateWorkflowData(workflowData *WorkflowData, markdownPath
message := FormatValidationMessage(validationResult, c.strictMode)

if len(validationResult.MissingPermissions) > 0 {
if c.strictMode {
downgradeToWarning := c.strictMode && shouldDowngradeDefaultToolsetPermissionError(workflowData.ParsedTools.GitHub)
if c.strictMode && !downgradeToWarning {
// In strict mode, missing permissions are errors
return formatCompilerError(markdownPath, "error", message, nil)
} else {
// In non-strict mode, missing permissions are warnings
fmt.Fprintln(os.Stderr, formatCompilerMessage(markdownPath, "warning", message))
c.IncrementWarningCount()
}

if downgradeToWarning {
message += "\n\n" + missingPermissionsDefaultToolsetWarning
}

// In non-strict mode, missing permissions are warnings.
// In strict mode with default-only toolsets, this is intentionally downgraded to warning.
fmt.Fprintln(os.Stderr, formatCompilerMessage(markdownPath, "warning", message))
c.IncrementWarningCount()
}
}
}
Expand Down Expand Up @@ -424,6 +433,21 @@ Ensure proper audience validation and trust policies are configured.`
return nil
}

// shouldDowngradeDefaultToolsetPermissionError returns true when strict-mode
// permission errors should be downgraded because the GitHub tool uses only the
// default toolset, either explicitly ([default]) or implicitly (no toolsets configured).
func shouldDowngradeDefaultToolsetPermissionError(githubTool *GitHubToolConfig) bool {
if githubTool == nil {
return false
}

if len(githubTool.Toolset) == 0 {
return true
}

return len(githubTool.Toolset) == 1 && githubTool.Toolset[0] == GitHubToolset("default")
}

// generateAndValidateYAML generates GitHub Actions YAML and validates
// the output size and format.
func (c *Compiler) generateAndValidateYAML(workflowData *WorkflowData, markdownPath string, lockFile string) (string, []string, []string, error) {
Expand Down
40 changes: 40 additions & 0 deletions pkg/workflow/permissions_warning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,46 @@ tools:
expectWarning: false,
warningMessage: "",
},
{
name: "default toolset only in strict mode produces warning",
content: `---
on: push
strict: true
permissions:
contents: read
issues: read
tools:
github:
toolsets: [default]
---

# Test Workflow
`,
strict: true,
expectError: false,
expectWarning: true,
warningMessage: "Some of the GitHub tools will not be available until the missing permissions are granted.",
},
{
name: "implied default toolset in strict mode produces warning",
content: `---
on: push
strict: true
permissions:
contents: read
issues: read
tools:
github:
min-integrity: none
---

# Test Workflow
`,
strict: true,
expectError: false,
expectWarning: true,
warningMessage: "Some of the GitHub tools will not be available until the missing permissions are granted.",
},
{
name: "sufficient permissions in non-strict mode produces no warning",
content: `---
Expand Down
Loading