33The offline Lua hook tests (` tests/hooks_test.lua ` ) run in the ** Test Plugin**
44workflow. The end-to-end suite runs in containers against real vfox on Linux
55and Windows; each ` vfox ` x ` mirror ` combination gets its own throwaway
6- container.
6+ container. On Linux, CI runs the suite natively on the stock runners (Docker
7+ plus Go from ` actions/setup-go ` ), the way the repository dev container
8+ reproduces it locally. On Windows it runs through a Docker Compose runner
9+ image, since dev containers cannot host Windows container images (see below).
10+
11+ ## Dev container
12+
13+ ` .devcontainer/ ` opens a Linux development environment that works on all four
14+ host platforms:
15+
16+ | Host | How the dev container runs |
17+ | --------------------- | ---------------------------------------------- |
18+ | Linux amd64 / arm64 | natively |
19+ | Windows amd64 / arm64 | Docker Desktop in Linux-container mode (WSL 2) |
20+
21+ It carries Go 1.27.1 (the version CI installs), the Docker CLI, stylua,
22+ lua-language-server, and the license tools — all pinned to the versions in
23+ ` .github/workflows/lint.yml ` and ` license.yml ` — and mounts the host Docker
24+ daemon socket. The suites then run testcontainers against that daemon
25+ (Docker-out-of-Docker), spawning the same target containers a native CI
26+ runner spawns; this is deliberately not Docker-in-Docker, so image cache and
27+ networking stay the host's. The image needs no workspace files, so the build
28+ context stays at ` .devcontainer/ ` ; ` postCreateCommand ` warms the Go module
29+ cache for ` tests/e2e ` so the first test run does not stop to download.
30+
31+ Open it with any Dev Containers spec tool — ** Dev Containers: Reopen in
32+ Container** in VS Code/Cursor, or the CLI:
33+
34+ ``` bash
35+ devcontainer up --workspace-folder .
36+ devcontainer exec --workspace-folder . bash
37+ ```
38+
39+ ` TESTCONTAINERS_RYUK_DISABLED=true ` is preset: Ryuk publishes a port on the
40+ host daemon and waits for the suite to dial it back, which a
41+ Docker-out-of-Docker container cannot do. The suites terminate every
42+ container explicitly via ` t.Cleanup ` instead; leftovers from killed runs
43+ share the ` vfox-nodejs-e2e- ` name prefix for pruning. Rootless Docker users
44+ export ` DOCKER_SOCK="$XDG_RUNTIME_DIR/docker.sock" ` on the host before
45+ opening the container. On Windows hosts, keeping the checkout inside WSL 2
46+ (e.g. under ` \\wsl$ ` ) keeps file and bind-mount access fast; a checkout on
47+ the Windows filesystem works too.
48+
49+ Windows * container* coverage (` tests/e2e/windows ` ) cannot run in a dev
50+ container: the Dev Containers spec does not support Windows container images
51+ ([ vscode-remote-release #445 ] ( https://github.com/microsoft/vscode-remote-release/issues/445 ) ),
52+ and Windows containers only run on a Windows daemon. That suite keeps its
53+ Docker Compose runner on a Windows host; see [ Windows 11] ( #windows-11 ) below.
754
855## What the suite verifies
956
@@ -62,55 +109,59 @@ pin `VFOX_VERSION` and `MIRROR` explicitly to widen or narrow the matrix.
62109| ` E2E_RETRY_ATTEMPTS ` | ` 3 ` | Attempts per network-touching exec (linear 10s backoff) |
63110| ` E2E_LINUX_BASE ` | ` ubuntu ` | Linux userland: ` ubuntu ` (glibc) or ` alpine ` (musl, see docs/musl.md) |
64111
65- ## Ubuntu
66-
67- Only Docker Engine (in either rootful or rootless mode) is required on the
68- host. ARM64 runs the default mirror only.
112+ ## Linux (Ubuntu)
69113
70- ### rootful Docker
71-
72- Execute in Bash,
114+ Inside the dev container, from the repository root:
73115
74116``` bash
75- sudo apt install --assume-yes git
76- git clone git@github.com:version-fox/vfox-nodejs.git
77- cd ./vfox-nodejs/
78- docker compose -f tests/e2e/linux/compose.yaml run --rm e2e
117+ cd tests/e2e
118+ go test -v -timeout 55m -run TestE2E ./linux
79119```
80120
81- ### rootless Docker
82-
83- With rootless Docker the daemon socket lives elsewhere; point ` DOCKER_SOCK `
84- at it instead:
121+ Scope it down while iterating the same way:
85122
86123``` bash
87- sudo apt install --assume-yes git
88- git clone git@github.com:version-fox/vfox-nodejs.git
89- cd ./vfox-nodejs/
90- DOCKER_SOCK=" $XDG_RUNTIME_DIR /docker.sock" docker compose -f tests/e2e/linux/compose.yaml run --rm e2e
124+ VFOX_VERSION=latest MIRROR=default E2E_MAX_JOBS=1 go test -v -timeout 55m -run TestE2E ./linux
91125```
92126
127+ On a native host the same command works with two prerequisites — Docker
128+ Engine (rootful or rootless) and Go 1.27.1 — which is exactly what CI
129+ provisions. Rootless Docker users point the Docker client at their socket
130+ (` export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock" ` ); the dev
131+ container's socket mount covers that case for you. ARM64 runs the default
132+ mirror only.
133+
93134## Alpine (musl)
94135
95- Same host requirement. The Alpine suite builds
96- ` tests/e2e/linux/Dockerfile-alpine ` (musl userland with ` libstdc++ ` ) and
97- asserts the musl userland before running the standard flow, proving the
98- plugin selects the ` *-musl ` tarballs
136+ The Alpine suite builds ` tests/e2e/linux/Dockerfile-alpine ` (musl userland
137+ with ` libstdc++ ` ) and asserts the musl userland before running the standard
138+ flow, proving the plugin selects the ` *-musl ` tarballs
99139([ issue #29 ] ( https://github.com/version-fox/vfox-nodejs/issues/29 ) ).
100140See [ docs/musl.md] ( musl.md ) for the tarball matrix.
101141
142+ Set ` E2E_LINUX_BASE ` to switch the same Linux suite onto the Alpine image:
143+
102144``` bash
103- docker compose -f tests/e2e/linux/compose.alpine.yaml run --rm e2e
145+ cd tests/e2e
146+ E2E_LINUX_BASE=alpine go test -v -timeout 55m -run TestE2E ./linux
104147```
105148
106- Scope it down locally the same way, e.g.
107- ` VFOX_VERSION=latest MIRROR=default E2E_MAX_JOBS=1 ` in front of the command .
149+ CI exports the same variable in its musl job; the dev container needs
150+ nothing else .
108151
109- ## Windows 11 Pro
152+ ## Windows 11
110153
111154Windows containers cannot be emulated across architectures, so the ARM64
112155suite needs an ARM64 host (a Copilot+ PC or the ` windows-11-arm ` CI runner).
113156
157+ There is no dev container for this suite — the Dev Containers spec rejects
158+ Windows container images (see [ Dev container] ( #dev-container ) ) — so it keeps
159+ its Docker Compose runner. The runner image (` Dockerfile-runner ` : stock
160+ servercore plus the pinned Go MSI) drives the host daemon through the mounted
161+ named pipe; the host requirement is Docker in Windows-container mode plus the
162+ Compose v5 plugin (installed once per machine below). Go never touches the
163+ host, so it cannot conflict with a vfox-managed toolchain.
164+
114165The ` windows-11-arm ` runner has no Windows Hypervisor Platform feature, so
115166Hyper-V isolation is unavailable; process isolation needs only the
116167Containers feature.
@@ -191,6 +242,12 @@ curl.exe -fsSL `
191242docker compose -f tests/e2e/windows/compose.arm64.yaml run --rm --build e2e
192243```
193244
245+ On arm64, Go is also what builds the engine, so ` install-docker-arm64.ps1 `
246+ runs before the suite; the compose runner image then carries its own pinned
247+ Go for the tests, and the host Go is not used again. Scope the run down with
248+ ` $env:VFOX_VERSION = 'latest'; $env:MIRROR = 'default' ` in front of the
249+ compose command, as on the other platforms.
250+
194251## WSL
195252
196253The WSL suite (` tests/e2e/wsl/ ` ) drives the Ubuntu distribution on the
@@ -208,6 +265,9 @@ Combos share one distro and run sequentially, each isolated in
208265its own ` HOME ` /` VFOX_HOME ` slot. ` MIRROR ` defaults apply as usual; CI pins
209266` MIRROR=default ` to keep the run to the ` latest ` /` main ` vfox channels.
210267
268+ It runs from the Windows host (it needs ` wsl.exe ` and the installed distro),
269+ not from the dev container.
270+
211271### CI
212272
213273The ` WSL (windows-2025) ` job installs ` Ubuntu-24.04 ` with
@@ -231,14 +291,11 @@ go test -v -timeout 55m -run TestE2E ./wsl
231291
232292## Local checks
233293
234- Execute in Bash on Ubuntu before pushing.
294+ Execute from the dev container — everything below is preinstalled and pinned
295+ to the versions the workflows use — or provision the same tools on a host.
235296
236297``` bash
237- docker run --rm -v " $PWD :/work" -w /work apache/skywalking-eyes:0.9.0 header check
238- docker run --rm -v " $PWD :/work" -w /work apache/skywalking-eyes:0.9.0 header fix
239- docker run --rm -v " $PWD :/src" ghcr.io/google/addlicense:v1.2.0 -check -f .license.tpl tests/e2e/windows/* .ps1
240- docker run --rm -v " $PWD :/src" ghcr.io/google/addlicense:v1.2.0 -f .license.tpl tests/e2e/windows/* .ps1
241-
298+ # Lua and Go checks (.github/workflows/lint.yml).
242299cd tests/e2e
243300go test -short ./...
244301test -z " $( gofmt -l .) "
@@ -248,5 +305,23 @@ cd ../..
248305go run github.com/yuin/gopher-lua/cmd/glua@v1.1.1 tests/hooks_test.lua
249306
250307stylua --check .
251- mise x aqua:LuaLS/lua-language-server@3.19.1 -- lua-language-server --check . --checklevel=Warning
308+ lua-language-server --check . --checklevel=Warning
309+ ```
310+
311+ ``` bash
312+ # License headers (.github/workflows/license.yml).
313+ license-eye header check
314+ license-eye header fix
315+ addlicense -check -f .license.tpl tests/e2e/windows/* .ps1
316+ addlicense -f .license.tpl tests/e2e/windows/* .ps1
317+ ```
318+
319+ On a Docker-only host the license checks run as containers instead (the same
320+ images CI uses):
321+
322+ ``` bash
323+ docker run --rm -v " $PWD :/work" -w /work apache/skywalking-eyes:0.9.0 header check
324+ docker run --rm -v " $PWD :/work" -w /work apache/skywalking-eyes:0.9.0 header fix
325+ docker run --rm -v " $PWD :/src" ghcr.io/google/addlicense:v1.2.0 -check -f .license.tpl tests/e2e/windows/* .ps1
326+ docker run --rm -v " $PWD :/src" ghcr.io/google/addlicense:v1.2.0 -f .license.tpl tests/e2e/windows/* .ps1
252327```
0 commit comments