Skip to content

[test-improver] Improve tests for internal/server guard_policy_parsing - #12919

Merged
lpcox merged 2 commits into
mainfrom
test-improver/guard-policy-parsing-d8f20fa8b5e70b76
Sep 11, 2026
Merged

lpcox merged 2 commits into
mainfrom
test-improver/guard-policy-parsing-d8f20fa8b5e70b76

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

File analyzed

internal/server/guard_policy_parsing_test.go

Improvements made

  • Converted TestParseServerGuardPolicy_AllowOnly from a single ad-hoc test into a table-driven test covering:
    • modern allow-only format with slice repos (the original smoke-allowonly.lock.yml shape)
    • modern allow-only format with string repos
    • legacy top-level repos/min-integrity format
    • write-sink format
  • Replaced the only manual assertion (t.Fatalf("repos is not a []interface{}, got %T: %v", ...)) with require.True/assert.Equal, aligning with the project's testify conventions.
  • Added TestParseServerGuardPolicy_Errors (new) covering two previously-untested error paths in config.ParseServerGuardPolicy: an invalid repos scope value, and a server-ID-nested value that isn't an object.
  • Kept TestResolveGuardPolicy_ServerGuardPolicies as-is since it's a focused smoke test; the exhaustive resolveGuardPolicy branch coverage already lives in resolve_guard_policy_test.go.

Coverage

  • internal/server package coverage: 94.4% → 94.4% (this file's target functions were already well covered by sibling test files; the change focuses on structure, clarity, and adding two previously-missing error-path assertions for config.ParseServerGuardPolicy).
  • internal/config ParseServerGuardPolicy: 96.0% (unchanged; verified via go tool cover).

Test output

go test -v ./internal/server/... -run "TestParseServerGuardPolicy_AllowOnly|TestParseServerGuardPolicy_Errors|TestResolveGuardPolicy_ServerGuardPolicies"
--- PASS: TestParseServerGuardPolicy_AllowOnly (0.00s)
    --- PASS: TestParseServerGuardPolicy_AllowOnly/modern_allow-only_format_with_slice_repos (0.00s)
    --- PASS: TestParseServerGuardPolicy_AllowOnly/modern_allow-only_format_with_string_repos (0.00s)
    --- PASS: TestParseServerGuardPolicy_AllowOnly/legacy_repos/min-integrity_format_at_top_level (0.00s)
    --- PASS: TestParseServerGuardPolicy_AllowOnly/write-sink_format (0.00s)
--- PASS: TestParseServerGuardPolicy_Errors (0.00s)
    --- PASS: TestParseServerGuardPolicy_Errors/invalid_repos_scope_value (0.00s)
    --- PASS: TestParseServerGuardPolicy_Errors/server-id-nested_value_is_not_an_object (0.00s)
--- PASS: TestResolveGuardPolicy_ServerGuardPolicies (0.00s)
PASS

Also verified with go test -count=3 ./internal/server/... (pass), go vet ./internal/server/... (clean), and gofmt -l (clean). Full go test ./... across all packages and test/integration pass; only the unrelated Rust guard test step failed due to a sandboxed network/crates.io registry restriction in this environment.

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • api.github.com
  • example.com
  • index.crates.io
  • nonexistent.local
  • slow.example.com
  • thishostdoesnotexist12345.com

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.github.com"
    - "example.com"
    - "index.crates.io"
    - "nonexistent.local"
    - "slow.example.com"
    - "thishostdoesnotexist12345.com"

See Network Configuration for more information.

Generated by Test Improver · copilot · auto · 252.9 AIC · ⊞ 8.3K · ◷

- Convert TestParseServerGuardPolicy_AllowOnly into a table-driven test
  covering modern allow-only (slice and string repos), legacy
  repos/min-integrity, and write-sink formats.
- Replace the raw t.Fatalf type-assertion failure with a testify
  require.True/assert.Equal check for consistency with project
  conventions.
- Add TestParseServerGuardPolicy_Errors covering the invalid-scope and
  server-id-nested-non-object error paths returned by
  config.ParseServerGuardPolicy.
- Keep TestResolveGuardPolicy_ServerGuardPolicies as the smoke test for
  server-level policy resolution (already covered in depth by
  resolve_guard_policy_test.go).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lpcox
lpcox marked this pull request as ready for review September 11, 2026 00:03
Copilot AI balanced review requested due to automatic review settings September 11, 2026 00:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Tighten the invalid-repos assertion and rename the broader-scope test.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This test-only PR expands and restructures guard-policy parsing coverage.

Changes:

  • Adds table-driven cases for modern, legacy, and write-sink formats.
  • Adds malformed-policy error coverage.
  • Uses testify assertions consistently.

Review notes: rename the allow-only test to reflect its broader scope and assert the specific invalid-repos error message.

File summaries
File Description
internal/server/guard_policy_parsing_test.go Expanded and reorganized guard-policy parsing tests.
Review details

Suppressed comments (1)

internal/server/guard_policy_parsing_test.go:108

  • This expectation is too broad for the case named invalid repos scope value: any error containing repos would pass, including an unrelated missing-field or parsing error. Pin the validation message already produced for this input (allow-only.repos string must be 'all' or 'public') so the test verifies the intended error path.
			wantErr: "repos",
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/server/guard_policy_parsing_test.go Outdated
@github-actions

Copy link
Copy Markdown
Contributor Author

🔒 mcpg Read-Only Stress — gvisor

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: gvisor

Part Surface Op Result Expected Status
A MCP reads data ALLOWED ✅
B MCP writes (reaction/star/issue/comment/branch/file/PR) absent from catalog BLOCKED ⚠️
C CLI reads data ALLOWED ✅
D CLI REST writes (reaction/star/issue/comment) not tested (gh unauthenticated) BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) not tested (gh unauthenticated) BLOCKED ⚠️

Overall: INCONCLUSIVE

  • Part A/C: all 4 reads (list_issues, list_pull_requests, get_file_contents, list_commits) returned data via the proxied github CLI (status=200).
  • Part B: none of the targeted write tools (add_issue_comment, star_repository, issue_write, create_branch, create_or_update_file, create_pull_request) are present in the exposed tool catalog (only 23 read-only tools registered). This confirms gh-aw's backend GITHUB_READ_ONLY=1 defense-in-depth, but per the test's own validation criteria, an absent tool only proves backend/toolset configuration, not mcpg's own gateway-level DIFC/guard enforcement — so this row is INCONCLUSIVE, not PASS.
  • Part D/E: gh auth status reports "not logged into any GitHub hosts" — gh is unauthenticated in this environment, so the REST/GraphQL write-blocking boundary could not be exercised.

No writes leaked. No cleanup needed.

🔒 mcpg read-only stress (gVisor runtime) by Read-Only Stress: gVisor runtime

@github-actions

This comment has been minimized.

…licy

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor Author

🔒 mcpg Read-Only Stress — default

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: default AWF (normal container isolation)

Part Surface Op Result Expected Status
A MCP reads (list_issues, list_pull_requests, get_file_contents, list_commits) data returned ALLOWED ✅
B MCP writes (add_issue_comment/star_repository/issue_write/create_branch/create_or_update_file/create_pull_request) all 7 write tools absent from the 23-tool catalog exposed under tools.github: (read-only toolset) BLOCKED ⚠️
C CLI reads (list_issues, get_file_contents via github CLI proxy) data returned ALLOWED ✅
D CLI REST writes (reaction/star/issue/comment via gh api) gh unauthenticated (no GH_TOKEN); all writes refused client-side before reaching GitHub BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) gh unauthenticated; refused client-side BLOCKED ⚠️

Overall: INCONCLUSIVE

No write leaked through mcpg in this run. Part B is ⚠️ because all targeted write
tools were absent from the exposed catalog (gh-aw's tools.github: always sets
GITHUB_READ_ONLY=1), so this only proves backend/toolset config, not the
gateway's own independent DIFC/guard enforcement layer. Parts D/E are ⚠️ because
gh had no GH_TOKEN in this environment, so writes were refused client-side
rather than exercising the GitHub API token-scope boundary. Independent evidence
of mcpg's own write-blocking layer lives in internal/guard/internal/difc
unit tests, not this probe.

🔒 mcpg read-only stress (default AWF runtime) by Read-Only Stress: default runtime

@lpcox
lpcox merged commit 3848a2e into main Sep 11, 2026
36 of 38 checks passed
@lpcox
lpcox deleted the test-improver/guard-policy-parsing-d8f20fa8b5e70b76 branch September 11, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants