Skip to content

Commit 66c2f88

Browse files
authored
Add Windows Test Runner (#326)
* Add Windows support to test workflow and e2e tests
1 parent 6e8844e commit 66c2f88

3 files changed

Lines changed: 80 additions & 27 deletions

File tree

.github/workflows/test.yml

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,67 @@ permissions:
1010
contents: read
1111

1212
jobs:
13-
test:
14-
name: Go Tests
15-
runs-on: ubuntu-latest
13+
unit-tests:
14+
name: Unit Tests
15+
runs-on: ${{ matrix.os }}
16+
strategy:
17+
matrix:
18+
os: [ubuntu-latest, windows-latest]
1619
steps:
1720
- uses: actions/checkout@v5
1821

1922
- uses: actions/setup-go@v6
2023
with:
2124
go-version: stable
25+
cache: true
2226

23-
- name: Run unit tests
27+
- name: Run unit tests (Linux)
28+
if: runner.os == 'Linux'
2429
working-directory: ./src/pipeleak
25-
run: go test $(go list ./... | grep -v /tests/e2e) -v -race -coverprofile=coverage.out -covermode=atomic
30+
run: go test $(go list ./... | grep -v /tests/e2e) -v -race
2631

27-
- name: Build pipeleak binary for e2e tests
32+
- name: Run unit tests (Windows)
33+
if: runner.os == 'Windows'
34+
working-directory: ./src/pipeleak
35+
run: |
36+
$packages = go list ./... | Where-Object { $_ -notmatch '/tests/e2e' }
37+
go test $packages -v -race
38+
shell: pwsh
39+
40+
e2e-tests:
41+
name: E2E Tests
42+
runs-on: ${{ matrix.os }}
43+
strategy:
44+
matrix:
45+
os: [ubuntu-latest, windows-latest]
46+
steps:
47+
- uses: actions/checkout@v5
48+
49+
- uses: actions/setup-go@v6
50+
with:
51+
go-version: stable
52+
cache: true
53+
54+
- name: Build pipeleak binary for e2e tests (Linux)
55+
if: runner.os == 'Linux'
2856
working-directory: ./src/pipeleak
2957
run: go build -o pipeleak .
3058

31-
- name: Run e2e tests
59+
- name: Build pipeleak binary for e2e tests (Windows)
60+
if: runner.os == 'Windows'
61+
working-directory: ./src/pipeleak
62+
run: go build -o pipeleak.exe .
63+
64+
- name: Run e2e tests (Linux)
65+
if: runner.os == 'Linux'
3266
working-directory: ./src/pipeleak
3367
run: go test ./tests/e2e/... -v -timeout 10m
3468
env:
3569
PIPELEAK_BINARY: ./pipeleak
3670

37-
- name: Display coverage
71+
- name: Run e2e tests (Windows)
72+
if: runner.os == 'Windows'
3873
working-directory: ./src/pipeleak
39-
run: go tool cover -func=coverage.out
40-
41-
- name: Upload coverage reports
42-
uses: codecov/codecov-action@v5
43-
with:
44-
files: ./src/pipeleak/coverage.out
45-
flags: unittests
46-
name: codecov-umbrella
47-
continue-on-error: true
74+
run: go test ./tests/e2e/... -v -timeout 10m
75+
env:
76+
PIPELEAK_BINARY: ./pipeleak.exe

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ renovate-enum-out
55
cli-docs
66
site
77
src/pipeleak/pipeleak
8+
src/pipeleak/pipeleak.exe
9+
src/pipeleak/coverage.out
810
.vscode

src/pipeleak/tests/e2e/cli_integration.go

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
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
93117
func 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

Comments
 (0)