diff --git a/.github/workflows/aw-portfolio-yield.lock.yml b/.github/workflows/aw-portfolio-yield.lock.yml index 85a3f4374f9..778d086b2c7 100644 --- a/.github/workflows/aw-portfolio-yield.lock.yml +++ b/.github/workflows/aw-portfolio-yield.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c4ace1ac375dd7f3297e6dfb63f9d6f14743feb20b424ca1f058a784846442dd","compiler_version":"v0.74.8","strict":true,"agent_id":"copilot"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","GRAFANA_SERVICE_ACCOUNT_TOKEN","GRAFANA_URL","SENTRY_ACCESS_TOKEN","SENTRY_OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"v0.74.8","version":"v0.74.8"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.49"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4"},{"image":"grafana/mcp-grafana","digest":"sha256:60a4e3a417a69eeb864a72052c53b4aa4466ff3577d6ef9bacc671f4b77d7090","pinned_image":"grafana/mcp-grafana@sha256:60a4e3a417a69eeb864a72052c53b4aa4466ff3577d6ef9bacc671f4b77d7090"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c4ace1ac375dd7f3297e6dfb63f9d6f14743feb20b424ca1f058a784846442dd","strict":true,"agent_id":"copilot"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN","GRAFANA_SERVICE_ACCOUNT_TOKEN","GRAFANA_URL","SENTRY_ACCESS_TOKEN","SENTRY_OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.25.49"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.49"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4"},{"image":"grafana/mcp-grafana","digest":"sha256:60a4e3a417a69eeb864a72052c53b4aa4466ff3577d6ef9bacc671f4b77d7090","pinned_image":"grafana/mcp-grafana@sha256:60a4e3a417a69eeb864a72052c53b4aa4466ff3577d6ef9bacc671f4b77d7090"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -14,7 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # -# This file was automatically generated by gh-aw (v0.74.8). DO NOT EDIT. +# This file was automatically generated by gh-aw. DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -52,7 +52,6 @@ # - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 (source v9) # - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 -# - github/gh-aw-actions/setup@v0.74.8 # # Container images used: # - ghcr.io/github/gh-aw-firewall/agent:0.25.49 @@ -67,7 +66,7 @@ name: "Agentic Workflow Portfolio Yield" on: schedule: - - cron: "7 9 * * 1" + - cron: "40 8 * * 1" # Friendly format: weekly on monday around 09:00 (scattered) workflow_dispatch: inputs: @@ -109,9 +108,16 @@ jobs: setup-trace-id: ${{ steps.setup.outputs.trace-id }} stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.74.8 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -130,7 +136,6 @@ jobs: GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.5' }} GH_AW_INFO_VERSION: "1.0.48" GH_AW_INFO_AGENT_VERSION: "1.0.48" - GH_AW_INFO_CLI_VERSION: "v0.74.8" GH_AW_INFO_WORKFLOW_NAME: "Agentic Workflow Portfolio Yield" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" @@ -161,6 +166,7 @@ jobs: sparse-checkout: | .github .agents + actions/setup .claude .codex .crush @@ -187,16 +193,6 @@ jobs: setupGlobals(core, github, context, exec, io, getOctokit); const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); await main(); - - name: Check compile-agentic version - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - GH_AW_COMPILED_VERSION: "v0.74.8" - with: - script: | - const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); - setupGlobals(core, github, context, exec, io, getOctokit); - const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); - await main(); - name: Create prompt with built-in context env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -372,9 +368,16 @@ jobs: setup-span-id: ${{ steps.setup.outputs.span-id }} setup-trace-id: ${{ steps.setup.outputs.trace-id }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.74.8 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -862,7 +865,7 @@ jobs: GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} - GH_AW_VERSION: v0.74.8 + GH_AW_VERSION: dev GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true @@ -1090,9 +1093,16 @@ jobs: tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} total_count: ${{ steps.missing_tool.outputs.total_count }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.74.8 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1229,9 +1239,16 @@ jobs: detection_reason: ${{ steps.detection_conclusion.outputs.reason }} detection_success: ${{ steps.detection_conclusion.outputs.success }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.74.8 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1362,7 +1379,7 @@ jobs: COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || 'claude-sonnet-4.5' }} GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt - GH_AW_VERSION: v0.74.8 + GH_AW_VERSION: dev GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1448,9 +1465,16 @@ jobs: process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} steps: + - name: Checkout actions folder + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: github/gh-aw + sparse-checkout: | + actions + persist-credentials: false - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@v0.74.8 + uses: ./actions/setup with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1512,3 +1536,4 @@ jobs: /tmp/gh-aw/safe-output-items.jsonl /tmp/gh-aw/temporary-id-map.json if-no-files-found: ignore + diff --git a/docs/src/content/docs/reference/network.md b/docs/src/content/docs/reference/network.md index c5b395b2030..a9c4a549542 100644 --- a/docs/src/content/docs/reference/network.md +++ b/docs/src/content/docs/reference/network.md @@ -166,12 +166,12 @@ network: - "api.example.com" # Custom domain (not part of known ecosystem) ```` -### Warning Messages +### Informational Messages -When strict mode encounters an individual ecosystem domain, it emits a warning suggesting the appropriate ecosystem identifier: +When strict mode encounters an individual ecosystem domain, it emits an informational message suggesting the appropriate ecosystem identifier: ````text -warning: strict mode: recommend using ecosystem identifiers instead of individual domain names for better maintainability: 'pypi.org' → 'python', 'npmjs.org' → 'node' +recommend using ecosystem identifiers instead of individual domain names for better maintainability: 'pypi.org' → 'python', 'npmjs.org' → 'node' ```` ## Implementation diff --git a/pkg/workflow/strict_mode_llm_gateway_test.go b/pkg/workflow/strict_mode_llm_gateway_test.go index 2ff31a97b33..68a9737413c 100644 --- a/pkg/workflow/strict_mode_llm_gateway_test.go +++ b/pkg/workflow/strict_mode_llm_gateway_test.go @@ -5,6 +5,8 @@ package workflow import ( "strings" "testing" + + "github.com/github/gh-aw/pkg/testutil" ) // TestValidateStrictFirewall_LLMGatewaySupport tests the LLM gateway validation in strict mode @@ -77,7 +79,7 @@ func TestValidateStrictFirewall_LLMGatewaySupport(t *testing.T) { } }) - t.Run("copilot engine allows domains from known ecosystems with warning suggesting ecosystem identifier in strict mode", func(t *testing.T) { + t.Run("copilot engine allows domains from known ecosystems with informational ecosystem guidance in strict mode", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -89,14 +91,12 @@ func TestValidateStrictFirewall_LLMGatewaySupport(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("copilot", networkPerms, nil) if err != nil { t.Errorf("Expected no error for individual ecosystem domains in strict mode, got: %v", err) } - // Should have incremented warning count - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) @@ -117,7 +117,7 @@ func TestValidateStrictFirewall_LLMGatewaySupport(t *testing.T) { } }) - t.Run("codex engine allows domains from known ecosystems with warning suggesting ecosystem identifier", func(t *testing.T) { + t.Run("codex engine allows domains from known ecosystems with informational ecosystem guidance", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -129,14 +129,12 @@ func TestValidateStrictFirewall_LLMGatewaySupport(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("codex", networkPerms, nil) if err != nil { t.Errorf("Expected no error for individual ecosystem domains in strict mode, got: %v", err) } - // Should have incremented warning count - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) @@ -260,9 +258,9 @@ func TestValidateStrictFirewall_LLMGatewaySupport(t *testing.T) { }) } -// TestValidateStrictFirewall_EcosystemSuggestions tests ecosystem suggestions in warning messages +// TestValidateStrictFirewall_EcosystemSuggestions tests ecosystem suggestions in informational messages func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { - t.Run("warns with ecosystem suggestion when individual domain from ecosystem is used", func(t *testing.T) { + t.Run("prints informational ecosystem suggestion when individual domain from ecosystem is used", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -273,18 +271,51 @@ func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() - err := compiler.validateStrictFirewall("copilot", networkPerms, nil) - if err != nil { - t.Errorf("Expected no error for individual ecosystem domain in strict mode, got: %v", err) + output := testutil.CaptureStderr(t, func() { + err := compiler.validateStrictFirewall("copilot", networkPerms, nil) + if err != nil { + t.Errorf("Expected no error for individual ecosystem domain in strict mode, got: %v", err) + } + }) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) + } + if !strings.Contains(output, "recommend using ecosystem identifiers") || + !strings.Contains(output, "'pypi.org'") || + !strings.Contains(output, "'python'") { + t.Errorf("Expected informational ecosystem guidance in stderr, got: %q", output) + } + }) + + t.Run("prints informational ecosystem suggestion without strict mode warning prefix", func(t *testing.T) { + compiler := NewCompiler() + compiler.strictMode = true + + networkPerms := &NetworkPermissions{ + Allowed: []string{"files.pythonhosted.org", "pypi.org"}, + Firewall: &FirewallConfig{ + Enabled: true, + }, + } + + output := testutil.CaptureStderr(t, func() { + err := compiler.validateStrictFirewall("copilot", networkPerms, nil) + if err != nil { + t.Errorf("Expected no error for individual ecosystem domains in strict mode, got: %v", err) + } + }) + if !strings.Contains(output, "recommend using ecosystem identifiers") { + t.Errorf("Expected informational ecosystem guidance in stderr, got: %q", output) + } + if strings.Contains(output, "strict mode:") { + t.Errorf("Expected informational ecosystem guidance to omit strict mode warning prefix, got: %q", output) } - // Should have emitted a warning - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if !strings.Contains(output, "'files.pythonhosted.org' → 'python', 'pypi.org' → 'python'") { + t.Errorf("Expected informational ecosystem guidance to include both python suggestions, got: %q", output) } }) - t.Run("warns with ecosystem suggestion for multiple domains from same ecosystem", func(t *testing.T) { + t.Run("prints informational ecosystem suggestion for multiple domains from same ecosystem", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -295,18 +326,16 @@ func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("copilot", networkPerms, nil) if err != nil { t.Errorf("Expected no error for individual ecosystem domains in strict mode, got: %v", err) } - // Should have emitted a warning - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) - t.Run("warns with ecosystem suggestion for domains from different ecosystems", func(t *testing.T) { + t.Run("prints informational ecosystem suggestion for domains from different ecosystems", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -317,14 +346,12 @@ func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("copilot", networkPerms, nil) if err != nil { t.Errorf("Expected no error for individual ecosystem domains in strict mode, got: %v", err) } - // Should have emitted a warning - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) @@ -350,7 +377,7 @@ func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { } }) - t.Run("mixed custom and ecosystem domains shows warnings only for ecosystem domains", func(t *testing.T) { + t.Run("mixed custom and ecosystem domains print informational guidance without warning count", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -361,14 +388,12 @@ func TestValidateStrictFirewall_EcosystemSuggestions(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("copilot", networkPerms, nil) if err != nil { t.Errorf("Expected no error for mixed domains in strict mode, got: %v", err) } - // Should have emitted a warning for pypi.org only - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) @@ -448,7 +473,7 @@ func TestValidateStrictFirewall_CustomDomainBehavior(t *testing.T) { } }) - t.Run("ecosystem domain with custom domains emits warning for ecosystem domain only", func(t *testing.T) { + t.Run("ecosystem domain with custom domains prints informational guidance without warning count", func(t *testing.T) { compiler := NewCompiler() compiler.strictMode = true @@ -459,14 +484,12 @@ func TestValidateStrictFirewall_CustomDomainBehavior(t *testing.T) { }, } - initialWarnings := compiler.GetWarningCount() err := compiler.validateStrictFirewall("copilot", networkPerms, nil) if err != nil { t.Errorf("Expected no error for ecosystem domain with custom domain, got: %v", err) } - // Should have emitted a warning for pypi.org - if compiler.GetWarningCount() != initialWarnings+1 { - t.Errorf("Expected warning count to increase by 1, got %d warnings", compiler.GetWarningCount()-initialWarnings) + if compiler.GetWarningCount() != 0 { + t.Errorf("Expected no warnings for informational ecosystem guidance, got %d", compiler.GetWarningCount()) } }) diff --git a/pkg/workflow/strict_mode_permissions_validation.go b/pkg/workflow/strict_mode_permissions_validation.go index efc298a8fbf..ee7f3720e4e 100644 --- a/pkg/workflow/strict_mode_permissions_validation.go +++ b/pkg/workflow/strict_mode_permissions_validation.go @@ -167,19 +167,17 @@ func (c *Compiler) validateStrictFirewall(engineID string, networkPermissions *N } if len(ecosystemDomainsNotAsIdentifiers) > 0 { - strictModeValidationLog.Printf("Engine '%s' has ecosystem domains not specified as identifiers in strict mode, emitting warning", engineID) + strictModeValidationLog.Printf("Engine '%s' has ecosystem domains not specified as identifiers in strict mode, emitting informational guidance", engineID) - // Build warning message with ecosystem suggestions + // Build informational message with ecosystem suggestions var suggestions []string for _, ds := range ecosystemDomainsNotAsIdentifiers { suggestions = append(suggestions, fmt.Sprintf("'%s' → '%s'", ds.domain, ds.ecosystem)) } - warningMsg := "strict mode: recommend using ecosystem identifiers instead of individual domain names for better maintainability: " + strings.Join(suggestions, ", ") + infoMsg := "recommend using ecosystem identifiers instead of individual domain names for better maintainability: " + strings.Join(suggestions, ", ") - // Print warning message and increment warning count - fmt.Fprintln(os.Stderr, console.FormatWarningMessage(warningMsg)) - c.IncrementWarningCount() + fmt.Fprintln(os.Stderr, console.FormatInfoMessage(infoMsg)) } }