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
63 changes: 63 additions & 0 deletions cli/e2e/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//go:build e2e

package e2e_test

import (
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/rogpeppe/go-internal/testscript"
)

var sameBinary string

func TestMain(m *testing.M) {
tmpDir, err := os.MkdirTemp("", "same-e2e-*")
if err != nil {
panic(err)
}

sameBinary = filepath.Join(tmpDir, "same")

//nolint:gosec // Building binary with static arguments, not user input
cmd := exec.Command("nix", "develop", "-c", "go", "build", "-o", sameBinary, "./cli/cmd/same")
cmd.Dir = filepath.Join("..", "..")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
panic("failed to build same binary: " + err.Error())
}

exitCode := m.Run()

_ = os.RemoveAll(tmpDir)

os.Exit(exitCode)
}

func TestScripts(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata",
Setup: setupE2E,
})
}

func setupE2E(env *testscript.Env) error {
env.Setenv("NO_COLOR", "1")
env.Setenv("CI", "true")

binDir := filepath.Dir(sameBinary)
currentPath := env.Getenv("PATH")
env.Setenv("PATH", binDir+string(os.PathListSeparator)+currentPath)

homeDir := filepath.Join(env.WorkDir, ".home")
if err := os.MkdirAll(homeDir, 0o750); err != nil {
return err
}
env.Setenv("HOME", homeDir)

return nil
}
12 changes: 12 additions & 0 deletions cli/e2e/testdata/basic_execution.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Basic task execution test
exec same run --ci hello
stderr '\[hello\] Starting\.\.\.'
stdout '\[hello\] Hello, World!'
stderr '\[hello\] ✓ Completed'

-- same.yaml --
version: "1"
project: test
tasks:
hello:
cmd: ["echo", "Hello, World!"]
19 changes: 19 additions & 0 deletions cli/e2e/testdata/cache_hit.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# First run builds from scratch
exec same run --ci greet
stderr '\[greet\] ✓ Completed'
! stderr 'Cached'

# Second run hits cache
exec same run --ci greet
stderr '\[greet\] ⚡ Cached'

-- same.yaml --
version: "1"
project: test
tasks:
greet:
cmd: ["echo", "Greetings!"]
input: ["input.txt"]

-- input.txt --
Hello
26 changes: 26 additions & 0 deletions cli/e2e/testdata/cache_invalidation.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# First run
exec same run --ci process
stderr '\[process\] ✓ Completed'
exists .same/store

# Modify input
cp data2.txt data.txt

# Second run rebuilds
exec same run --ci process
stderr '\[process\] Starting\.\.\.'
stderr '\[process\] ✓ Completed'
! stderr 'Cached'

-- same.yaml --
version: "1"
project: test
tasks:
process:
input: ["data.txt"]
cmd: ["cat", "data.txt"]

-- data.txt --
original
-- data2.txt --
modified
30 changes: 30 additions & 0 deletions cli/e2e/testdata/clean.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Run task to populate cache
exec same run --ci task1
exists .same/store

# Clean build cache (default)
exec same clean
! exists .same/store

# Verify cache directories may still exist
# (Nix cache is managed separately)

# Repopulate
exec same run --ci task1
exists .same/store

# Clean all - removes build store and attempts to clean cache
exec same clean --all
! exists .same/store
# Note: cache directory structure may remain even after clean --all

-- same.yaml --
version: "1"
project: test
tasks:
task1:
cmd: ["echo", "test"]
input: ["file.txt"]

-- file.txt --
content
27 changes: 27 additions & 0 deletions cli/e2e/testdata/dependency_order.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Verify topological execution order
exec same run --ci final
stderr '\[setup\] Starting\.\.\.'
stderr '\[setup\] ✓ Completed'
stderr '\[build\] Starting\.\.\.'
stderr '\[build\] ✓ Completed'
stderr '\[final\] Starting\.\.\.'
stderr '\[final\] ✓ Completed'

-- same.yaml --
version: "1"
project: test
tasks:
setup:
cmd: ["sh", "-c", "echo 'Setup complete' > setup.txt"]
target: ["setup.txt"]

build:
cmd: ["sh", "-c", "cat setup.txt && echo 'Build complete' > build.txt"]
input: ["setup.txt"]
target: ["build.txt"]
dependsOn: ["setup"]

final:
cmd: ["sh", "-c", "cat build.txt && echo 'Final step'"]
input: ["build.txt"]
dependsOn: ["build"]
17 changes: 17 additions & 0 deletions cli/e2e/testdata/error_circular_deps.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Circular dependency should be detected
! exec same run --ci a
# Command should fail with non-zero exit code

-- same.yaml --
version: "1"
project: test
tasks:
a:
cmd: ["echo", "A"]
dependsOn: ["b"]
b:
cmd: ["echo", "B"]
dependsOn: ["c"]
c:
cmd: ["echo", "C"]
dependsOn: ["a"]
9 changes: 9 additions & 0 deletions cli/e2e/testdata/error_invalid_config.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Invalid config should fail with error
! exec same run --ci task1
stderr 'failed to load configuration'

-- same.yaml --
version: "1"
project: test
tasks:
invalid syntax here
3 changes: 3 additions & 0 deletions cli/e2e/testdata/error_missing_file.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# No same.yaml present
! exec same run --ci anything
stderr 'could not find samefile or workfile'
9 changes: 9 additions & 0 deletions cli/e2e/testdata/error_unknown_task.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
! exec same run --ci nonexistent
# Command should fail with non-zero exit code

-- same.yaml --
version: "1"
project: test
tasks:
real:
cmd: ["echo", "exists"]
22 changes: 22 additions & 0 deletions cli/e2e/testdata/hermetic_env.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Set host variable
env TEST_VAR=from_host

# Task without env should not see it
exec same run --ci no-env
! stdout 'from_host'

# Task with explicit env should see it
exec same run --ci with-env
stdout 'custom_value'

-- same.yaml --
version: "1"
project: test
tasks:
no-env:
cmd: ["sh", "-c", "echo TEST_VAR=${TEST_VAR:-empty}"]

with-env:
cmd: ["sh", "-c", "echo TEST_VAR=$TEST_VAR"]
environment:
TEST_VAR: "custom_value"
22 changes: 22 additions & 0 deletions cli/e2e/testdata/nix_hermetic.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Multiple tools in isolated environment
# TODO: Re-enable when Nix tool resolution is fully implemented
skip 'Nix hermetic environments not yet implemented'

exec same run --ci multi-tool
! stderr 'operation failed'

-- same.work.yaml --
version: "1"
root: "."
tools:
go: go@1.25.4
lint: golangci-lint@2.7.2
projects: ["."]

-- same.yaml --
version: "1"
project: test
tasks:
multi-tool:
cmd: ["sh", "-c", "go version && golangci-lint version"]
tools: ["go", "lint"]
21 changes: 21 additions & 0 deletions cli/e2e/testdata/nix_tool_resolution.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Task requires Go tool from Nix
# TODO: Re-enable when Nix tool resolution is fully implemented
skip 'Nix tool resolution not yet implemented'

exec same run --ci check-go
! stderr 'operation failed'

-- same.work.yaml --
version: "1"
root: "."
tools:
go: go@1.25.4
projects: ["."]

-- same.yaml --
version: "1"
project: test
tasks:
check-go:
cmd: ["go", "version"]
tools: ["go"]
23 changes: 23 additions & 0 deletions cli/e2e/testdata/no_cache_flag.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# First run
exec same run --ci task
stderr '\[task\] ✓ Completed'

# Cached run
exec same run --ci task
stderr 'Cached'

# Force rebuild with --no-cache
exec same run --ci --no-cache task
stderr '\[task\] Starting'
! stderr 'Cached'

-- same.yaml --
version: "1"
project: test
tasks:
task:
cmd: ["echo", "running"]
input: ["data.txt"]

-- data.txt --
stable
30 changes: 30 additions & 0 deletions cli/e2e/testdata/workspace.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Run task from sub-project
cd proj1
exec same run --ci build
stderr '\[build\] ✓ Completed'

# Run task from another project
cd ../proj2
exec same run --ci test
stderr '\[test\] ✓ Completed'

-- same.work.yaml --
version: "1"
root: "."
projects:
- "proj1"
- "proj2"

-- proj1/same.yaml --
version: "1"
project: proj1
tasks:
build:
cmd: ["echo", "Building proj1"]

-- proj2/same.yaml --
version: "1"
project: proj2
tasks:
test:
cmd: ["echo", "Testing proj2"]
3 changes: 2 additions & 1 deletion cli/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/creack/pty v1.1.24
github.com/grindlemire/graft v0.2.3
github.com/muesli/termenv v0.16.0
github.com/rogpeppe/go-internal v1.14.1
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1
github.com/vito/midterm v0.2.3
Expand All @@ -18,6 +19,7 @@ require (
go.trai.ch/zerr v0.2.1
go.uber.org/mock v0.6.0
golang.org/x/sync v0.19.0
golang.org/x/term v0.39.0
gopkg.in/yaml.v3 v3.0.1
)

Expand Down Expand Up @@ -51,7 +53,6 @@ require (
go.opentelemetry.io/otel/metric v1.39.0 // indirect
golang.org/x/mod v0.31.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.3.8 // indirect
golang.org/x/tools v0.40.0 // indirect
)
2 changes: 0 additions & 2 deletions cli/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
Expand Down
7 changes: 7 additions & 0 deletions cli/same.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ tasks:
target: ["bin/same"]
tools: ["go"]
dependsOn: ["generate"]

# Run E2E tests
e2e-test:
input: ["e2e", "cmd", "internal"]
cmd: ["go", "test", "-v", "-tags=e2e", "./e2e/..."]
tools: ["go"]
dependsOn: ["generate"]
Loading