-
Notifications
You must be signed in to change notification settings - Fork 0
165 lines (149 loc) · 6.88 KB
/
Copy pathdocker-windows.yaml
File metadata and controls
165 lines (149 loc) · 6.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
---
name: docker-windows
"on":
pull_request:
paths:
- .github/actions/free-disk-space-windows/**
- .github/workflows/docker-windows.yaml
- Dockerfile.nanoserver
- Dockerfile.windows
workflow_dispatch:
permissions:
contents: read
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
defaults:
run:
shell: bash --noprofile --norc -euo pipefail {0}
env:
MISE_ENV: dart,dotnet,java,js,python,rust,zig
jobs:
build:
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- runner: windows-2022
base: nanoserver
windows_version: ltsc2022
- runner: windows-2025
base: nanoserver
windows_version: ltsc2025
- runner: windows-2022
base: servercore
windows_version: ltsc2022
- runner: windows-2025
base: servercore
windows_version: ltsc2025
name: build (${{ matrix.runner }}, ${{ matrix.base }})
timeout-minutes: 120
env:
# Pin the mise version because the prebuilt "latest" zip is too old.
# The classic Windows builder on windows-2022 can't substitute build-args into the Dockerfile's RUN, and
# mise's prebuilt "latest" zip is stale (2026.3.0, too old for the config). 2026.6.5 is the first release
# with auto_env (loads .mise/config.windows.toml).
MISE_VERSION: "2026.6.5"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
- name: Show MISE_ENV
if: matrix.base == 'servercore'
run: echo "MISE_ENV=$MISE_ENV"
# Start the Docker daemon and confirm connectivity before building.
# Hosted Windows runners don't reliably leave the Docker daemon running, so the build can fail connecting
# to the docker_engine pipe. Start it (no-op if already running) and confirm connectivity before building.
- name: Start the Docker daemon
run: |
sc query docker | grep -q RUNNING || net start docker
docker version
- name: Free disk space on Windows runner
uses: ./.github/actions/free-disk-space-windows
with:
keep-image: mcr.microsoft.com/windows/${{ matrix.base }}:${{ matrix.windows_version }}
- name: Prepare mise and Github token for the build context
run: |
v="${{ env.MISE_VERSION }}"
curl -fsSL -o mise.zip "https://github.com/jdx/mise/releases/download/v$v/mise-v$v-windows-x64.zip"
printf '%s' "${{ github.token }}" > gh_token
# Pick which Dockerfile each matrix lane builds.
# The build is split into `build-minimal` -> diagnostics -> `precompile` so the et-rp (rustpython)
# diagnostic runs between the two stages. Both `docker build` calls share BuildKit's layer cache; the
# second one rebuilds only the layers above `build-minimal`, so the split adds the diagnostic step's
# runtime, not a second full compile.
- name: Resolve Dockerfile + image tag
id: dockerfile
run: |
case "${{ matrix.base }}" in
nanoserver) dockerfile=Dockerfile.nanoserver ;;
servercore) dockerfile=Dockerfile.windows ;;
*) echo "unknown matrix.base: ${{ matrix.base }}" >&2; exit 2 ;;
esac
tag="et-windows:${{ matrix.runner }}-${{ matrix.base }}-build-minimal"
echo "dockerfile=$dockerfile" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Build stage build-minimal
env:
DOCKERFILE: ${{ steps.dockerfile.outputs.dockerfile }}
IMAGE_TAG: ${{ steps.dockerfile.outputs.tag }}
run: |
args="-f $DOCKERFILE --build-arg MISE_ENV"
if [ "${{ matrix.runner }}" != "windows-2022" ]; then
args="$args --build-arg WINDOWS_VERSION=${{ matrix.windows_version }}"
fi
args="$args --target build-minimal -t $IMAGE_TAG"
docker build $args .
# Diagnose whether the et-rp (rustpython) binary actually runs inside this base image.
# servercore expected: works. nanoserver expected: fails with 0xc0000139 (STATUS_ENTRYPOINT_NOT_FOUND)
# when rustpython.exe tries to resolve symbols from Nano-stripped shell32/winmm/propsys. Captured here
# rather than only via the preinstall fallback so the comparison sits side-by-side in the same workflow
# run. continue-on-error so a Nano failure here doesn't pre-empt the precompile build that follows.
- name: Diagnose et-rp (rustpython) in build-minimal
continue-on-error: true
env:
IMAGE_TAG: ${{ steps.dockerfile.outputs.tag }}
run: |
echo "::group::which rustpython"
docker run --rm "$IMAGE_TAG" cmd /c "mise where http:et-rp & where rustpython"
echo "::endgroup::"
echo "::group::rustpython --version"
docker run --rm "$IMAGE_TAG" cmd /c "mise exec -- rustpython --version"
echo "::endgroup::"
echo "::group::rustpython -c hello"
docker run --rm "$IMAGE_TAG" cmd /c "mise exec -- rustpython -c \"print('et-rp ok')\""
echo "::endgroup::"
# The build target depends on the base image.
# nanoserver stops at `precompile` (no python/dotnet/test-runtime; the test stage doesn't exist there),
# servercore goes all the way through `test` so the next two steps can `docker run` the suite. Both targets
# compose with the precompile-stage layer cache from the build-minimal step above.
- name: Build stage precompile (nanoserver) / test (servercore)
env:
DOCKERFILE: ${{ steps.dockerfile.outputs.dockerfile }}
run: |
if [ "${{ matrix.base }}" = "servercore" ]; then
target=test
tag="-t et-windows-test"
else
target=precompile
tag=""
fi
args="-f $DOCKERFILE --build-arg MISE_ENV"
if [ "${{ matrix.runner }}" != "windows-2022" ]; then
args="$args --build-arg WINDOWS_VERSION=${{ matrix.windows_version }}"
fi
args="$args --target $target $tag"
docker build $args .
# Run the test suite split the same way docker-linux does.
# cargo-test-other (workspace minus et-ws-web-runner) and test-ws-web-runner (Deno-runtime gated, self-skips
# on hosts that can't satisfy it). Each runs in a fresh container so the per-phase compile target/ doesn't
# share the writable layer with the other phase. servercore-only -- Nano has no test stage.
- name: Run cargo-test-other
if: matrix.base == 'servercore'
run: docker run --rm et-windows-test mise run cargo-test-other
- name: Run test-ws-web-runner
if: matrix.base == 'servercore'
run: docker run --rm et-windows-test mise run test-ws-web-runner