99 "os"
1010 "os/exec"
1111 "path/filepath"
12+ "runtime"
1213 "sync"
1314)
1415
@@ -37,10 +38,10 @@ func init() {
3738 moduleDir := filepath .Clean (filepath .Join (wd , ".." , ".." ))
3839 if tmpDir , err := os .MkdirTemp ("" , "pipeleak-e2e-" ); err == nil {
3940 tmpBin := filepath .Join (tmpDir , "pipeleak" )
40- cmd := exec . Command ( "/bin/bash" , "-lc" , fmt . Sprintf ( "cd %q && go build -o %q ." , moduleDir , tmpBin ))
41- cmd . Env = os . Environ ()
42- // Do not wire stdout/stderr here to keep test init quiet
43- if err := cmd . Run ( ); err == nil {
41+ if runtime . GOOS == "windows" {
42+ tmpBin += ".exe"
43+ }
44+ if err := buildBinary ( moduleDir , tmpBin ); err == nil {
4445 pipeleakBinaryResolved = tmpBin
4546 }
4647 }
@@ -64,6 +65,12 @@ func resolveBinaryPath() {
6465 filepath .Join (".." , ".." , "pipeleak" ), // Relative to tests/e2e
6566 }
6667
68+ // On Windows, also try with .exe extension
69+ if runtime .GOOS == "windows" {
70+ candidates = append (candidates , pipeleakBinary + ".exe" )
71+ candidates = append (candidates , filepath .Join (".." , ".." , "pipeleak.exe" ))
72+ }
73+
6774 // If PIPELEAK_BINARY was set, also try it from current working directory
6875 if os .Getenv ("PIPELEAK_BINARY" ) != "" {
6976 wd , _ := os .Getwd ()
@@ -88,6 +95,23 @@ func resolveBinaryPath() {
8895 })
8996}
9097
98+ // buildBinary builds the pipeleak binary in a cross-platform way
99+ func buildBinary (moduleDir , outputPath string ) error {
100+ var cmd * exec.Cmd
101+ if runtime .GOOS == "windows" {
102+ // Use Go build directly on Windows
103+ cmd = exec .Command ("go" , "build" , "-o" , outputPath , "." )
104+ } else {
105+ // Use Go build directly on Unix-like systems
106+ cmd = exec .Command ("go" , "build" , "-o" , outputPath , "." )
107+ }
108+ cmd .Dir = moduleDir
109+ cmd .Env = os .Environ ()
110+ // Note: stdout/stderr are intentionally not wired to keep init() quiet
111+ // Errors will be surfaced on first execution if build fails
112+ return cmd .Run ()
113+ }
114+
91115// executeCLIWithContext calls the actual CLI command execution via exec.Command with context support
92116// This avoids cobra global state issues by running the binary as a separate process
93117func executeCLIWithContext (ctx context.Context , args []string ) error {
@@ -116,6 +140,9 @@ func executeCLIWithContext(ctx context.Context, args []string) error {
116140 return
117141 }
118142 tmpBin := filepath .Join (tmpDir , "pipeleak" )
143+ if runtime .GOOS == "windows" {
144+ tmpBin += ".exe"
145+ }
119146
120147 // Build from the module root containing main.go (./ relative to src/pipeleak)
121148 // We assume tests run from the repo module at src/pipeleak/tests/e2e
@@ -127,12 +154,7 @@ func executeCLIWithContext(ctx context.Context, args []string) error {
127154 // tests run in src/pipeleak/tests/e2e; module with main.go is at ../../
128155 moduleDir := filepath .Clean (filepath .Join (buildDir , ".." , ".." ))
129156
130- // Use bash -lc to ensure proper PATH resolution for 'go' and allow 'cd' semantics
131- buildCmd := exec .Command ("/bin/bash" , "-lc" , fmt .Sprintf ("cd %q && go build -o %q ." , moduleDir , tmpBin ))
132- buildCmd .Env = os .Environ ()
133- buildCmd .Stdout = os .Stdout
134- buildCmd .Stderr = os .Stderr
135- if err := buildCmd .Run (); err != nil {
157+ if err := buildBinary (moduleDir , tmpBin ); err != nil {
136158 pipeleakBinaryResolved = ""
137159 return
138160 }
0 commit comments