-
Notifications
You must be signed in to change notification settings - Fork 0
283 lines (274 loc) · 11.3 KB
/
Copy pathci.yml
File metadata and controls
283 lines (274 loc) · 11.3 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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
name: ci
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
# Force JavaScript-based actions onto Node.js 24 ahead of the
# 2026-06-02 default flip; silences the Node 20 deprecation banner.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25"
cache: true
- uses: golangci/golangci-lint-action@v9
with:
# Pinned exact (not v2.5). Keep in sync with Makefile
# GOLANGCI_LINT_VERSION.
version: v2.5.0
test-linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
go: ["1.25", "1.26"]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
cache: true
- run: go vet ./...
- run: go test -race -count=1 ./...
# Apple-container backend lives in runtime/applecontainer and is
# darwin/arm64-only (see build tags). This job builds the Swift
# bridge and runs the Go test suite on macOS so we get coverage of
# cgo compilation, go:embed of libACBridge.dylib, and the
# daemon-free unit tests. Daemon-dependent tests skip cleanly via
# runtimeOrSkip when Apple's `container` apiserver isn't running.
test-darwin:
runs-on: macos-26
strategy:
fail-fast: false
matrix:
go: ["1.25", "1.26"]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
cache: true
- name: Select Xcode with Swift 6.2
# apple/container 0.12.3 declares swift-tools-version 6.2;
# the macos-15 image ships an older Xcode by default. Pick
# the newest installed so SwiftPM can resolve the package.
run: sudo xcode-select -s /Applications/Xcode_latest.app || sudo xcode-select -s "$(ls -d /Applications/Xcode_*.app | sort -V | tail -1)"
- name: Cache SwiftPM artifacts
uses: actions/cache@v5
with:
path: |
applecontainer-bridge/.build
~/Library/Caches/org.swift.swiftpm
# Key on Package.resolved so the cache busts when dependency
# versions move. Bump the `v1` prefix to force a full miss
# after a toolchain change that breaks artifact compat.
key: swiftpm-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('applecontainer-bridge/Package.resolved') }}
restore-keys: |
swiftpm-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Build Swift bridge
run: make bridge
- run: go vet ./...
- run: go test -race -count=1 ./...
test-integration-linux:
runs-on: ubuntu-latest
needs: [lint, test-linux]
strategy:
fail-fast: false
matrix:
go: ["1.25", "1.26"]
shard: [1, 2, 3]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
cache: true
- name: Verify Docker available
run: |
docker version
docker compose version
- name: Run integration tests (shard ${{ matrix.shard }}/3)
env:
SHARD_INDEX: ${{ matrix.shard }}
SHARD_TOTAL: 3
run: |
# Enumerate tests under the integration tag, partition them
# deterministically by sorted-index modulo SHARD_TOTAL, and
# run only this shard's subset. Apple-container tests are
# build-tagged darwin/arm64, so they don't appear here.
set -euo pipefail
tests=$(go test -tags=integration -list '.*' ./test/integration/... \
| grep -E '^Test' | sort -u)
if [ -z "$tests" ]; then
echo "no integration tests discovered" >&2
exit 1
fi
selected=$(echo "$tests" | awk -v s="$SHARD_INDEX" -v t="$SHARD_TOTAL" \
'{ if ((NR - 1) % t == (s - 1)) print }')
echo "Shard ${SHARD_INDEX}/${SHARD_TOTAL} will run:"
echo "$selected"
pattern="^($(echo "$selected" | paste -sd '|' -))$"
go test -race -count=1 -tags=integration -timeout=15m \
-run "$pattern" ./test/integration/...
# Real Podman + CRIU checkpoint/restore. The runtime/podman backend and
# the Engine checkpoint/restore + project-orchestrator paths only execute
# against a live Podman socket with CRIU (PODMAN_SOCKET-gated). The
# cross-node test (TestPodmanXNode_*) needs two hosts, so it skips here
# (no DCCKPT_XNODE_DIR) — run it on two machines by hand.
#
# Why a container: the hosted runner's apt podman is unusable (24.04 has
# no criu; 22.04's podman 3.4.4 can't checkpoint and predates the libpod
# v5 API). So we build the gated tests on the runner (compile coverage,
# static CGO_ENABLED=0 so they run on Fedora), then run them INSIDE a
# modern-podman container (podman 5.x + crun + criu) that's privileged +
# --cgroupns=host so CRIU can drive the runner's kernel. The script
# smoke-tests an actual checkpoint first and skips green (with the real
# reason) if this runner can't — e.g. nested cgroup-freezer perms — so a
# capable runner runs for real while an incapable one stays green.
test-integration-podman:
runs-on: ubuntu-latest
needs: [lint, test-linux]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: "1.25"
cache: true
- name: Build gated test binaries (static; compile coverage + run in container)
env:
CGO_ENABLED: "0"
run: |
go test -tags=integration -c ./test/integration -o ./int.test
go test -c ./runtime/podman -o ./podman.test
- name: Checkpoint/restore in a modern-podman privileged container
run: |
docker run --rm --privileged --cgroupns=host \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
--security-opt label=disable \
-v "$PWD":/w -w /w \
quay.io/podman/stable bash /w/.github/scripts/podman-cr.sh
# Integration tests against a live Apple `container` daemon.
#
# Verified-on-CI status:
# - pkg install : OK on macos-15 and macos-26
# - system start : OK
# - kernel set : OK
# - builder start : FAILS on both macos-15 and macos-26 with
# "VZErrorDomain Code=2 Virtualization is not available on
# this hardware."
#
# i.e. GitHub-hosted macOS runners do not expose
# Virtualization.framework for Linux guests, regardless of image
# version. Apple's `container` runtime is hardcoded to VZ (no QEMU
# fallback like Colima/Lima), so there is no workaround at the
# workflow level. The only paths to a passing job today are:
# 1. Self-hosted macOS runner with virtualization entitlements
# 2. GH exposing VZ on hosted runners (no announced timeline)
#
# continue-on-error keeps the failure visible without blocking
# merges. Drop it once a real green run is available.
test-integration-darwin:
runs-on: macos-26
needs: [test-darwin]
strategy:
fail-fast: false
matrix:
go: ["1.25", "1.26"]
shard: [1, 2, 3]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go }}
cache: true
- name: Install apple/container
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# `gh release download` authenticates with GH_TOKEN, dodging
# the strict anonymous rate limit on api.github.com that
# bit us when curling the unauth'd releases endpoint.
gh release download --repo apple/container \
--pattern '*installer-signed.pkg' \
--output /tmp/container.pkg
sudo installer -pkg /tmp/container.pkg -target /
container --version
- name: Select Xcode with Swift 6.2
# apple/container 0.12.3 declares swift-tools-version 6.2;
# the macos-15 image ships an older Xcode by default. Pick
# the newest installed so SwiftPM can resolve the package.
run: sudo xcode-select -s /Applications/Xcode_latest.app || sudo xcode-select -s "$(ls -d /Applications/Xcode_*.app | sort -V | tail -1)"
- name: Cache SwiftPM artifacts
uses: actions/cache@v5
with:
path: |
applecontainer-bridge/.build
~/Library/Caches/org.swift.swiftpm
key: swiftpm-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('applecontainer-bridge/Package.resolved') }}
restore-keys: |
swiftpm-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Build Swift bridge
run: make bridge
- name: Start container apiserver
run: |
# --disable-kernel-install skips the interactive kernel prompt
# that would otherwise hang in CI; we install the recommended
# kernel explicitly in the next step.
container system start --disable-kernel-install
container system status
- name: Install default kernel
# The builder (and any container) needs a configured kernel.
# `--recommended` pulls Apple's recommended binary
# non-interactively, which `--disable-kernel-install` skipped.
run: container system kernel set --recommended
- name: Start builder
id: builder
# On GH-hosted macOS runners VZ is unavailable, so this step
# always fails. Mark it continue-on-error so the JOB stays
# green (continue-on-error at job level wouldn't — that only
# affects workflow status, not the per-job check). The next
# step gates on this step's outcome so we don't run the
# integration tests against a missing daemon.
continue-on-error: true
run: container builder start
- name: Run apple-container integration tests (shard ${{ matrix.shard }}/3)
if: steps.builder.outcome == 'success'
env:
SHARD_INDEX: ${{ matrix.shard }}
SHARD_TOTAL: 3
run: |
# Filter to TestAppleContainer_* — the docker-backed tests
# share the `integration` build tag and would fail without a
# Docker daemon on this runner. Then partition that subset
# across shards.
set -euo pipefail
tests=$(go test -tags=integration -list '^TestAppleContainer_' ./test/integration/... \
| grep -E '^TestAppleContainer_' | sort -u)
if [ -z "$tests" ]; then
echo "no apple-container integration tests discovered" >&2
exit 1
fi
selected=$(echo "$tests" | awk -v s="$SHARD_INDEX" -v t="$SHARD_TOTAL" \
'{ if ((NR - 1) % t == (s - 1)) print }')
echo "Shard ${SHARD_INDEX}/${SHARD_TOTAL} will run:"
echo "$selected"
if [ -z "$selected" ]; then
echo "shard is empty; nothing to run"
exit 0
fi
pattern="^($(echo "$selected" | paste -sd '|' -))$"
go test -race -count=1 -tags=integration -timeout=15m \
-run "$pattern" ./test/integration/...
- name: Stop container services
if: always()
run: |
container builder stop || true
container system stop || true