-
Notifications
You must be signed in to change notification settings - Fork 405
385 lines (366 loc) · 18.2 KB
/
Copy pathbuild-onie.yml
File metadata and controls
385 lines (366 loc) · 18.2 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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
name: Build ONIE (kvm_x86_64)
# Builds the generic amd64 ONIE image for the kvm_x86_64 target, intended
# to run as a VM under KVM/QEMU. The build follows the upstream-recommended
# containerized flow (see contrib/build-env and machine/kvm_x86_64/INSTALL),
# with secure boot enabled: the workflow generates demonstration signing
# keys and self-signs the shim before building.
# Run on every push and pull request: the point of this workflow is to
# confirm the change still builds, and the kvm_x86_64 image depends on far
# more than the build files (installer/, rootconf/, patches/, ...), so path
# filtering would risk skipping validation on build-affecting changes.
on:
workflow_dispatch:
inputs:
oce_scope:
description: >-
OCE compliance test scope: "default" (a fast representative
subset, also what push/PR runs) or "full" (the entire OCE
installer+updater sweep, tests 3-121 -- slow, many VM boots).
type: choice
default: default
options:
- default
- full
push:
pull_request:
# Cancel an in-progress run when a newer commit is pushed to the same ref,
# so stacked pushes don't pile up concurrent builds.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build kvm_x86_64
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# The GCC 14 / Debian 13 toolchain build plus the full image (restored
# x-tools cache + every package + kernel + recovery ISO) exceeds the
# ~14 GB free on a stock ubuntu-latest runner. Reclaim ~25 GB of
# preinstalled toolchains we do not use so the build has headroom.
- name: Free up runner disk space
run: |
echo "Disk before cleanup:"; df -h /
sudo rm -rf /usr/local/lib/android /opt/hostedtoolcache /usr/share/dotnet \
/usr/local/.ghcup /usr/share/swift /usr/local/share/powershell \
/usr/local/lib/node_modules || true
echo "Disk after cleanup:"; df -h /
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Determine host UID/GID
id: ids
run: |
echo "uid=$(id -u)" >> "$GITHUB_OUTPUT"
echo "gid=$(id -g)" >> "$GITHUB_OUTPUT"
- name: Build the ONIE build-environment image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .github/onie-build
tags: onie-build-env:latest
build-args: |
UID=${{ steps.ids.outputs.uid }}
GID=${{ steps.ids.outputs.gid }}
load: true
cache-from: type=gha
cache-to: type=gha,mode=max
# Cache the crosstool-NG cross toolchain -- the long pole of a cold
# build. We cache the whole stamp chain (so make does not rebuild on a
# missing root stamp) but only the parts the warm, no-op path actually
# needs -- NOT the multi-GB crosstool-NG build scratch or ct-ng source
# tree, which are only used while building the toolchain. On a cache
# hit "make xtools" is a no-op and the real build only uses the
# installed toolchain, so dropping the scratch keeps the cache blob
# small and fast/reliable to restore.
#
# build/stamp-project -- top-of-chain project stamp
# build/download -- toolchain tarballs + download stamps
# build/crosstool-ng/stamp -- crosstool-NG build stamps
# build/x-tools/*/stamp -- xtools build stamps
# build/x-tools/*/install -- the installed cross toolchain
# build/x-tools/*/build/.config -- xtools config (an xtools-build prereq)
#
# The key is tied to every input that can change the toolchain --
# including the Dockerfile, since it defines the compiler/host
# environment the toolchain is built in. No loose restore-keys: any
# input change forces a clean rebuild rather than restoring a
# mismatched toolchain.
- name: Restore cross-toolchain cache
id: xtools-cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
build/stamp-project
build/download
build/crosstool-ng/stamp
build/x-tools/*/stamp
build/x-tools/*/install
build/x-tools/*/build/.config
key: onie-xtools-kvm_x86_64-${{ hashFiles('build-config/make/xtools.make', 'build-config/make/crosstool-ng.make', 'build-config/make/compiler.make', 'build-config/conf/crosstool/**', 'patches/crosstool-NG/**', '.github/onie-build/Dockerfile') }}
# ONIE drives its build with stamp files compared by mtime. A fresh
# checkout gives every repo source file a current mtime, which is newer
# than the restored stamps -- so make would consider the toolchain
# stale and rebuild it (e.g. build/.../.config depends on the
# checked-out conf/crosstool config). A cache hit means the key
# matched, i.e. every toolchain input is unchanged and the restored
# toolchain is valid, so bump the restored artifacts ahead of the
# checkout to make "make xtools" a genuine no-op.
- name: Mark restored toolchain up to date
if: steps.xtools-cache.outputs.cache-hit == 'true'
# Restoring build/stamp-project makes make skip the project-stamp
# recipe, which is what normally creates the project output dirs --
# so recreate them (build/images is an output, not part of the
# cache, and the kernel install copies vmlinuz into it).
#
# Then touch only the files make compares -- the stamp files and the
# toolchain .config. Do NOT touch the toolchain tree itself: it
# contains read-only binaries and symlinks to host tools (bash,
# make, ...) that touch would follow and fail to update.
#
# Touch them all to ONE identical timestamp (-t), not "now" per file.
# The xtools build stamp depends on .config (xtools.make), and a bare
# `find -exec touch {} +` batches files across calls that can straddle a
# one-second boundary -- leaving .config (touched last) newer than the
# build stamp. make then re-runs `ct-ng build`, which fails because the
# ct-ng binary is intentionally not in the cache. Equal mtimes mean no
# cached target is ever "newer-than" a cached prerequisite, so `make
# xtools` is a reliable no-op; the timestamp is "now" (after checkout),
# so it's also newer than the just-checked-out toolchain config sources.
run: |
mkdir -p build build/images build/download
ts="$(date +%Y%m%d%H%M.%S)"
find build/stamp-project build/download \
build/crosstool-ng/stamp \
build/x-tools/*/stamp \
build/x-tools/*/build/.config \
-type f -exec touch -t "$ts" {} +
- name: Build cross toolchain
run: |
docker run --rm --privileged \
-v "${PWD}:/onie" \
onie-build-env \
bash -lc 'cd build-config && make -j"$(nproc)" \
MACHINE=kvm_x86_64 \
xtools'
# Save only on a cache miss, and only after the toolchain build above
# succeeded (default if: success()), so a broken toolchain is never
# cached. Running before the full build means a later-stage failure
# still preserves the toolchain for the next run.
- name: Save cross-toolchain cache
if: steps.xtools-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
build/stamp-project
build/download
build/crosstool-ng/stamp
build/x-tools/*/stamp
build/x-tools/*/install
build/x-tools/*/build/.config
key: ${{ steps.xtools-cache.outputs.cache-primary-key }}
- name: Build ONIE
run: |
docker run --rm --privileged \
-v "${PWD}:/onie" \
onie-build-env \
bash -lc 'cd build-config && \
make MACHINE=kvm_x86_64 signing-keys-generate && \
make MACHINE=kvm_x86_64 shim-self-sign && \
make -j"$(nproc)" MACHINE=kvm_x86_64 all recovery-iso demo'
- name: Upload kvm recovery image
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-kvm-recovery-iso
path: build/images/onie-recovery-x86_64-kvm_x86_64-r0.iso
retention-days: 7
# The demonstration PK/KEK/db that signed this build's shim/grub/kernel.
# The boot-test job enrolls them into an OVMF varstore to validate the
# secure-boot signature chain. These are the SAME keys this run signed
# with, so the enrolled db matches the shipped image (regenerating would
# not). Demo keys only -- non-sensitive (see machine-security.make).
- name: Upload secure-boot demo keys
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-kvm-sb-keys
# Exclude the gpg-agent sockets that signing-keys-generate leaves in
# the gpg-keys dirs -- upload-artifact can't zip sockets and warns
# ENTRYNOTSUPPORTED; only the .pem/.der key material is needed.
path: |
encryption/machines/kvm_x86_64/keys
!encryption/machines/kvm_x86_64/keys/**/S.gpg-agent*
retention-days: 7
# Artifacts for the install-test job: the recovery kernel/initrd (booted
# directly in install mode), the ONIE updater (to embed ONIE on a blank
# disk first), and the demo OS installer (the NOS discovery installs).
- name: Upload install-test images
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-kvm-install-images
path: |
build/images/kvm_x86_64-r0.vmlinuz
build/images/kvm_x86_64-r0.initrd
build/images/onie-updater-x86_64-kvm_x86_64-r0
build/images/demo-installer-x86_64-kvm_x86_64-r0.bin
retention-days: 7
# Boot the built recovery ISO headlessly under QEMU+OVMF and assert ONIE gets
# past GRUB into the OS (serial-console milestones, no kernel panic). ONIE is
# serial end-to-end (GRUB+kernel+userspace on ttyS0) so a serial capture
# suffices -- no screen scraping/OCR. See emulation/ci-boot-test.sh.
boot-test:
name: Boot test kvm_x86_64
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Enable KVM (grant /dev/kvm access)
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Install QEMU + OVMF
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
qemu-system-x86 qemu-utils ovmf python3-virt-firmware
- name: Download kvm recovery image
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: onie-kvm-recovery-iso
path: build/images
- name: Download secure-boot demo keys
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: onie-kvm-sb-keys
path: encryption/machines/kvm_x86_64/keys
# SB-relaxed smoke: plain OVMF on the default 'pc' machine -- proves the
# image boots past GRUB into the OS independent of the SB signature chain.
- name: Boot ONIE (SB-relaxed) and assert it reaches the OS
run: |
SERIAL_LOG="$PWD/onie-boot-serial.log" BOOT_MODE=relaxed \
emulation/ci-boot-test.sh \
build/images/onie-recovery-x86_64-kvm_x86_64-r0.iso 300
# SB-enforced: enroll the demo PK/KEK/db, boot the secboot OVMF on
# q35,smm=on, and assert the shim/grub/kernel chain verifies (plus a
# negative control with db omitted that MUST be rejected). This is the
# signal that catches a broken signing chain in the grub/shim/kernel
# modernization PRs even when the image otherwise builds and boots.
- name: Boot ONIE (SB-enforced) and assert the signing chain verifies
run: |
SERIAL_LOG="$PWD/onie-boot-serial-secureboot.log" BOOT_MODE=secureboot \
KEYS_DIR="$PWD/encryption/machines/kvm_x86_64/keys" \
emulation/ci-boot-test.sh \
build/images/onie-recovery-x86_64-kvm_x86_64-r0.iso 300
- name: Upload serial logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-boot-serial-log
path: onie-boot-serial*.log
retention-days: 7
# Functional discovery-install: prove ONIE actually installs an OS and boots
# it, not just that it reaches rescue. Embed ONIE onto a blank disk, then in
# install mode point discovery (install_url=) at the locally-served demo
# installer, install it, and boot the resulting demo OS -- all headless via
# the serial console. This exercises the real installer path (download,
# exec_installer, the NOS writing GRUB + the OS to disk, the OS booting) that
# the boot-smoke jobs do not. Runs Secure-Boot-relaxed (legacy BIOS) -- the
# signing chain is covered by boot-test. See emulation/ci-install-test.sh.
install-test:
name: Install test kvm_x86_64
# Chained after boot-test (not parallel) so only one VM-heavy job runs at a
# time, keeping CI resource use low.
needs: boot-test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Enable KVM (grant /dev/kvm access)
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Install QEMU
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends qemu-system-x86 qemu-utils
- name: Download install-test images
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: onie-kvm-install-images
path: build/images
- name: Install demo OS via discovery and boot it
run: |
SERIAL_PREFIX="$PWD/onie-install" \
emulation/ci-install-test.sh \
build/images/kvm_x86_64-r0.vmlinuz \
build/images/kvm_x86_64-r0.initrd \
build/images/demo-installer-x86_64-kvm_x86_64-r0.bin 600
- name: Upload install serial logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-install-serial-log
path: onie-install-*.log
retention-days: 7
# Run ONIE's own OCE (ONIE Compliance Environment, contrib/oce) compliance
# suite against the image. Where install-test hands ONIE the installer URL
# directly (install_url=), OCE exercises the REAL OCP discovery path: it
# stands up isc-dhcp-server advertising the ONIE VIVSO vendor option (DHCP
# option 125) plus an nginx HTTP server, and ONIE must DHCP, read the VIVSO
# installer URL, and fetch+install the image itself. OCE needs L2 to the DUT
# (it validates the DUT shares the host interface's subnet), so the VM is on a
# tap interface rather than user-mode SLIRP. contrib/oce is python3 (it was
# ported in the python2-to-3 PR this is stacked on). See
# emulation/ci-oce-test.sh.
oce-test:
name: OCE compliance kvm_x86_64
# Chained after install-test (not parallel) so only one VM-heavy job runs
# at a time, keeping CI resource use low.
needs: install-test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Enable KVM (grant /dev/kvm access)
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Install QEMU + OCE service backends + python deps
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
qemu-system-x86 qemu-utils isc-dhcp-server nginx-light tftpd-hpa \
dnsmasq dosfstools python3-venv
python3 -m venv /tmp/oce-venv
/tmp/oce-venv/bin/pip install --quiet jinja2 netifaces psutil
- name: Download install-test images
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: onie-kvm-install-images
path: build/images
- name: Run OCE compliance test (full install/update via OCP discovery)
run: |
# On push/PR (no dispatch input) run the fast "default" subset; a
# human can manually dispatch this workflow with oce_scope=full to
# run the entire OCE installer+updater sweep.
SCOPE="${{ inputs.oce_scope }}"
[ -z "$SCOPE" ] && SCOPE=default
OCE_PYTHON=/tmp/oce-venv/bin/python SERIAL_PREFIX="$PWD/onie-oce" \
emulation/ci-oce-test.sh \
build/images/kvm_x86_64-r0.vmlinuz \
build/images/kvm_x86_64-r0.initrd \
build/images/demo-installer-x86_64-kvm_x86_64-r0.bin \
build/images/onie-updater-x86_64-kvm_x86_64-r0 \
"$SCOPE"
- name: Upload OCE serial logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: onie-oce-serial-log
path: onie-oce-*.log
retention-days: 7