From 9bd56d46bdf3a0549770e673e1eb6a1d16e2dc60 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 08:48:54 +0000 Subject: [PATCH 1/4] Initial plan From ac361fa709335c7319b9b2ae37c024eaea55c6e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 09:01:21 +0000 Subject: [PATCH 2/4] Refactor permissions parsing from compiler.go to permissions.go Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/compiler.go | 70 ++------------------------------ pkg/workflow/permissions.go | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/pkg/workflow/compiler.go b/pkg/workflow/compiler.go index 0918949c26e..a382825e304 100644 --- a/pkg/workflow/compiler.go +++ b/pkg/workflow/compiler.go @@ -1070,78 +1070,16 @@ func (c *Compiler) extractPermissions(frontmatter map[string]any) string { return "" } - // If it's a shorthand permission, use the standard extraction - if _, ok := permissionsValue.(string); ok { - return c.extractTopLevelYAMLSection(frontmatter, "permissions") - } - - // If it's a map, check if it has 'all' and expand it - if mapValue, ok := permissionsValue.(map[string]any); ok { - if allValue, hasAll := mapValue["all"]; hasAll { - if allLevel, ok := allValue.(string); ok && allLevel == "read" { - // Create a new Permissions object and expand all: read - permissions := NewPermissionsAllRead() - - // Add any explicit overrides - for key, value := range mapValue { - if key != "all" { - if strValue, ok := value.(string); ok { - if scope := c.convertKeyToPermissionScope(key); scope != "" { - permissions.Set(scope, PermissionLevel(strValue)) - } - } - } - } - - // Render to YAML and remove the "permissions:" prefix - yamlStr := permissions.RenderToYAML() - return yamlStr - } - } + // Try to use the permissions.go ExtractPermissionsYAML function first + yamlStr := ExtractPermissionsYAML(permissionsValue) + if yamlStr != "" { + return yamlStr } // Fallback to standard extraction for other cases return c.extractTopLevelYAMLSection(frontmatter, "permissions") } -// convertKeyToPermissionScope converts a string key to a PermissionScope -func (c *Compiler) convertKeyToPermissionScope(key string) PermissionScope { - switch key { - case "actions": - return PermissionActions - case "attestations": - return PermissionAttestations - case "checks": - return PermissionChecks - case "contents": - return PermissionContents - case "deployments": - return PermissionDeployments - case "discussions": - return PermissionDiscussions - case "id-token": - return PermissionIdToken - case "issues": - return PermissionIssues - case "models": - return PermissionModels - case "packages": - return PermissionPackages - case "pages": - return PermissionPages - case "pull-requests": - return PermissionPullRequests - case "repository-projects": - return PermissionRepositoryProj - case "security-events": - return PermissionSecurityEvents - case "statuses": - return PermissionStatuses - default: - return "" - } -} - // extractIfCondition extracts the if condition from frontmatter, returning just the expression // without the "if: " prefix func (c *Compiler) extractIfCondition(frontmatter map[string]any) string { diff --git a/pkg/workflow/permissions.go b/pkg/workflow/permissions.go index dc17aad73d6..33d670026db 100644 --- a/pkg/workflow/permissions.go +++ b/pkg/workflow/permissions.go @@ -771,3 +771,82 @@ func NewPermissionsContentsWritePRReadIssuesRead() *Permissions { PermissionIssues: PermissionRead, }) } + +// ConvertKeyToPermissionScope converts a string key to a PermissionScope +func ConvertKeyToPermissionScope(key string) PermissionScope { + switch key { + case "actions": + return PermissionActions + case "attestations": + return PermissionAttestations + case "checks": + return PermissionChecks + case "contents": + return PermissionContents + case "deployments": + return PermissionDeployments + case "discussions": + return PermissionDiscussions + case "id-token": + return PermissionIdToken + case "issues": + return PermissionIssues + case "models": + return PermissionModels + case "packages": + return PermissionPackages + case "pages": + return PermissionPages + case "pull-requests": + return PermissionPullRequests + case "repository-projects": + return PermissionRepositoryProj + case "security-events": + return PermissionSecurityEvents + case "statuses": + return PermissionStatuses + default: + return "" + } +} + +// ExtractPermissionsYAML extracts permissions from frontmatter and handles all: read expansion +// Returns YAML string representation of the permissions +func ExtractPermissionsYAML(permissionsValue any) string { + if permissionsValue == nil { + return "" + } + + // If it's a shorthand permission string, convert to YAML format + if strValue, ok := permissionsValue.(string); ok { + return "permissions: " + strValue + } + + // If it's a map, check if it has 'all' and expand it + if mapValue, ok := permissionsValue.(map[string]any); ok { + if allValue, hasAll := mapValue["all"]; hasAll { + if allLevel, ok := allValue.(string); ok && allLevel == "read" { + // Create a new Permissions object and expand all: read + permissions := NewPermissionsAllRead() + + // Add any explicit overrides + for key, value := range mapValue { + if key != "all" { + if strValue, ok := value.(string); ok { + if scope := ConvertKeyToPermissionScope(key); scope != "" { + permissions.Set(scope, PermissionLevel(strValue)) + } + } + } + } + + // Render to YAML + yamlStr := permissions.RenderToYAML() + return yamlStr + } + } + } + + // For other cases, return empty (caller should use standard extraction) + return "" +} From a0c5ff9a699540b8d89cae3f83ede743917af27f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 09:15:45 +0000 Subject: [PATCH 3/4] Simplify and remove duplicate logic in permissions.go Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/permissions.go | 90 ++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/pkg/workflow/permissions.go b/pkg/workflow/permissions.go index 33d670026db..e71c2f5cc4b 100644 --- a/pkg/workflow/permissions.go +++ b/pkg/workflow/permissions.go @@ -106,33 +106,7 @@ func (p *PermissionsParser) parse() { // Try to parse as YAML map var perms map[string]any if err := yaml.Unmarshal([]byte(yamlContent), &perms); err == nil { - // Handle 'all' key specially - if allValue, exists := perms["all"]; exists { - if strValue, ok := allValue.(string); ok { - if strValue == "write" { - // all: write is not allowed - don't set any permissions - return - } - if strValue == "read" { - // Check that no other permissions are set to 'none' when all: read is used - for key, value := range perms { - if key != "all" { - if permValue, ok := value.(string); ok && permValue == "none" { - // all: read cannot be combined with : none - don't set any permissions - return - } - } - } - p.hasAll = true - p.allLevel = strValue - } - } - } // Convert any values to strings - for key, value := range perms { - if strValue, ok := value.(string); ok { - p.parsedPerms[key] = strValue - } - } + p.parsePermissionsMap(perms) } } @@ -237,39 +211,45 @@ func NewPermissionsParserFromValue(permissionsValue any) *PermissionsParser { return parser } - // Handle map format + // Handle map format - use shared validation logic if mapValue, ok := permissionsValue.(map[string]any); ok { - // Handle 'all' key specially - if allValue, exists := mapValue["all"]; exists { - if strValue, ok := allValue.(string); ok { - if strValue == "write" { - // all: write is not allowed, return empty parser - return parser - } - if strValue == "read" { - // Check that no other permissions are set to 'none' when all: read is used - for key, value := range mapValue { - if key != "all" { - if permValue, ok := value.(string); ok && permValue == "none" { - // all: read cannot be combined with : none, return empty parser - return parser - } + parser.parsePermissionsMap(mapValue) + } + + return parser +} + +// parsePermissionsMap parses a permissions map and validates all: read usage +func (p *PermissionsParser) parsePermissionsMap(perms map[string]any) { + // Handle 'all' key specially + if allValue, exists := perms["all"]; exists { + if strValue, ok := allValue.(string); ok { + if strValue == "write" { + // all: write is not allowed - don't set any permissions + return + } + if strValue == "read" { + // Check that no other permissions are set to 'none' when all: read is used + for key, value := range perms { + if key != "all" { + if permValue, ok := value.(string); ok && permValue == "none" { + // all: read cannot be combined with : none - don't set any permissions + return } } - parser.hasAll = true - parser.allLevel = strValue } + p.hasAll = true + p.allLevel = strValue } } + } - for key, value := range mapValue { - if strValue, ok := value.(string); ok { - parser.parsedPerms[key] = strValue - } + // Convert any values to strings + for key, value := range perms { + if strValue, ok := value.(string); ok { + p.parsedPerms[key] = strValue } } - - return parser } // ContainsCheckout returns true if the given custom steps contain an actions/checkout step @@ -826,6 +806,14 @@ func ExtractPermissionsYAML(permissionsValue any) string { if mapValue, ok := permissionsValue.(map[string]any); ok { if allValue, hasAll := mapValue["all"]; hasAll { if allLevel, ok := allValue.(string); ok && allLevel == "read" { + // Use the parser to validate the map + parser := NewPermissionsParserFromValue(permissionsValue) + + // If validation failed (hasAll is not set), return empty + if !parser.hasAll { + return "" + } + // Create a new Permissions object and expand all: read permissions := NewPermissionsAllRead() From 5cce6a824e045e9fd5460763af0b10d87b576a9f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 09:30:46 +0000 Subject: [PATCH 4/4] Enhance ExtractPermissionsYAML to handle all permission cases Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/artifacts-summary.lock.yml | 8 ++++---- .github/workflows/audit-workflows.lock.yml | 8 ++++---- .github/workflows/brave.lock.yml | 8 ++++---- .github/workflows/changeset-generator.lock.yml | 8 ++++---- .github/workflows/cli-version-checker.lock.yml | 8 ++++---- .../workflows/commit-changes-analyzer.lock.yml | 8 ++++---- .github/workflows/daily-doc-updater.lock.yml | 12 ++++++------ .github/workflows/dev-hawk.lock.yml | 12 ++++++------ .github/workflows/dev.lock.yml | 8 ++++---- .../workflows/duplicate-code-detector.lock.yml | 8 ++++---- .../workflows/example-workflow-analyzer.lock.yml | 8 ++++---- .../workflows/github-mcp-tools-report.lock.yml | 8 ++++---- .github/workflows/go-logger.lock.yml | 8 ++++---- .github/workflows/go-pattern-detector.lock.yml | 8 ++++---- .github/workflows/issue-classifier.lock.yml | 12 ++++++------ .github/workflows/lockfile-stats.lock.yml | 8 ++++---- .github/workflows/mcp-inspector.lock.yml | 8 ++++---- .github/workflows/pdf-summary.lock.yml | 8 ++++---- .github/workflows/plan.lock.yml | 8 ++++---- .github/workflows/poem-bot.lock.yml | 8 ++++---- .github/workflows/q.lock.yml | 8 ++++---- .github/workflows/repo-tree-map.lock.yml | 8 ++++---- .github/workflows/research.lock.yml | 8 ++++---- .github/workflows/scout.lock.yml | 8 ++++---- .github/workflows/security-fix-pr.lock.yml | 12 ++++++------ .github/workflows/test-jqschema.lock.yml | 4 ++-- .github/workflows/test-post-steps.lock.yml | 8 ++++---- .github/workflows/test-svelte.lock.yml | 4 ++-- .github/workflows/tidy.lock.yml | 8 ++++---- .github/workflows/unbloat-docs.lock.yml | 12 ++++++------ .github/workflows/video-analyzer.lock.yml | 8 ++++---- .github/workflows/weekly-issue-summary.lock.yml | 12 ++++++------ pkg/workflow/compiler.go | 4 ++-- pkg/workflow/permissions.go | 16 ++++++++++++++++ 34 files changed, 154 insertions(+), 138 deletions(-) diff --git a/.github/workflows/artifacts-summary.lock.yml b/.github/workflows/artifacts-summary.lock.yml index a7434d28786..d94d22e4a52 100644 --- a/.github/workflows/artifacts-summary.lock.yml +++ b/.github/workflows/artifacts-summary.lock.yml @@ -26,8 +26,8 @@ name: "Artifacts Summary" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -58,8 +58,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index c607d8afcfc..8c1521ab130 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -31,8 +31,8 @@ name: "Agentic Workflow Audit Agent" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -63,8 +63,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index 6f48c3a6619..a8051a16fa8 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -38,8 +38,8 @@ name: "Brave Web Search Agent" - edited permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -942,8 +942,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" diff --git a/.github/workflows/changeset-generator.lock.yml b/.github/workflows/changeset-generator.lock.yml index 5b8e3c3ce3b..2a55f230b13 100644 --- a/.github/workflows/changeset-generator.lock.yml +++ b/.github/workflows/changeset-generator.lock.yml @@ -33,8 +33,8 @@ name: "Changeset Generator" - ready_for_review permissions: - contents: read - pull-requests: read + contents: read + pull-requests: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" @@ -570,8 +570,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - contents: read - pull-requests: read + contents: read + pull-requests: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml index 47b188a8743..c9719ee23d8 100644 --- a/.github/workflows/cli-version-checker.lock.yml +++ b/.github/workflows/cli-version-checker.lock.yml @@ -30,8 +30,8 @@ name: "CLI Version Checker" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -62,8 +62,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/commit-changes-analyzer.lock.yml b/.github/workflows/commit-changes-analyzer.lock.yml index 0bb4c58d4fd..d3284ca90d0 100644 --- a/.github/workflows/commit-changes-analyzer.lock.yml +++ b/.github/workflows/commit-changes-analyzer.lock.yml @@ -29,8 +29,8 @@ name: "Commit Changes Analyzer" type: string permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -61,8 +61,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml index 46df1a0718f..aa9e02da36d 100644 --- a/.github/workflows/daily-doc-updater.lock.yml +++ b/.github/workflows/daily-doc-updater.lock.yml @@ -26,9 +26,9 @@ name: "Daily Documentation Updater" workflow_dispatch: null permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -59,9 +59,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml index 25d16d52fd8..3702e785e5f 100644 --- a/.github/workflows/dev-hawk.lock.yml +++ b/.github/workflows/dev-hawk.lock.yml @@ -35,9 +35,9 @@ name: "Dev Hawk" - Dev permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -434,9 +434,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 380cc648262..cf1213e022a 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -16,8 +16,8 @@ name: "Dev" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: cancel-in-progress: true @@ -49,8 +49,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" steps: diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml index f8df43b49b9..0fca6d3fe6f 100644 --- a/.github/workflows/duplicate-code-detector.lock.yml +++ b/.github/workflows/duplicate-code-detector.lock.yml @@ -30,8 +30,8 @@ name: "Duplicate Code Detector" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -62,8 +62,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-codex-${{ github.workflow }}" env: diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml index 7e715b32c55..9c05d32d8bc 100644 --- a/.github/workflows/example-workflow-analyzer.lock.yml +++ b/.github/workflows/example-workflow-analyzer.lock.yml @@ -26,8 +26,8 @@ name: "Weekly Workflow Analysis" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -58,8 +58,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index 5d860e2fb51..48cc56c182b 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -29,8 +29,8 @@ name: "GitHub MCP Remote Server Tools Report Generator" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -61,8 +61,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index 540efc9b1d5..efc523f9a27 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -26,8 +26,8 @@ name: "Go Logger Enhancement" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -58,8 +58,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml index 3ef17a18b67..b40b40ccf40 100644 --- a/.github/workflows/go-pattern-detector.lock.yml +++ b/.github/workflows/go-pattern-detector.lock.yml @@ -35,8 +35,8 @@ name: "Go Pattern Detector" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.ref }}" @@ -69,8 +69,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":1},\"missing_tool\":{}}" diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index ebc60600ad9..6122cee590c 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -32,9 +32,9 @@ name: "Issue Classifier" - opened permissions: - actions: read - contents: read - models: read + actions: read + contents: read + models: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number }}" @@ -810,9 +810,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - models: read + actions: read + contents: read + models: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\"],\"max\":1},\"missing_tool\":{}}" diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml index c28989fac2e..18acd17a237 100644 --- a/.github/workflows/lockfile-stats.lock.yml +++ b/.github/workflows/lockfile-stats.lock.yml @@ -26,8 +26,8 @@ name: "Lockfile Statistics Analysis Agent" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -58,8 +58,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index 93746ad14ce..831259d602f 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -51,8 +51,8 @@ name: "MCP Inspector Agent" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -83,8 +83,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 3188e8992dd..c4ba207b635 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -54,8 +54,8 @@ name: "Resource Summarizer Agent" type: string permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -960,8 +960,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index 170901320a7..a516626d5ed 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -29,8 +29,8 @@ name: "Plan Command" - edited permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -567,8 +567,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_issue\":{\"max\":5},\"missing_tool\":{}}" diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index e3142d8960b..a2a101b6678 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -71,8 +71,8 @@ name: "Poem Bot - A Creative Agentic Workflow" required: false permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -1224,8 +1224,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_ASSETS_ALLOWED_EXTS: ".png,.jpg,.jpeg" GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index cb440b0db97..c4f81b7e7dc 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -67,8 +67,8 @@ name: "Q" - edited permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -980,8 +980,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{},\"missing_tool\":{}}" diff --git a/.github/workflows/repo-tree-map.lock.yml b/.github/workflows/repo-tree-map.lock.yml index 78d2cc36518..489b005f6ed 100644 --- a/.github/workflows/repo-tree-map.lock.yml +++ b/.github/workflows/repo-tree-map.lock.yml @@ -24,8 +24,8 @@ name: "Repository Tree Map Generator" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -56,8 +56,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/research.lock.yml b/.github/workflows/research.lock.yml index 5e0f3e0396f..8394e985ad6 100644 --- a/.github/workflows/research.lock.yml +++ b/.github/workflows/research.lock.yml @@ -33,8 +33,8 @@ name: "Basic Research Agent" type: string permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -65,8 +65,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 494d36a9537..e8d60d9bf21 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -71,8 +71,8 @@ name: "Scout" required: true permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -985,8 +985,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_tool\":{}}" diff --git a/.github/workflows/security-fix-pr.lock.yml b/.github/workflows/security-fix-pr.lock.yml index dc4cecfc7cc..23f5cf687e8 100644 --- a/.github/workflows/security-fix-pr.lock.yml +++ b/.github/workflows/security-fix-pr.lock.yml @@ -24,9 +24,9 @@ name: "Security Fix PR" workflow_dispatch: null permissions: - actions: read - contents: read - security-events: read + actions: read + contents: read + security-events: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -57,9 +57,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - security-events: read + actions: read + contents: read + security-events: read concurrency: group: "gh-aw-claude-${{ github.workflow }}" env: diff --git a/.github/workflows/test-jqschema.lock.yml b/.github/workflows/test-jqschema.lock.yml index 8e2202ee586..aade9687d08 100644 --- a/.github/workflows/test-jqschema.lock.yml +++ b/.github/workflows/test-jqschema.lock.yml @@ -20,7 +20,7 @@ name: "Test jqschema" workflow_dispatch: null permissions: - contents: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -51,7 +51,7 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - contents: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" steps: diff --git a/.github/workflows/test-post-steps.lock.yml b/.github/workflows/test-post-steps.lock.yml index caacc74abaf..a98c2ae520e 100644 --- a/.github/workflows/test-post-steps.lock.yml +++ b/.github/workflows/test-post-steps.lock.yml @@ -16,8 +16,8 @@ name: "Test Post-Steps Workflow" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -48,8 +48,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" steps: diff --git a/.github/workflows/test-svelte.lock.yml b/.github/workflows/test-svelte.lock.yml index dc5d8790a5b..71c2add65e9 100644 --- a/.github/workflows/test-svelte.lock.yml +++ b/.github/workflows/test-svelte.lock.yml @@ -20,7 +20,7 @@ name: "Test Svelte MCP" workflow_dispatch: null permissions: - contents: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -51,7 +51,7 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - contents: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" steps: diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 36367aa797c..f33d9a73597 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -41,8 +41,8 @@ name: "Tidy" workflow_dispatch: null permissions: - actions: read - contents: read + actions: read + contents: read concurrency: cancel-in-progress: true @@ -417,8 +417,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read env: GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safe-outputs/outputs.jsonl GH_AW_SAFE_OUTPUTS_CONFIG: "{\"create_pull_request\":{},\"missing_tool\":{},\"push_to_pull_request_branch\":{}}" diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index 121a237fcdf..42d53243420 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -46,9 +46,9 @@ name: "Documentation Unbloat" workflow_dispatch: null permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read concurrency: group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}" @@ -792,9 +792,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - pull-requests: read + actions: read + contents: read + pull-requests: read env: GH_AW_ASSETS_ALLOWED_EXTS: ".png,.jpg,.jpeg" GH_AW_ASSETS_BRANCH: "assets/${{ github.workflow }}" diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml index dfae9d7fa45..c9bb57e9efd 100644 --- a/.github/workflows/video-analyzer.lock.yml +++ b/.github/workflows/video-analyzer.lock.yml @@ -33,8 +33,8 @@ name: "Video Analysis Agent" type: string permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -65,8 +65,8 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read + actions: read + contents: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index 2076356d0cf..ac3a6a57c1e 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -26,9 +26,9 @@ name: "Weekly Issue Summary" workflow_dispatch: null permissions: - actions: read - contents: read - issues: read + actions: read + contents: read + issues: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -59,9 +59,9 @@ jobs: needs: activation runs-on: ubuntu-latest permissions: - actions: read - contents: read - issues: read + actions: read + contents: read + issues: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: diff --git a/pkg/workflow/compiler.go b/pkg/workflow/compiler.go index a382825e304..f7f8a4ed3ef 100644 --- a/pkg/workflow/compiler.go +++ b/pkg/workflow/compiler.go @@ -1070,13 +1070,13 @@ func (c *Compiler) extractPermissions(frontmatter map[string]any) string { return "" } - // Try to use the permissions.go ExtractPermissionsYAML function first + // Use the permissions.go ExtractPermissionsYAML function which handles all cases yamlStr := ExtractPermissionsYAML(permissionsValue) if yamlStr != "" { return yamlStr } - // Fallback to standard extraction for other cases + // Fallback to standard extraction for edge cases return c.extractTopLevelYAMLSection(frontmatter, "permissions") } diff --git a/pkg/workflow/permissions.go b/pkg/workflow/permissions.go index e71c2f5cc4b..99cab8f1169 100644 --- a/pkg/workflow/permissions.go +++ b/pkg/workflow/permissions.go @@ -833,6 +833,22 @@ func ExtractPermissionsYAML(permissionsValue any) string { return yamlStr } } + + // Regular permissions map (no 'all' key or non-read 'all' value) + // Convert to Permissions object and render + permissions := NewPermissions() + for key, value := range mapValue { + if strValue, ok := value.(string); ok { + if scope := ConvertKeyToPermissionScope(key); scope != "" { + permissions.Set(scope, PermissionLevel(strValue)) + } + } + } + + // Only render if we have permissions + if len(permissions.permissions) > 0 { + return permissions.RenderToYAML() + } } // For other cases, return empty (caller should use standard extraction)