Skip to content

Refactor: Consolidate micro-files and extract Docker helpers#1641

Merged
lpcox merged 2 commits intomainfrom
claude/refactor-semantic-function-clustering
Mar 6, 2026
Merged

Refactor: Consolidate micro-files and extract Docker helpers#1641
lpcox merged 2 commits intomainfrom
claude/refactor-semantic-function-clustering

Conversation

@Claude
Copy link
Contributor

@Claude Claude AI commented Mar 6, 2026

Analysis of 71 Go files identified micro-files fragmenting trivially small code, Docker helpers misplaced in validation logic, and a test file without a matching implementation file.

Changes

Merged operational defaults

  • config_logging.go → config_payload.go: Consolidated DefaultLogDir with DefaultPayloadDir and DefaultPayloadSizeThreshold
  • Single location for all gateway operational defaults

Consolidated tightly-coupled code

  • logger/constants.go → logger/logger.go: Moved EnvDebug and EnvDebugColors to where they're referenced
  • server/errors.go → server/auth.go: Moved logRuntimeError to its only call site (2 uses in auth middleware)

Separated concerns

  • Created docker_helpers.go: Extracted 5 Docker inspection functions from validation_env.go
    • runDockerInspect, checkDockerAccessible, checkPortMapping, checkStdinInteractive, checkLogDirMounted
    • Isolates Docker I/O from validation result logic

Established implementation file

  • Created guard_policy.go: Implementation file for guard policy configuration
    • Matches existing config_guardpolicies_test.go pattern
    • Provides GuardPolicyConfig type with helper methods (GetPolicy, HasPolicy, IsEmpty)
    • Canonical location for future guard-policy logic

Impact

  • Removed 3 micro-files (config_logging.go, logger/constants.go, server/errors.go)
  • Improved discoverability: operational defaults, logger constants, and auth helpers now co-located with usage
  • Cleaner separation: Docker I/O isolated from validation logic

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /tmp/go-build3487354539/b297/launcher.test /tmp/go-build3487354539/b297/launcher.test -test.testlogfile=/tmp/go-build3487354539/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 9526385/b231/_pkg_.a .cfg .12/x64/bin/as -p b/gh-aw-mcpg/int-d -lang=go1.25 ache/go/1.25.7/x64/pkg/tool/linuHEAD (dns block)
    • Triggering command: /tmp/go-build2202525201/b297/launcher.test /tmp/go-build2202525201/b297/launcher.test -test.testlogfile=/tmp/go-build2202525201/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true cal/bin/git x_amd64/vet 7354539/b325/timeutil.test uRC0HPMQT 9526385/b019/vet--version tnet/tools/as 7354539/b325/timeutil.test e=/t�� t0 m0s ker/cli-plugins/docker-compose -s -w -buildmode=exe ker/cli-plugins/docker-compose (dns block)
    • Triggering command: /tmp/go-build2711332198/b297/launcher.test /tmp/go-build2711332198/b297/launcher.test -test.testlogfile=/tmp/go-build2711332198/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true --abbrev-ref ude-agent-sdk/vendor/ripgrep/x64github.com/github/gh-aw-mcpg/internal/mcp /usr/bin/base64 se 9526385/b220/vet-d k/_temp/ghcca-node/node/bin/git base64 -d --64 as docker-buildx -I /tmp/go-build114/usr/bin/runc x_amd64/vet docker-buildx (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build3487354539/b279/config.test /tmp/go-build3487354539/b279/config.test -test.testlogfile=/tmp/go-build3487354539/b279/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 9526385/b229/_pkg_.a .cfg de/node/bin/as -p Sushi/toml/inter-d -lang=go1.25 /x86_64-linux-gnu/13/cc1 -I 64/src/net -I 64/pkg/tool/linux_amd64/vet --gdwarf-5 --64 -o 64/pkg/tool/linux_amd64/vet (dns block)
    • Triggering command: /tmp/go-build2202525201/b279/config.test /tmp/go-build2202525201/b279/config.test -test.testlogfile=/tmp/go-build2202525201/b279/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 10 x_amd64/vet ache/go/1.25.7/x64/pkg/tool/linux_amd64/vet 9526385/b038/_pkbase64 .cfg ache/go/1.25.7/x-lang=go1.25 ache/go/1.25.7/x64/pkg/tool/linux_amd64/vet rev-�� --abbrev-ref HEAD docker-buildx 64/src/runtime/cbase64 HEAD 64/pkg/tool/linu-importcfg docker-buildx (dns block)
    • Triggering command: /tmp/go-build2711332198/b279/config.test /tmp/go-build2711332198/b279/config.test -test.testlogfile=/tmp/go-build2711332198/b279/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true -o as ache/go/1.25.7/x64/bin/git ache/go/1.25.7/xgit 64/src/crypto/tlrev-parse ache/go/1.25.7/x--abbrev-ref git rev-�� --abbrev-ref HEAD /usr/bin/base64 se 9526385/b160/vet-d tnet/tools/git base64 (dns block)
  • nonexistent.local
    • Triggering command: /tmp/go-build3487354539/b297/launcher.test /tmp/go-build3487354539/b297/launcher.test -test.testlogfile=/tmp/go-build3487354539/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 9526385/b231/_pkg_.a .cfg .12/x64/bin/as -p b/gh-aw-mcpg/int-d -lang=go1.25 ache/go/1.25.7/x64/pkg/tool/linuHEAD (dns block)
    • Triggering command: /tmp/go-build2202525201/b297/launcher.test /tmp/go-build2202525201/b297/launcher.test -test.testlogfile=/tmp/go-build2202525201/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true cal/bin/git x_amd64/vet 7354539/b325/timeutil.test uRC0HPMQT 9526385/b019/vet--version tnet/tools/as 7354539/b325/timeutil.test e=/t�� t0 m0s ker/cli-plugins/docker-compose -s -w -buildmode=exe ker/cli-plugins/docker-compose (dns block)
    • Triggering command: /tmp/go-build2711332198/b297/launcher.test /tmp/go-build2711332198/b297/launcher.test -test.testlogfile=/tmp/go-build2711332198/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true --abbrev-ref ude-agent-sdk/vendor/ripgrep/x64github.com/github/gh-aw-mcpg/internal/mcp /usr/bin/base64 se 9526385/b220/vet-d k/_temp/ghcca-node/node/bin/git base64 -d --64 as docker-buildx -I /tmp/go-build114/usr/bin/runc x_amd64/vet docker-buildx (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build3487354539/b297/launcher.test /tmp/go-build3487354539/b297/launcher.test -test.testlogfile=/tmp/go-build3487354539/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 9526385/b231/_pkg_.a .cfg .12/x64/bin/as -p b/gh-aw-mcpg/int-d -lang=go1.25 ache/go/1.25.7/x64/pkg/tool/linuHEAD (dns block)
    • Triggering command: /tmp/go-build2202525201/b297/launcher.test /tmp/go-build2202525201/b297/launcher.test -test.testlogfile=/tmp/go-build2202525201/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true cal/bin/git x_amd64/vet 7354539/b325/timeutil.test uRC0HPMQT 9526385/b019/vet--version tnet/tools/as 7354539/b325/timeutil.test e=/t�� t0 m0s ker/cli-plugins/docker-compose -s -w -buildmode=exe ker/cli-plugins/docker-compose (dns block)
    • Triggering command: /tmp/go-build2711332198/b297/launcher.test /tmp/go-build2711332198/b297/launcher.test -test.testlogfile=/tmp/go-build2711332198/b297/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true --abbrev-ref ude-agent-sdk/vendor/ripgrep/x64github.com/github/gh-aw-mcpg/internal/mcp /usr/bin/base64 se 9526385/b220/vet-d k/_temp/ghcca-node/node/bin/git base64 -d --64 as docker-buildx -I /tmp/go-build114/usr/bin/runc x_amd64/vet docker-buildx (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build3487354539/b306/mcp.test /tmp/go-build3487354539/b306/mcp.test -test.testlogfile=/tmp/go-build3487354539/b306/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net ache/go/1.25.7/x64/src/net/http/internal/testcert/testcert.go cal/bin/as -I /tmp/go-build114rev-parse -I 02.o -o 64/src/net httptest/httptest.go 64/pkg/tool/linux_amd64/compile -p github.com/githu-d -lang=go1.25 64/pkg/tool/linux_amd64/compile (dns block)
    • Triggering command: /tmp/go-build2202525201/b306/mcp.test /tmp/go-build2202525201/b306/mcp.test -test.testlogfile=/tmp/go-build2202525201/b306/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true bin/git x_amd64/vet /opt/hostedtoolcache/go/1.25.7/x64/pkg/tool/linux_amd64/link se 9526385/b030/vet/usr/bin/runc 64/pkg/tool/linu--version /opt/hostedtoolcache/go/1.25.7/xHEAD -o /tmp/go-build3487354539/b224/cmd.test -importcfg ker/cli-plugins/docker-compose -s -w -buildmode=exe ker/cli-plugins/docker-compose (dns block)
    • Triggering command: /tmp/go-build731852698/b310/mcp.test /tmp/go-build731852698/b310/mcp.test -test.testlogfile=/tmp/go-build731852698/b310/testlog.txt -test.paniconexit0 -test.timeout=10m0s dock�� ache/uv/0.10.9/x-stringintconv git ker/docker-init --abbrev-ref HEAD ver.test ker/docker-init exit�� --abbrev-ref HEAD ash -lang=go1.25 git ker/docker-init git (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

- Merge config_logging.go into config_payload.go (both operational defaults)
- Move EnvDebug/EnvDebugColors constants from logger/constants.go into logger/logger.go
- Move logRuntimeError from server/errors.go into server/auth.go (only used there)
- Extract Docker helpers from validation_env.go into docker_helpers.go
- Create guard_policy.go implementation file matching config_guardpolicies_test.go

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
@Claude Claude AI changed the title [WIP] Refactor semantic function clustering analysis in Go files Refactor: Consolidate micro-files and extract Docker helpers Mar 6, 2026
@lpcox lpcox marked this pull request as ready for review March 6, 2026 23:11
Copilot AI review requested due to automatic review settings March 6, 2026 23:11
@lpcox lpcox merged commit 4b13882 into main Mar 6, 2026
11 checks passed
@lpcox lpcox deleted the claude/refactor-semantic-function-clustering branch March 6, 2026 23:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR consolidates three "micro-files" (each containing trivially small amounts of code) into their related files, extracts Docker helper functions from validation_env.go into a dedicated docker_helpers.go, and introduces a new guard_policy.go file with a type-safe wrapper for guard policy configuration.

Changes:

  • Merged config_logging.go, logger/constants.go, and server/errors.go into their respective related files (config_payload.go, logger.go, auth.go), eliminating 3 micro-files.
  • Extracted Docker inspection/validation functions from validation_env.go into docker_helpers.go to separate Docker I/O concerns from validation logic.
  • Created guard_policy.go with a new GuardPolicyConfig type and helper methods for type-safe guard policy access.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/config/config_logging.go Deleted; DefaultLogDir constant moved to config_payload.go
internal/config/config_payload.go Added DefaultLogDir constant alongside existing payload defaults
internal/logger/constants.go Deleted; EnvDebug/EnvDebugColors constants moved to logger.go
internal/logger/logger.go Added EnvDebug/EnvDebugColors constants where they are referenced
internal/server/errors.go Deleted; logRuntimeError moved to auth.go
internal/server/auth.go Added logRuntimeError function (its only call site)
internal/config/validation_env.go Removed Docker helper functions and containerIDPattern regex
internal/config/docker_helpers.go New file with extracted Docker inspection functions
internal/config/guard_policy.go New file with GuardPolicyConfig type and helper methods

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2 to +51
// This file defines guard policy configuration and helpers.
package config

// GuardPolicyConfig provides a type-safe interface for accessing guard policies
// from ServerConfig. Guard policies control access to MCP server resources.
//
// Structure (GitHub MCP Server):
// - repos: "all", "public", or array of patterns (e.g., ["owner/repo", "owner/*"])
// - min-integrity: "none", "reader", "writer", or "merged"
//
// The guard policies are stored as map[string]interface{} to support
// server-specific schemas without forcing all servers to use the same structure.
type GuardPolicyConfig struct {
policies map[string]interface{}
}

// NewGuardPolicyConfig creates a GuardPolicyConfig wrapper around the raw policies map.
func NewGuardPolicyConfig(policies map[string]interface{}) *GuardPolicyConfig {
if policies == nil {
return &GuardPolicyConfig{policies: make(map[string]interface{})}
}
return &GuardPolicyConfig{policies: policies}
}

// GetPolicy returns the policy configuration for a specific service (e.g., "github", "slack").
// Returns nil if the service has no policy configured.
func (gp *GuardPolicyConfig) GetPolicy(service string) map[string]interface{} {
if gp.policies == nil {
return nil
}
if policy, ok := gp.policies[service].(map[string]interface{}); ok {
return policy
}
return nil
}

// HasPolicy returns true if a policy is configured for the given service.
func (gp *GuardPolicyConfig) HasPolicy(service string) bool {
return gp.GetPolicy(service) != nil
}

// IsEmpty returns true if no policies are configured.
func (gp *GuardPolicyConfig) IsEmpty() bool {
return len(gp.policies) == 0
}

// GetGuardPolicies is a helper method on ServerConfig for type-safe access to guard policies.
func (sc *ServerConfig) GetGuardPolicies() *GuardPolicyConfig {
return NewGuardPolicyConfig(sc.GuardPolicies)
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The GuardPolicyConfig type and all its methods (NewGuardPolicyConfig, GetPolicy, HasPolicy, IsEmpty, GetGuardPolicies) are currently unused anywhere in the codebase — they are dead code with no callers and no tests. The existing config_guardpolicies_test.go tests the raw GuardPolicies map on ServerConfig directly, not through these new helpers.

If these are intended for future use, consider either adding tests now (to match the pattern of the existing config_guardpolicies_test.go) or deferring this code until there are actual consumers. Introducing untested, unused code increases maintenance burden without providing value.

Suggested change
// This file defines guard policy configuration and helpers.
package config
// GuardPolicyConfig provides a type-safe interface for accessing guard policies
// from ServerConfig. Guard policies control access to MCP server resources.
//
// Structure (GitHub MCP Server):
// - repos: "all", "public", or array of patterns (e.g., ["owner/repo", "owner/*"])
// - min-integrity: "none", "reader", "writer", or "merged"
//
// The guard policies are stored as map[string]interface{} to support
// server-specific schemas without forcing all servers to use the same structure.
type GuardPolicyConfig struct {
policies map[string]interface{}
}
// NewGuardPolicyConfig creates a GuardPolicyConfig wrapper around the raw policies map.
func NewGuardPolicyConfig(policies map[string]interface{}) *GuardPolicyConfig {
if policies == nil {
return &GuardPolicyConfig{policies: make(map[string]interface{})}
}
return &GuardPolicyConfig{policies: policies}
}
// GetPolicy returns the policy configuration for a specific service (e.g., "github", "slack").
// Returns nil if the service has no policy configured.
func (gp *GuardPolicyConfig) GetPolicy(service string) map[string]interface{} {
if gp.policies == nil {
return nil
}
if policy, ok := gp.policies[service].(map[string]interface{}); ok {
return policy
}
return nil
}
// HasPolicy returns true if a policy is configured for the given service.
func (gp *GuardPolicyConfig) HasPolicy(service string) bool {
return gp.GetPolicy(service) != nil
}
// IsEmpty returns true if no policies are configured.
func (gp *GuardPolicyConfig) IsEmpty() bool {
return len(gp.policies) == 0
}
// GetGuardPolicies is a helper method on ServerConfig for type-safe access to guard policies.
func (sc *ServerConfig) GetGuardPolicies() *GuardPolicyConfig {
return NewGuardPolicyConfig(sc.GuardPolicies)
}
// This file previously defined guard policy configuration helpers.
package config

Copilot uses AI. Check for mistakes.
Comment on lines 12 to +15

// logRuntimeError logs runtime errors to stdout per spec section 9.2
func logRuntimeError(errorType, detail string, r *http.Request, serverName *string) {
logAuth.Printf("Logging runtime error: type=%s, detail=%s", errorType, detail)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The logRuntimeError function previously used logErrors = logger.New("server:errors") (defined in the deleted errors.go), but now uses logAuth which logs under the "server:auth" namespace. This changes the debug log namespace for runtime error messages. While minor (typical usage is DEBUG=server:* or DEBUG=*), anyone filtering by DEBUG=server:errors would no longer see these messages. Consider whether this namespace change is intentional.

Suggested change
// logRuntimeError logs runtime errors to stdout per spec section 9.2
func logRuntimeError(errorType, detail string, r *http.Request, serverName *string) {
logAuth.Printf("Logging runtime error: type=%s, detail=%s", errorType, detail)
var logErrors = logger.New("server:errors")
// logRuntimeError logs runtime errors to stdout per spec section 9.2
func logRuntimeError(errorType, detail string, r *http.Request, serverName *string) {
logErrors.Printf("Logging runtime error: type=%s, detail=%s", errorType, detail)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants