-
Notifications
You must be signed in to change notification settings - Fork 9
264 lines (263 loc) · 11.9 KB
/
Copy pathmatrix.yml
File metadata and controls
264 lines (263 loc) · 11.9 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
name: Build Kernel Matrix
on:
workflow_call:
inputs:
spec:
description: 'Build Specification'
type: string
default: "new"
required: true
publish:
description: 'Publish Builds'
type: boolean
default: true
required: true
# Publishing runs share one group so two of them can't race on the same image
# tags. Non-publishing runs only need to be keyed by PR/ref.
concurrency:
group: ${{ inputs.publish && 'kernel-builder-publish' || format('kernel-builder-{0}', github.event.pull_request.number || github.ref) }}
jobs:
matrix:
name: matrix
runs-on:
group: Self Hosted
labels: edera-24
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
with:
egress-policy: audit
- name: Install the latest version of uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.14"
- name: Setup Crane
uses: imjasonh/setup-crane@v0.7
- name: checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
submodules: recursive
- name: install dependencies
run: uv sync
- name: generate matrix
run: './hack/build/generate-matrix.sh "${{ inputs.spec }}"'
- name: upload matrix
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: matrix
path: "matrix.json"
compression-level: 0
- name: capture matrix
id: capture-matrix
run: |
# Split matrix.json into two strategy-matrix-shaped outputs: one keyed
# on `builds` (per-arch build jobs) and one on `merges` (per
# (version, flavor) manifest-list assembly jobs). Each iteration of the
# build job sees matrix.builds.* and each merge sees matrix.merges.*.
BUILDS=$(jq -c '{builds: .builds}' matrix.json)
MERGES=$(jq -c '{merges: .merges}' matrix.json)
echo "builds=${BUILDS}" >> "${GITHUB_OUTPUT}"
echo "merges=${MERGES}" >> "${GITHUB_OUTPUT}"
outputs:
builds: "${{ steps.capture-matrix.outputs.builds }}"
merges: "${{ steps.capture-matrix.outputs.merges }}"
build:
name: "build ${{ matrix.builds.version }} ${{ matrix.builds.flavor }} ${{ matrix.builds.arch }}"
needs: matrix
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.builds) }}
runs-on: "${{ matrix.builds.runner }}"
env:
KERNEL_PUBLISH: "${{ inputs.publish }}"
KERNEL_VERSION: "${{ matrix.builds.version }}"
KERNEL_SRC_URL: "${{ matrix.builds.source }}"
FIRMWARE_URL: "${{ matrix.builds.firmware_url }}"
FIRMWARE_SIG_URL: "${{ matrix.builds.firmware_sig_url }}"
KERNEL_FLAVOR: "${{ matrix.builds.flavor }}"
KERNEL_TAGS: "${{ join(matrix.builds.tags, ',') }}"
KERNEL_ARCH: "${{ matrix.builds.arch }}"
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
with:
egress-policy: audit
- name: report disk space (before)
uses: edera-dev/actions/report-disk-space@6e6996f6fff5d6016bcdc097e9065da6fb33ac7f # v0.0.17
- name: reclaim runner disk space
# Kernel builds never touch Rust or the hosted toolcache, so both
# opt-in removals are on. Must stay before cosign-installer, which
# installs into the toolcache this deletes.
uses: edera-dev/actions/reclaim-disk-space@6e6996f6fff5d6016bcdc097e9065da6fb33ac7f # v0.0.17
with:
remove-toolcache: 'true'
remove-rust: 'true'
- name: checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
submodules: recursive
- name: install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: prepare scratch dir
# Some runner generations carry a secondary temp disk at /mnt; its
# size varies by VM SKU and is not reliably documented, so route the
# build trees there only when it is a distinct filesystem with more
# free space than the root disk. The device check comes first:
# comparing two df readings of the same filesystem can differ by a
# few KiB of measurement jitter and must not trigger the redirect.
# sudo because /mnt is root-owned while docker.sh and the
# in-container build user both run unprivileged.
run: |
ROOT_DEV="$(stat -c %d /)"
MNT_DEV="$(stat -c %d /mnt 2>/dev/null || echo "${ROOT_DEV}")"
if [ "${MNT_DEV}" = "${ROOT_DEV}" ]; then
echo "/mnt is not a distinct filesystem; keeping build trees on /"
exit 0
fi
ROOT_AVAIL="$(df --output=avail -k / | tail -1 | tr -d ' ')"
MNT_AVAIL="$(df --output=avail -k /mnt | tail -1 | tr -d ' ')"
if [ "${MNT_AVAIL}" -gt "${ROOT_AVAIL}" ]; then
sudo mkdir -p /mnt/kernel-scratch
sudo chmod a+rwX /mnt/kernel-scratch
echo "KERNEL_SCRATCH_DIR=/mnt/kernel-scratch" >> "${GITHUB_ENV}"
echo "using /mnt scratch (${MNT_AVAIL}K avail vs ${ROOT_AVAIL}K on /)"
else
echo "keeping build trees on / (${ROOT_AVAIL}K avail vs ${MNT_AVAIL}K on /mnt)"
fi
# - name: docker setup linux-kernel-oci
# run: sudo uv run ./hack/build/docker-setup.py
- name: docker setup buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: docker login ghcr.io
uses: Wandalen/wretry.action@e68c23e6309f2871ca8ae4763e7629b9c258e1ea # v3.8.0
with:
action: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: |
registry: ghcr.io
username: "${{github.actor}}"
password: "${{secrets.GITHUB_TOKEN}}"
- name: configure sccache
# Exports SCCACHE_AZURE_{RW_MODE,BLOB_CONTAINER,KEY_PREFIX} via
# GITHUB_ENV; the connection string is bound below on the one step
# that runs the build. All four names must match the -e passthrough
# list in hack/build/generate-docker-script.py (docker_compile); a
# name missing there silently never reaches the build container.
id: sccache
uses: edera-dev/actions/configure-azure-sccache@6e6996f6fff5d6016bcdc097e9065da6fb33ac7f # v0.0.17
with:
connection-string-rw: ${{ secrets.SCCACHE_AZURE_CONNECTION_STRING }}
connection-string-ro: ${{ secrets.SCCACHE_AZURE_CONNECTION_STRING_RO }}
key-prefix: kernel
- name: Install the latest version of uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: "3.14"
- name: generate docker script
run: "./hack/build/generate-docker-script.sh"
- name: upload docker script
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: "build-${{ matrix.builds.version }}-${{ matrix.builds.flavor }}-${{ matrix.builds.arch }}.sh"
path: "docker.sh"
compression-level: 0
- name: run docker script
env:
SCCACHE_AZURE_CONNECTION_STRING: ${{ steps.sccache.outputs.connection-string }}
run: sh -x docker.sh
- name: report disk space (after)
# always() so ENOSPC failures still show where the disk went.
if: always()
uses: edera-dev/actions/report-disk-space@6e6996f6fff5d6016bcdc097e9065da6fb33ac7f # v0.0.17
- name: upload digests
# Only produced when publishing — push-by-digest path writes digests.json.
if: ${{ inputs.publish }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: "digests-${{ matrix.builds.version }}-${{ matrix.builds.flavor }}-${{ matrix.builds.arch }}"
path: "digests.json"
if-no-files-found: error
compression-level: 0
retention-days: 1
merge:
# Stitch the per-arch single-platform pushes from `build` into multi-arch
# manifest lists. Only runs when publishing; no-op when nothing was pushed.
name: "merge ${{ matrix.merges.version }} ${{ matrix.merges.flavor }}"
needs: [matrix, build]
if: ${{ inputs.publish && needs.matrix.outputs.merges != '' }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.matrix.outputs.merges) }}
runs-on:
group: Self Hosted
labels: edera-24
env:
KERNEL_PUBLISH: "${{ inputs.publish }}"
KERNEL_VERSION: "${{ matrix.merges.version }}"
KERNEL_FLAVOR: "${{ matrix.merges.flavor }}"
KERNEL_PRODUCES: "${{ join(matrix.merges.produces, ',') }}"
KERNEL_SRC_URL: "${{ matrix.merges.source }}"
FIRMWARE_URL: "${{ matrix.merges.firmware_url }}"
DIGESTS_DIR: digests
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1
with:
egress-policy: audit
- name: checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
- name: Install the latest version of uv
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
with:
python-version: '3.14'
- name: install python deps
run: uv sync
- name: install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: docker setup buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: docker login ghcr.io
uses: Wandalen/wretry.action@e68c23e6309f2871ca8ae4763e7629b9c258e1ea # v3.8.0
with:
action: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with: |
registry: ghcr.io
username: "${{github.actor}}"
password: "${{secrets.GITHUB_TOKEN}}"
- name: download digest artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
# Each per-arch build uploads its digests under a uniquely-named
# artifact; pattern + default merge-multiple=false drops each artifact
# into its own subdirectory under digests/.
pattern: "digests-${{ matrix.merges.version }}-${{ matrix.merges.flavor }}-*"
path: digests
- name: generate merge script
run: uv run ./hack/build/generate-merge-script.py
- name: upload merge script
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: "merge-${{ matrix.merges.version }}-${{ matrix.merges.flavor }}.sh"
path: "merge.sh"
compression-level: 0
- name: run merge script
run: sh -x merge.sh
- name: generate and attest CycloneDX SBOM
env:
COSIGN_EXPERIMENTAL: "true"
run: |
set -euo pipefail
uv run hack/build/generate-sbom.py
jq -e '.bomFormat == "CycloneDX" and ((.components // []) | length > 0)' \
sbom.cdx.json >/dev/null \
|| { echo "::error::kernel SBOM is empty or invalid"; exit 1; }
# Attest the SBOM to each published manifest (kernel + SDK)
attested=""
IFS=',' read -ra refs <<< "${KERNEL_PRODUCES}"
for ref in "${refs[@]}"; do
[ -n "${ref}" ] || continue
image="${ref%:*}"
case " ${attested} " in *" ${image} "*) continue ;; esac
attested="${attested} ${image}"
echo "attesting SBOM to ${ref}"
cosign attest --yes --type cyclonedx --predicate sbom.cdx.json "${ref}"
done