Skip to content

Commit 3507cf4

Browse files
feat(ci): support running e2e tests on windows
Signed-off-by: Swapnanil-Gupta <swpnlg@amazon.com>
1 parent d9898a5 commit 3507cf4

10 files changed

Lines changed: 193 additions & 49 deletions

File tree

.github/workflows/macos-ci.yaml

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ on:
1616
- deps/full-os.conf
1717
- deps/lima-bundles.conf
1818
- e2e/**
19-
- lima-template/**
19+
- lima-template/macos.yaml
2020
- Makefile
2121
- Makefile.darwin
2222
workflow_dispatch:
@@ -26,33 +26,6 @@ concurrency:
2626
cancel-in-progress: true
2727

2828
jobs:
29-
install-dependencies:
30-
# This is a spot check for make install.dependencies on macOS x86/ARM platforms.
31-
# Finch-core provides the core dependencies needed to run Finch such as the base OS
32-
# image, rootfs, and Lima bundle. Validate the mechanism used to install the core
33-
# dependencies works on macOS.
34-
strategy:
35-
fail-fast: false
36-
matrix:
37-
os: [macos-26, macos-15, macos-15-intel]
38-
runs-on: ${{ matrix.os }}
39-
steps:
40-
- name: Checkout code
41-
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
42-
with:
43-
fetch-depth: 0
44-
persist-credentials: false
45-
submodules: true
46-
- name: Setup go
47-
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
48-
with:
49-
go-version-file: e2e/go.mod
50-
cache-dependency-path: e2e/go.sum
51-
- name: Install platform dependencies
52-
run: make install.dependencies
53-
- name: Clean up dependencies
54-
run: make clean
55-
5629
e2e-tests:
5730
strategy:
5831
fail-fast: false
@@ -91,7 +64,7 @@ jobs:
9164
- name: Install dependencies
9265
shell: zsh {0}
9366
run: brew install lz4 automake autoconf libtool
94-
- name: Build project
67+
- name: Install platform dependencies
9568
shell: zsh {0}
9669
run: |
9770
export PATH="/opt/homebrew/opt/libtool/libexec/gnubin:$PATH"
@@ -102,3 +75,6 @@ jobs:
10275
- name: Run e2e tests
10376
shell: zsh {0}
10477
run: FINCH_VM_TYPE=${{ matrix.vm_type }} make test-e2e
78+
- name: Clean up dependencies
79+
if: always()
80+
run: make clean

.github/workflows/windows-ci.yaml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,31 @@ on:
1414
- .gitmodules
1515
- deps/container-runtime-full-archive.conf
1616
- deps/rootfs.conf
17-
- lima-template/**
17+
- e2e/**
18+
- lima-template/windows.yaml
1819
- Makefile
1920
- Makefile.windows
2021
workflow_dispatch:
2122

23+
permissions:
24+
contents: read
25+
2226
concurrency:
2327
group: ${{ github.workflow }}-${{ github.ref }}
2428
cancel-in-progress: true
2529

2630
jobs:
27-
install-dependencies:
28-
# This is a spot check for make install.dependencies on Windows platform.
29-
# Finch-core provides the core dependencies needed to run Finch such as the base OS
30-
# image, rootfs, and Lima bundle. Validate the mechanism used to install the core
31-
# dependencies works on Windows.
31+
e2e-tests:
3232
strategy:
3333
fail-fast: false
3434
matrix:
35-
os: [windows-2022]
35+
os: [windows-2025]
3636
runs-on: ${{ matrix.os }}
3737
steps:
38+
- name: Configure git CRLF settings
39+
run: |
40+
git config --global core.autocrlf false
41+
git config --global core.eol lf
3842
- name: Checkout code
3943
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
4044
with:
@@ -46,7 +50,17 @@ jobs:
4650
with:
4751
go-version-file: e2e/go.mod
4852
cache-dependency-path: e2e/go.sum
53+
- name: Setup WSL2
54+
uses: Vampire/setup-wsl@v7
55+
- name: Allow inbound traffic from WSL2
56+
shell: pwsh
57+
run: |
58+
New-NetFirewallRule -DisplayName "Allow WSL2 inbound" -Direction Inbound `
59+
-RemoteAddress 172.16.0.0/12 -Action Allow | Out-Null
4960
- name: Install platform dependencies
5061
run: make install.dependencies
62+
- name: Run e2e tests
63+
run: make test-e2e
5164
- name: Clean up dependencies
65+
if: always()
5266
run: make clean

Makefile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ $(FINCH_DAEMON_OUTDIR)/finch-daemon: $(OUTPUT_DIRECTORIES)
5757
install: uninstall
5858
mkdir -p $(DEST)
5959
(cd _output && tar c * | tar Cvx $(DEST) )
60-
sed -i.bak -e "s|${FINCH_OS_IMAGE_LOCATION}|$(FINCH_IMAGE_LOCATION)|g" $(DEST)/lima-template/fedora.yaml
60+
sed -i.bak -e "s|${FINCH_OS_IMAGE_LOCATION}|$(FINCH_IMAGE_LOCATION)|g" $(DEST)/lima-template/macos.yaml
6161
rm $(DEST)/lima-template/*.yaml.bak
6262

6363
.PHONY: uninstall
@@ -75,6 +75,11 @@ clean:
7575
-@cd src/finch-daemon && make clean 2>/dev/null || true
7676
-@cd src/socket_vmnet && make clean 2>/dev/null || true
7777

78+
# Windows CI runs on GitHub hosted runners and can take over 1h to complete.
7879
.PHONY: test-e2e
79-
test-e2e: $(LIMA_TEMPLATE_OUTDIR)/fedora.yaml
80-
cd e2e && VM_TYPE=$(FINCH_VM_TYPE) go test -timeout 30m -v ./... -ginkgo.v
80+
test-e2e: $(LIMA_TEMPLATE)
81+
cd e2e && VM_TYPE=$(FINCH_VM_TYPE) LIMA_TEMPLATE=$(LIMA_TEMPLATE) \
82+
go test -timeout 3h -v ./... \
83+
-ginkgo.vv \
84+
-ginkgo.timeout=3h \
85+
-ginkgo.flake-attempts=3

Makefile.darwin

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
OS_OUTDIR := $(OUTDIR)/os
55
LIMA_TEMPLATE_OUTDIR := $(OUTDIR)/lima-template
6+
LIMA_TEMPLATE := $(LIMA_TEMPLATE_OUTDIR)/macos.yaml
67
CRED_HELPERS_OUTDIR := $(OUTDIR)/cred-helpers
78
OUTPUT_DIRECTORIES += $(OS_OUTDIR) $(LIMA_TEMPLATE_OUTDIR) $(CRED_HELPERS_OUTDIR)
89
SOCKET_VMNET_TEMP_PREFIX ?= $(OUTDIR)/dependencies/lima-socket_vmnet/opt/finch
@@ -61,8 +62,8 @@ install.lima-socket-vmnet:
6162
cd src/socket_vmnet && git clean -f -d
6263
cd src/socket_vmnet && PREFIX=$(SOCKET_VMNET_TEMP_PREFIX) "$(MAKE)" install.bin
6364

64-
$(LIMA_TEMPLATE_OUTDIR)/fedora.yaml: $(LIMA_TEMPLATE_OUTDIR)
65-
cp lima-template/fedora.yaml $@.template
65+
$(LIMA_TEMPLATE_OUTDIR)/macos.yaml: $(LIMA_TEMPLATE_OUTDIR)
66+
cp lima-template/macos.yaml $@.template
6667
# using -i.bak is very intentional, it allows the following commands to succeed for both GNU / BSD sed
6768
# this sed command uses the alternative separator of "|" because the image location uses "/"
6869
sed -i.bak -e "s|<image_location>|$(FINCH_IMAGE_LOCATION)|g" $@.template

Makefile.windows

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,34 @@
33

44
# TODO: Use Finch rootfs in Finch on Windows testing
55
ROOTFS_OUTPUT_DIR := $(OUTDIR)/os
6+
LIMA_TEMPLATE_OUTDIR := $(OUTDIR)/lima-template
7+
LIMA_TEMPLATE := $(LIMA_TEMPLATE_OUTDIR)/windows.yaml
68
CRED_HELPERS_OUTDIR := $(OUTDIR)/cred-helpers
7-
OUTPUT_DIRECTORIES += $(ROOTFS_OUTPUT_DIR) $(CRED_HELPERS_OUTDIR)
9+
OUTPUT_DIRECTORIES += $(ROOTFS_OUTPUT_DIR) $(LIMA_TEMPLATE_OUTDIR) $(CRED_HELPERS_OUTDIR)
810

911
include $(CURDIR)/deps/rootfs.conf
1012
ifeq ($(ARCH), x86_64)
1113
FINCH_ROOTFS_BASENAME := $(X86_64_ARTIFACT)
1214
FINCH_ROOTFS_DIGEST := $(X86_64_512_DIGEST)
15+
LIMA_ARCH = x86_64
1316
else
1417
$(error Finch on Windows ARM not supported)
1518
endif
1619

20+
# WSL2 imports the locally downloaded rootfs tarball rather than booting a disk image.
21+
FINCH_IMAGE_LOCATION ?= $(ROOTFS_OUTPUT_DIR)/$(FINCH_ROOTFS_BASENAME)
22+
FINCH_IMAGE_DIGEST ?= "sha512:$(FINCH_ROOTFS_DIGEST)"
23+
24+
# rootfs.conf sets X86_64_ARTIFACT_PATHING for the rootfs download; clear it so it
25+
# does not leak into the container-runtime artifact URL below.
26+
X86_64_ARTIFACT_PATHING :=
27+
include $(CURDIR)/deps/container-runtime-full-archive.conf
28+
ifneq ($(X86_64_ARTIFACT_PATHING),)
29+
X86_64_ARTIFACT := "$(X86_64_ARTIFACT_PATHING)/$(X86_64_ARTIFACT)"
30+
endif
31+
CONTAINER_RUNTIME_ARCHIVE_X86_64_LOCATION ?= "$(ARTIFACT_BASE_URL)/$(X86_64_ARTIFACT)"
32+
CONTAINER_RUNTIME_ARCHIVE_X86_64_DIGEST ?= "sha256:$(X86_64_256_DIGEST)"
33+
1734
# WSL2 is the only virtual machine type supported for Finch on Windows
1835
FINCH_VM_TYPE := wsl2
1936

@@ -22,14 +39,32 @@ WINGIT_x86_URL := $(or $(WINGIT_x86_URL),https://github.com/git-for-windows/git/
2239
WINGIT_x86_BASENAME ?= $(notdir $(WINGIT_x86_URL))
2340
WINGIT_x86_HASH := $(or $(WINGIT_x86_HASH),"sha512:795a2e7e0be5ab78f2d28d0bd971961d121b9c808a95dec795343dc5af943574dcf54f63a8580c5a5102075abdae387d7a67135c165821428afc07f11ef7543d")
2441

25-
install.dependencies: install.rootfs install.lima install.docker-credhelper
42+
install.dependencies: install.rootfs install.lima install.lima-template install.docker-credhelper
2643

2744
.PHONY: install.rootfs
2845
install.rootfs: $(ROOTFS_OUTPUT_DIR)/$(FINCH_ROOTFS_BASENAME)
2946

3047
$(ROOTFS_OUTPUT_DIR)/$(FINCH_ROOTFS_BASENAME): $(ROOTFS_OUTPUT_DIR) $(CURDIR)/deps/rootfs.conf
3148
bash deps/install.sh --arch $(ARCH) --output $@ $(CURDIR)/deps/rootfs.conf
3249

50+
.PHONY: install.lima-template
51+
install.lima-template: $(LIMA_TEMPLATE)
52+
53+
$(LIMA_TEMPLATE): $(LIMA_TEMPLATE_OUTDIR)
54+
cp lima-template/windows.yaml $@.template
55+
# using -i.bak is very intentional, it allows the following commands to succeed for both GNU / BSD sed
56+
# this sed command uses the alternative separator of "|" because the image location uses "/"
57+
sed -i.bak -e "s|<image_location>|$(FINCH_IMAGE_LOCATION)|g" $@.template
58+
sed -i.bak -e "s/<image_arch>/$(LIMA_ARCH)/g" $@.template
59+
sed -i.bak -e "s/<image_digest>/$(FINCH_IMAGE_DIGEST)/g" $@.template
60+
sed -i.bak -e "s|<container_runtime_archive_x86_64_location>|$(CONTAINER_RUNTIME_ARCHIVE_X86_64_LOCATION)|g" $@.template
61+
sed -i.bak -e "s/<container_runtime_archive_x86_64_digest>/$(CONTAINER_RUNTIME_ARCHIVE_X86_64_DIGEST)/g" $@.template
62+
63+
# Replace was successful, so cleanup .bak files
64+
rm $(LIMA_TEMPLATE_OUTDIR)/*.yaml.template.bak
65+
66+
mv $@.template $@
67+
3368
.PHONY: install.lima
3469
install.lima: lima-exe install.lima-dependencies-wsl2
3570

e2e/e2e_test.go

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
package e2e
55

66
import (
7+
"fmt"
78
"os"
9+
"os/exec"
810
"path/filepath"
11+
"regexp"
12+
"runtime"
913
"testing"
1014

1115
"github.com/onsi/ginkgo/v2"
@@ -38,19 +42,31 @@ func TestE2e(t *testing.T) {
3842
t.Fatalf("failed to get the current working directory: %v", err)
3943
}
4044

41-
vmConfigFile := filepath.Join(wd, "./../_output/lima-template/fedora.yaml")
45+
configFileName := "macos.yaml"
46+
if runtime.GOOS == "windows" {
47+
configFileName = "windows.yaml"
48+
}
49+
vmConfigFile := filepath.Join(wd, "./../_output/lima-template/", configFileName)
4250

4351
subject := "limactl"
4452
limaOpt, err := option.New([]string{subject})
4553
if err != nil {
4654
t.Fatalf("failed to initialize a testing option: %v", err)
4755
}
4856

49-
vmName := "fedora"
57+
vmName := "finch"
58+
59+
// We run nerdctl through lima directly rather than the Finch CLI, so the
60+
// option layer must resolve valueless -e/--env/--env-file entries against the
61+
// host environment (the Finch CLI does this natively).
62+
nerdctlMods := []option.Modifier{option.WithResolveEnvVarPassthrough()}
63+
if runtime.GOOS == "windows" {
64+
nerdctlMods = append(nerdctlMods, option.WithWindowsHostPathTranslation())
65+
}
5066

5167
nerdctlOpt, err := option.New(
5268
[]string{subject, "shell", vmName, "sudo", "-E", "nerdctl"},
53-
option.WithNoEnvironmentVariablePassthrough(),
69+
nerdctlMods...,
5470
)
5571
if err != nil {
5672
t.Fatalf("failed to initialize a testing option: %v", err)
@@ -62,13 +78,49 @@ func TestE2e(t *testing.T) {
6278
vmType = "vz"
6379
}
6480

81+
var runOpt *tests.RunOption
82+
switch runtime.GOOS {
83+
case "windows":
84+
runOpt = &tests.RunOption{
85+
BaseOpt: nerdctlOpt,
86+
CGMode: tests.Hybrid,
87+
}
88+
case "darwin":
89+
runOpt = &tests.RunOption{
90+
BaseOpt: nerdctlOpt,
91+
CGMode: tests.Unified,
92+
// See https://lima-vm.io/docs/config/network/user/.
93+
DefaultHostGatewayIP: "192.168.5.2",
94+
}
95+
}
96+
6597
ginkgo.SynchronizedBeforeSuite(func() []byte {
6698
limactlStartOpts := []string{"start", vmConfigFile, "--name", vmName, "--vm-type", vmType}
6799
if vmType == "vz" {
68100
limactlStartOpts = append(limactlStartOpts, "--set", ".ssh.overVsock=false")
69101
}
70102
command.New(limaOpt, limactlStartOpts...).WithTimeoutInSeconds(600).Run()
71103
tests.SetupLocalRegistry(nerdctlOpt)
104+
105+
// Get the WSL host gateway ip using netsh. This is only available when a
106+
// WSL VM instance is running.
107+
if runtime.GOOS == "windows" {
108+
n, err := exec.Command("netsh", "interface", "ipv4", "show", "addresses", "vEthernet (WSL (Hyper-V firewall))").CombinedOutput()
109+
gomega.Expect(err).Should(gomega.BeNil(), "netsh output: %s", string(n))
110+
runOpt.DefaultHostGatewayIP = extractIPAddress(string(n))
111+
}
112+
113+
// Finch CLI rewrites `--add-host <host>:host-gateway` to the host
114+
// IP before invoking nerdctl. Our subject runs nerdctl theough lima directly, so nerdctl
115+
// will fall back to its own default (the guest's own IP).
116+
// Configure the guest's nerdctl.toml so nerdctl resolves host-gateway to the host IP.
117+
if runOpt != nil && runOpt.DefaultHostGatewayIP != "" {
118+
script := fmt.Sprintf(
119+
"mkdir -p /etc/nerdctl && printf 'host_gateway_ip = \"%s\"\\n' > /etc/nerdctl/nerdctl.toml",
120+
runOpt.DefaultHostGatewayIP,
121+
)
122+
command.New(limaOpt, "shell", vmName, "sudo", "sh", "-c", script).Run()
123+
}
72124
return nil
73125
}, func(bytes []byte) {})
74126

@@ -79,7 +131,11 @@ func TestE2e(t *testing.T) {
79131
}, func() {})
80132

81133
ginkgo.Describe(description, func() {
82-
// TODO: add more e2e tests and make them work.
134+
if runOpt != nil {
135+
tests.Run(runOpt)
136+
}
137+
tests.Ps(nerdctlOpt)
138+
tests.Restart(nerdctlOpt)
83139
tests.Save(nerdctlOpt)
84140
tests.Load(nerdctlOpt)
85141
tests.Pull(nerdctlOpt)
@@ -129,6 +185,16 @@ func TestE2e(t *testing.T) {
129185
ginkgo.RunSpecs(t, description)
130186
}
131187

188+
func extractIPAddress(data string) string {
189+
re := regexp.MustCompile(`IP Address:\s+(\d+\.\d+\.\d+\.\d+)`)
190+
match := re.FindStringSubmatch(data)
191+
192+
if match != nil {
193+
return match[1]
194+
}
195+
return ""
196+
}
197+
132198
func printLimaLogs(vmName string) {
133199
userHomeDir := os.Getenv("HOME")
134200
if userHomeDir == "" {

e2e/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ require (
2222
golang.org/x/text v0.38.0 // indirect
2323
golang.org/x/tools v0.45.0 // indirect
2424
)
25+
26+
// TODO: revert
27+
replace github.com/runfinch/common-tests => github.com/Swapnanil-Gupta/common-tests v0.0.0-20260707213946-5d083626606f

e2e/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
22
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
3+
github.com/Swapnanil-Gupta/common-tests v0.0.0-20260707213946-5d083626606f h1:qEkAm+/D2RZdT/lar1ZMJRO0Sk/FJNhsLioqtMfKYKI=
4+
github.com/Swapnanil-Gupta/common-tests v0.0.0-20260707213946-5d083626606f/go.mod h1:mOOz4glmJ0uVwjgPEXKZPgHG8BzS2KCuE+XWV0Zg4hk=
35
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
46
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
57
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
@@ -36,8 +38,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
3638
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3739
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
3840
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
39-
github.com/runfinch/common-tests v0.10.1 h1:noZ9LbolXMLTZgXllAJtNkyO6JQrrnf1mpvN1zknU40=
40-
github.com/runfinch/common-tests v0.10.1/go.mod h1:PX9VBgtcOm+2Stjm4F6Y6KpovJ2emdSJ+y1X1URnAIU=
4141
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
4242
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
4343
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=

0 commit comments

Comments
 (0)