Skip to content

Commit ab5c342

Browse files
authored
test: implement the nits -- use filepath.Join instead of string concatenation (#139)
Replace manual path concatenation with filepath.Join for cross-platform compatibility. Remove redundant getBasePath() helper method. Improve the environment variable test -- it works indeed Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
1 parent 3b64102 commit ab5c342

File tree

2 files changed

+106
-48
lines changed

2 files changed

+106
-48
lines changed

environment/integration/integration_test.go

Lines changed: 103 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ func TestSystemHandlesProblematicFiles(t *testing.T) {
155155

156156
// Should still handle text files
157157
user.FileWrite(env.ID, "notes.txt", "System should handle binary directories gracefully", "Add text file")
158+
159+
// Verify the text file was written and can be read
160+
content := user.FileRead(env.ID, "notes.txt")
161+
assert.Equal(t, "System should handle binary directories gracefully", content)
158162
})
159163
})
160164

@@ -395,7 +399,6 @@ func TestWeirdUserScenarios(t *testing.T) {
395399
require.NoError(t, err)
396400
assert.Contains(t, jsContent, "repo1", "Environment should still access its original repo")
397401
})
398-
399402
}
400403

401404
// TestEnvironmentConfigurationPersists verifies configuration persistence
@@ -467,44 +470,106 @@ func TestEnvironmentConfigurationPersists(t *testing.T) {
467470
})
468471
})
469472

470-
t.Run("EnvironmentVariableLimitations", func(t *testing.T) {
471-
t.Skip("Skipping - demonstrates unfixed limitation with environment variable persistence")
472-
473-
WithRepository(t, "envvar_test", SetupNodeRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
474-
newEnv := user.CreateEnvironment("Test env vars", "Creating environment for env var testing")
475-
476-
// Set environment variables
477-
vars := []string{
478-
"API_URL=https://api.example.com",
479-
"NODE_ENV=production",
480-
"PORT=3000",
481-
}
482-
483-
// Update config with environment variables
484-
updatedConfig := newEnv.Config.Copy()
485-
updatedConfig.Env = vars
486-
487-
user.UpdateEnvironment(newEnv.ID, "Test env vars", "Configure app", updatedConfig)
488-
489-
// Variables work in current session
490-
output := user.RunCommand(newEnv.ID, "echo API_URL=$API_URL NODE_ENV=$NODE_ENV PORT=$PORT", "Check env vars")
491-
assert.Contains(t, output, "API_URL=https://api.example.com")
492-
assert.Contains(t, output, "NODE_ENV=production")
493-
assert.Contains(t, output, "PORT=3000")
494-
495-
// Rebuild container
496-
rebuildConfig := newEnv.Config.Copy()
497-
user.UpdateEnvironment(newEnv.ID, "Test env vars", "Rebuild container", rebuildConfig)
498-
499-
// Env vars should persist through rebuilds (but don't)
500-
output = user.RunCommand(newEnv.ID, "echo API_URL=$API_URL", "Check API_URL after rebuild")
501-
assert.Contains(t, output, "API_URL=https://api.example.com")
502-
503-
output = user.RunCommand(newEnv.ID, "echo NODE_ENV=$NODE_ENV", "Check NODE_ENV after rebuild")
504-
assert.Contains(t, output, "NODE_ENV=production")
473+
t.Run("EnvironmentVariable", func(t *testing.T) {
474+
t.Run("Persistence", func(t *testing.T) {
475+
WithRepository(t, "envvar_persistence", SetupNodeRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
476+
// User: "Create a Node.js development environment"
477+
env := user.CreateEnvironment("Node.js Dev", "Setting up Node.js development environment")
478+
envID := env.ID // LLM only keeps the ID, not the whole object
479+
480+
// User: "I need to set environment variables for my API"
481+
// LLM has to provide ALL required fields because the tool requires them
482+
user.UpdateEnvironment(envID, "Node.js Dev", "Configure API environment variables", &environment.EnvironmentConfig{
483+
Instructions: "Node.js development environment with API configuration",
484+
BaseImage: "ubuntu:24.04",
485+
SetupCommands: []string{},
486+
Workdir: "/workdir",
487+
Env: []string{
488+
"API_URL=https://api.example.com",
489+
"NODE_ENV=production",
490+
"PORT=3000",
491+
},
492+
Secrets: []string{},
493+
})
494+
495+
// User: "Check if my environment variables are set"
496+
output := user.RunCommand(envID, "echo API_URL=$API_URL NODE_ENV=$NODE_ENV PORT=$PORT", "Verify env vars")
497+
assert.Contains(t, output, "API_URL=https://api.example.com")
498+
assert.Contains(t, output, "NODE_ENV=production")
499+
assert.Contains(t, output, "PORT=3000")
500+
501+
// User: "Add a simple setup command"
502+
// Again, LLM must provide ALL fields, potentially losing env vars if not careful
503+
user.UpdateEnvironment(envID, "Node.js Dev", "Add setup command", &environment.EnvironmentConfig{
504+
Instructions: "Node.js development environment with API configuration",
505+
BaseImage: "ubuntu:24.04",
506+
SetupCommands: []string{
507+
"echo 'Setup complete' > /tmp/setup.log",
508+
},
509+
Workdir: "/workdir",
510+
Env: []string{
511+
"API_URL=https://api.example.com",
512+
"NODE_ENV=production",
513+
"PORT=3000",
514+
},
515+
Secrets: []string{},
516+
})
517+
518+
// User: "Are my environment variables still there?"
519+
output = user.RunCommand(envID, "echo API_URL=$API_URL", "Check API_URL after rebuild")
520+
assert.Contains(t, output, "API_URL=https://api.example.com")
521+
522+
output = user.RunCommand(envID, "echo NODE_ENV=$NODE_ENV", "Check NODE_ENV after rebuild")
523+
assert.Contains(t, output, "NODE_ENV=production")
524+
525+
output = user.RunCommand(envID, "echo PORT=$PORT", "Check PORT after rebuild")
526+
assert.Contains(t, output, "PORT=3000")
527+
})
528+
})
505529

506-
output = user.RunCommand(newEnv.ID, "echo PORT=$PORT", "Check PORT after rebuild")
507-
assert.Contains(t, output, "PORT=3000")
530+
t.Run("Loss", func(t *testing.T) {
531+
// This test shows what happens when an LLM forgets to include env vars
532+
WithRepository(t, "envvar_loss", SetupNodeRepo, func(t *testing.T, repo *repository.Repository, user *UserActions) {
533+
// User: "Create a Node.js environment with env vars"
534+
env := user.CreateEnvironment("Node.js API", "Create Node.js API environment")
535+
envID := env.ID
536+
537+
// User: "Set up my API environment variables"
538+
user.UpdateEnvironment(envID, "Node.js API", "Configure environment", &environment.EnvironmentConfig{
539+
Instructions: "Node.js API with environment variables",
540+
BaseImage: "ubuntu:24.04",
541+
SetupCommands: []string{},
542+
Workdir: "/workdir",
543+
Env: []string{
544+
"DATABASE_URL=postgres://localhost:5432/mydb",
545+
"REDIS_URL=redis://localhost:6379",
546+
"API_KEY=secret123",
547+
},
548+
Secrets: []string{},
549+
})
550+
551+
// Verify env vars are set
552+
output := user.RunCommand(envID, "echo DATABASE_URL=$DATABASE_URL", "Check database URL")
553+
assert.Contains(t, output, "DATABASE_URL=postgres://localhost:5432/mydb")
554+
555+
// User: "Add a marker file"
556+
// LLM forgets to include the env vars when updating!
557+
user.UpdateEnvironment(envID, "Node.js API", "Add marker file", &environment.EnvironmentConfig{
558+
Instructions: "Node.js API with Redis support",
559+
BaseImage: "ubuntu:24.04",
560+
SetupCommands: []string{
561+
"touch /tmp/marker.txt",
562+
},
563+
Workdir: "/workdir",
564+
Env: []string{}, // Oops! LLM forgot to include existing env vars
565+
Secrets: []string{},
566+
})
567+
568+
// Check if env vars are lost
569+
output = user.RunCommand(envID, "echo DATABASE_URL=$DATABASE_URL", "Check if database URL survived")
570+
assert.NotContains(t, output, "postgres://localhost:5432/mydb", "Environment variables were lost!")
571+
assert.Equal(t, "DATABASE_URL=\n", output, "DATABASE_URL should be empty")
572+
})
508573
})
509574
})
510575

repository/repository.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log/slog"
88
"os"
99
"os/exec"
10+
"path/filepath"
1011
"sort"
1112
"strings"
1213

@@ -30,22 +31,14 @@ type Repository struct {
3031
basePath string // defaults to ~/.config/container-use if empty
3132
}
3233

33-
// getBasePath returns the base path for container-use data, using the default if not set
34-
func (r *Repository) getBasePath() string {
35-
if r.basePath != "" {
36-
return r.basePath
37-
}
38-
return cuGlobalConfigPath
39-
}
40-
4134
// getRepoPath returns the path for storing repository data
4235
func (r *Repository) getRepoPath() string {
43-
return r.getBasePath() + "/repos"
36+
return filepath.Join(r.basePath, "repos")
4437
}
4538

4639
// getWorktreePath returns the path for storing worktrees
4740
func (r *Repository) getWorktreePath() string {
48-
return r.getBasePath() + "/worktrees"
41+
return filepath.Join(r.basePath, "worktrees")
4942
}
5043

5144
func Open(ctx context.Context, repo string) (*Repository, error) {

0 commit comments

Comments
 (0)