diff --git a/pkg/workflow/compiler.go b/pkg/workflow/compiler.go index 2b8ae88f28..653b22a8b1 100644 --- a/pkg/workflow/compiler.go +++ b/pkg/workflow/compiler.go @@ -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 @@ -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() } } } @@ -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) { diff --git a/pkg/workflow/permissions_warning_test.go b/pkg/workflow/permissions_warning_test.go index cf36918ce6..934b167aff 100644 --- a/pkg/workflow/permissions_warning_test.go +++ b/pkg/workflow/permissions_warning_test.go @@ -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: `---