Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions internal/auth/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (

"github.com/github/gh-aw-mcpg/internal/logger"
"github.com/github/gh-aw-mcpg/internal/logger/sanitize"
"github.com/github/gh-aw-mcpg/internal/strutil"
)

var log = logger.New("auth:header")
Expand Down Expand Up @@ -173,8 +174,5 @@ func TruncateSessionID(sessionID string) string {
if sessionID == "" {
return "(none)"
}
if len(sessionID) <= 8 {
return sessionID
}
return sessionID[:8] + "..."
return strutil.Truncate(sessionID, 8)
}
25 changes: 25 additions & 0 deletions internal/difc/tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package difc

import "strings"

// StringsToTags converts a slice of strings to a slice of Tags,
// trimming whitespace and skipping empty values.
func StringsToTags(values []string) []Tag {
tags := make([]Tag, 0, len(values))
for _, value := range values {
trimmed := strings.TrimSpace(value)
if trimmed != "" {
tags = append(tags, Tag(trimmed))
}
}
return tags
}

// TagsToStrings converts a slice of Tags to a slice of strings.
func TagsToStrings(tags []Tag) []string {
values := make([]string, 0, len(tags))
for _, tag := range tags {
values = append(values, string(tag))
}
return values
}
89 changes: 89 additions & 0 deletions internal/difc/tags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package difc

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestStringsToTags(t *testing.T) {
tests := []struct {
name string
values []string
expected []Tag
}{
{
name: "empty slice",
values: []string{},
expected: []Tag{},
},
{
name: "nil slice",
values: nil,
expected: []Tag{},
},
{
name: "single value",
values: []string{"private:owner"},
expected: []Tag{"private:owner"},
},
{
name: "multiple values",
values: []string{"private:owner", "private:owner/repo"},
expected: []Tag{"private:owner", "private:owner/repo"},
},
{
name: "trims whitespace",
values: []string{" private:owner ", "\tprivate:repo\t"},
expected: []Tag{"private:owner", "private:repo"},
},
{
name: "skips empty strings",
values: []string{"private:owner", "", " ", "private:repo"},
expected: []Tag{"private:owner", "private:repo"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := StringsToTags(tt.values)
assert.Equal(t, tt.expected, result)
})
}
}

func TestTagsToStrings(t *testing.T) {
tests := []struct {
name string
tags []Tag
expected []string
}{
{
name: "empty slice",
tags: []Tag{},
expected: []string{},
},
{
name: "nil slice",
tags: nil,
expected: []string{},
},
{
name: "single tag",
tags: []Tag{"private:owner"},
expected: []string{"private:owner"},
},
{
name: "multiple tags",
tags: []Tag{"private:owner", "private:owner/repo"},
expected: []string{"private:owner", "private:owner/repo"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := TagsToStrings(tt.tags)
assert.Equal(t, tt.expected, result)
})
}
}
107 changes: 0 additions & 107 deletions internal/dockerutil/env_test.go

This file was deleted.

3 changes: 1 addition & 2 deletions internal/mcp/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"sync"
"time"

"github.com/github/gh-aw-mcpg/internal/dockerutil"
"github.com/github/gh-aw-mcpg/internal/logger"
"github.com/github/gh-aw-mcpg/internal/logger/sanitize"
sdk "github.com/modelcontextprotocol/go-sdk/mcp"
Expand Down Expand Up @@ -131,7 +130,7 @@ func NewConnection(ctx context.Context, serverID, command string, args []string,

// Expand Docker -e flags that reference environment variables
// Docker's `-e VAR_NAME` expects VAR_NAME to be in the environment
expandedArgs := dockerutil.ExpandEnvArgs(args)
expandedArgs := ExpandEnvArgs(args)
logConn.Printf("Expanded args for Docker env: %v", sanitize.SanitizeArgs(expandedArgs))

// Create command transport
Expand Down
46 changes: 29 additions & 17 deletions internal/mcp/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"strings"
"testing"

"github.com/github/gh-aw-mcpg/internal/dockerutil"
"github.com/github/gh-aw-mcpg/internal/logger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -202,13 +201,13 @@ func TestExpandDockerEnvArgs(t *testing.T) {
expected: []string{"run", "-e", "VAR1=value1", "-e", "VAR2=fixed", "image"},
},
{
name: "undefined env variable",
name: "undefined env variable leaves arg unchanged",
args: []string{"run", "-e", "UNDEFINED_VAR", "image"},
envVars: map[string]string{},
expected: []string{"run", "-e", "UNDEFINED_VAR", "image"},
},
{
name: "empty env variable value",
name: "empty env variable value expands to key=",
args: []string{"run", "-e", "EMPTY_VAR", "image"},
envVars: map[string]string{"EMPTY_VAR": ""},
expected: []string{"run", "-e", "EMPTY_VAR=", "image"},
Expand All @@ -219,32 +218,45 @@ func TestExpandDockerEnvArgs(t *testing.T) {
envVars: map[string]string{},
expected: []string{"run", "image", "-e"},
},
{
name: "nil args returns empty slice",
args: nil,
envVars: map[string]string{},
expected: []string{},
},
{
name: "empty args returns empty slice",
args: []string{},
envVars: map[string]string{},
expected: []string{},
},
{
name: "-e followed by empty string arg is not expanded",
args: []string{"run", "-e", "", "image"},
envVars: map[string]string{},
expected: []string{"run", "-e", "", "image"},
},
{
name: "value with equals sign in env var value",
args: []string{"run", "-e", "KEY_WITH_EQUALS", "image"},
envVars: map[string]string{"KEY_WITH_EQUALS": "a=b=c"},
expected: []string{"run", "-e", "KEY_WITH_EQUALS=a=b=c", "image"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set up environment variables for test
for k, v := range tt.envVars {
os.Setenv(k, v)
require.NoError(t, os.Setenv(k, v))
}
// Clean up after test
t.Cleanup(func() {
for k := range tt.envVars {
os.Unsetenv(k)
}
})

result := dockerutil.ExpandEnvArgs(tt.args)

if len(result) != len(tt.expected) {
t.Fatalf("Expected %d args, got %d: %v", len(tt.expected), len(result), result)
}

for i := range result {
if result[i] != tt.expected[i] {
t.Errorf("Arg %d: expected '%s', got '%s'", i, tt.expected[i], result[i])
}
}
result := ExpandEnvArgs(tt.args)
assert.Equal(t, tt.expected, result)
})
}
}
Expand Down
16 changes: 8 additions & 8 deletions internal/dockerutil/env.go → internal/mcp/dockerenv.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dockerutil
package mcp

import (
"fmt"
Expand All @@ -8,12 +8,12 @@ import (
"github.com/github/gh-aw-mcpg/internal/logger"
)

var logDockerutil = logger.New("dockerutil:env")
var logDockerEnv = logger.New("mcp:dockerenv")

// ExpandEnvArgs expands Docker -e flags that reference environment variables
// Converts "-e VAR_NAME" to "-e VAR_NAME=value" by reading from the process environment
// ExpandEnvArgs expands Docker -e flags that reference environment variables.
// Converts "-e VAR_NAME" to "-e VAR_NAME=value" by reading from the process environment.
func ExpandEnvArgs(args []string) []string {
logDockerutil.Printf("Expanding env args: input_count=%d", len(args))
logDockerEnv.Printf("Expanding env args: input_count=%d", len(args))
result := make([]string, 0, len(args))
for i := 0; i < len(args); i++ {
arg := args[i]
Expand All @@ -25,17 +25,17 @@ func ExpandEnvArgs(args []string) []string {
if len(nextArg) > 0 && !strings.Contains(nextArg, "=") {
// Look up the variable in the environment
if value, exists := os.LookupEnv(nextArg); exists {
logDockerutil.Printf("Expanding env var: name=%s", nextArg)
logDockerEnv.Printf("Expanding env var: name=%s", nextArg)
result = append(result, "-e")
result = append(result, fmt.Sprintf("%s=%s", nextArg, value))
i++ // Skip the next arg since we processed it
continue
}
logDockerutil.Printf("Env var not found in process environment: name=%s", nextArg)
logDockerEnv.Printf("Env var not found in process environment: name=%s", nextArg)
}
}
result = append(result, arg)
}
logDockerutil.Printf("Env args expansion complete: output_count=%d", len(result))
logDockerEnv.Printf("Env args expansion complete: output_count=%d", len(result))
return result
}
Loading
Loading