From 93aa82e852a39f9324669cffb084d67caa153ef1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 03:06:32 +0000 Subject: [PATCH 1/3] Initial plan From b99cf49e4c876fa1b7e307dd962dcec8ef7dd0ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 03:19:05 +0000 Subject: [PATCH 2/3] fix: default github.repos to 'all' when not specified in guard policy Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/tools_validation.go | 8 ++++---- pkg/workflow/tools_validation_test.go | 5 ++--- scratchpad/dev.md | 2 +- scratchpad/guard-policies-specification.md | 6 ++---- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pkg/workflow/tools_validation.go b/pkg/workflow/tools_validation.go index 343c18cc5a4..cfe37d86cd1 100644 --- a/pkg/workflow/tools_validation.go +++ b/pkg/workflow/tools_validation.go @@ -62,7 +62,7 @@ func validateGitHubToolConfig(tools *Tools, workflowName string) error { // validateGitHubGuardPolicy validates the GitHub guard policy configuration. // Guard policy fields (repos, min-integrity) are specified flat under github:. -// Both fields must be present if either is specified. +// If repos is not specified but min-integrity is, repos defaults to "all". func validateGitHubGuardPolicy(tools *Tools, workflowName string) error { if tools == nil || tools.GitHub == nil { return nil @@ -77,10 +77,10 @@ func validateGitHubGuardPolicy(tools *Tools, workflowName string) error { return nil } - // Validate repos field (required when min-integrity is set) + // Default repos to "all" when not specified if !hasRepos { - toolsValidationLog.Printf("Missing repos in guard policy for workflow: %s", workflowName) - return errors.New("invalid guard policy: 'github.repos' is required. Use 'all', 'public', or an array of repository patterns (e.g., ['owner/repo', 'owner/*'])") + toolsValidationLog.Printf("Defaulting repos to 'all' in guard policy for workflow: %s", workflowName) + github.Repos = "all" } // Validate repos format diff --git a/pkg/workflow/tools_validation_test.go b/pkg/workflow/tools_validation_test.go index 0cae4b958ec..4456f65b837 100644 --- a/pkg/workflow/tools_validation_test.go +++ b/pkg/workflow/tools_validation_test.go @@ -301,14 +301,13 @@ func TestValidateGitHubGuardPolicy(t *testing.T) { shouldError: false, }, { - name: "missing repos field", + name: "missing repos field defaults to all", toolsMap: map[string]any{ "github": map[string]any{ "min-integrity": "unapproved", }, }, - shouldError: true, - errorMsg: "'github.repos' is required", + shouldError: false, }, { name: "missing min-integrity field", diff --git a/scratchpad/dev.md b/scratchpad/dev.md index 3f5ae37195d..05199ee36de 100644 --- a/scratchpad/dev.md +++ b/scratchpad/dev.md @@ -1771,7 +1771,7 @@ tools: min-integrity: unapproved # none | unapproved | approved | merged ``` -Both `repos` and `min-integrity` are required when either is specified under `github:`. +`min-integrity` is required when using GitHub guard policies. `repos` defaults to `"all"` if not specified. **Repository Pattern Options**: - `"all"` — All repositories accessible by the token diff --git a/scratchpad/guard-policies-specification.md b/scratchpad/guard-policies-specification.md index 37c5a9d5db4..ceb3062ee3b 100644 --- a/scratchpad/guard-policies-specification.md +++ b/scratchpad/guard-policies-specification.md @@ -238,16 +238,14 @@ The design supports future MCP servers (Jira, WorkIQ) through: - Case-sensitive **Required Fields:** -- Both `repos` and `min-integrity` are required when either is specified under `github:` +- `min-integrity` is required when using GitHub guard policies +- `repos` defaults to `"all"` if not specified ## Error Messages The implementation provides clear, actionable error messages: ``` -invalid guard policy: 'github.repos' is required. -Use 'all', 'public', or an array of repository patterns (e.g., ['owner/repo', 'owner/*']) - invalid guard policy: repository pattern 'Owner/Repo' must be lowercase invalid guard policy: repository pattern 'owner/re*po' has wildcard in the middle. From b37ea93233f7d89793065ad833298ffa88cdfe53 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 19 Mar 2026 03:33:23 +0000 Subject: [PATCH 3/3] test: add workflow integration tests for guard policy min-integrity-only Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/compile_guard_policy_test.go | 148 ++++++++++++++++++ .../test-guard-policy-min-integrity-only.md | 22 +++ 2 files changed, 170 insertions(+) create mode 100644 pkg/cli/compile_guard_policy_test.go create mode 100644 pkg/cli/workflows/test-guard-policy-min-integrity-only.md diff --git a/pkg/cli/compile_guard_policy_test.go b/pkg/cli/compile_guard_policy_test.go new file mode 100644 index 00000000000..ea22dd1bf39 --- /dev/null +++ b/pkg/cli/compile_guard_policy_test.go @@ -0,0 +1,148 @@ +//go:build !integration + +package cli + +import ( + "os" + "path/filepath" + "testing" + + "github.com/github/gh-aw/pkg/workflow" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestGuardPolicyMinIntegrityOnly verifies that specifying only min-integrity +// under tools.github compiles successfully without requiring an explicit repos field. +// When repos is omitted, it should default to "all" (regression test for the fix). +func TestGuardPolicyMinIntegrityOnly(t *testing.T) { + tests := []struct { + name string + workflowContent string + expectError bool + errorContains string + }{ + { + name: "min-integrity only defaults repos to all", + workflowContent: `--- +on: + workflow_dispatch: +permissions: + contents: read +engine: copilot +tools: + github: + min-integrity: none +--- + +# Guard Policy Test + +This workflow uses min-integrity without specifying repos. +`, + expectError: false, + }, + { + name: "min-integrity with explicit repos=all compiles", + workflowContent: `--- +on: + workflow_dispatch: +permissions: + contents: read +engine: copilot +tools: + github: + repos: all + min-integrity: unapproved +--- + +# Guard Policy Test + +This workflow uses both repos and min-integrity. +`, + expectError: false, + }, + { + name: "min-integrity with repos=public compiles", + workflowContent: `--- +on: + workflow_dispatch: +permissions: + contents: read +engine: copilot +tools: + github: + repos: public + min-integrity: approved +--- + +# Guard Policy Test + +This workflow restricts to public repos. +`, + expectError: false, + }, + { + name: "min-integrity with repos array compiles", + workflowContent: `--- +on: + workflow_dispatch: +permissions: + contents: read +engine: copilot +tools: + github: + repos: + - owner/repo + min-integrity: merged +--- + +# Guard Policy Test + +This workflow specifies a repos array. +`, + expectError: false, + }, + { + name: "repos only without min-integrity fails validation", + workflowContent: `--- +on: + workflow_dispatch: +permissions: + contents: read +engine: copilot +tools: + github: + repos: all +--- + +# Guard Policy Test + +This workflow specifies repos without min-integrity. +`, + expectError: true, + errorContains: "min-integrity", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tmpDir := t.TempDir() + + workflowPath := filepath.Join(tmpDir, "test-guard-policy.md") + err := os.WriteFile(workflowPath, []byte(tt.workflowContent), 0644) + require.NoError(t, err, "Failed to write workflow file") + + compiler := workflow.NewCompiler() + err = CompileWorkflowWithValidation(compiler, workflowPath, false, false, false, false, false, false) + + if tt.expectError { + require.Error(t, err, "Expected compilation to fail") + if tt.errorContains != "" { + assert.Contains(t, err.Error(), tt.errorContains, "Error should mention %q", tt.errorContains) + } + } else { + assert.NoError(t, err, "Expected compilation to succeed") + } + }) + } +} diff --git a/pkg/cli/workflows/test-guard-policy-min-integrity-only.md b/pkg/cli/workflows/test-guard-policy-min-integrity-only.md new file mode 100644 index 00000000000..d1788d50a84 --- /dev/null +++ b/pkg/cli/workflows/test-guard-policy-min-integrity-only.md @@ -0,0 +1,22 @@ +--- +on: + workflow_dispatch: +permissions: + contents: read + issues: read + pull-requests: read +engine: copilot +tools: + github: + min-integrity: none +--- + +# Test Guard Policy with min-integrity Only + +This workflow verifies that specifying only `min-integrity` under `tools.github` +works correctly without requiring an explicit `repos` field. + +When `repos` is omitted, it should default to `all`, allowing the workflow to compile +successfully. + +Please list the first 3 open issues in this repository.