Skip to content

Commit 11e1b52

Browse files
committed
Merge branch 'pipelines' of ssh://forgejo.local:2222/ben/hypervisor
2 parents 074992e + 10be4cb commit 11e1b52

5 files changed

Lines changed: 608 additions & 1 deletion

File tree

Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
name: Build Hypervisor Bootc Images
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Build Fedora Minimal Bootc"]
6+
types: [completed]
7+
branches: [main]
8+
9+
workflow_dispatch:
10+
inputs:
11+
variants:
12+
description: 'Variants to build (besides base)'
13+
required: true
14+
default: 'all'
15+
type: choice
16+
options:
17+
- 'all'
18+
- 'none'
19+
- 'amd'
20+
- 'nvidia'
21+
- 'nvidia-negativo17'
22+
- 'nvidia-rpmfusion'
23+
versions_override:
24+
description: 'JSON array of Fedora versions to build, e.g. [44] (empty = use fedora-versions.yml)'
25+
required: false
26+
default: ''
27+
type: string
28+
29+
concurrency:
30+
group: build-hypervisor-${{ github.ref }}
31+
cancel-in-progress: false
32+
33+
env:
34+
# Plain-HTTP registry shared with the justfile (registry.local:5000).
35+
REGISTRY: registry.local:5000
36+
37+
jobs:
38+
setup:
39+
runs-on: native
40+
outputs:
41+
versions: ${{ steps.r.outputs.versions }}
42+
stable: ${{ steps.r.outputs.stable }}
43+
rechunker: ${{ steps.r.outputs.rechunker }}
44+
steps:
45+
- uses: actions/checkout@v4
46+
- id: r
47+
run: |
48+
command -v yq >/dev/null || sudo dnf install -y yq
49+
if [ -n "${{ inputs.versions_override }}" ]; then
50+
echo "versions=${{ inputs.versions_override }}"
51+
else
52+
echo "versions=$(yq -o=json -I=0 '.supported' fedora-versions.yml)"
53+
fi >> "$GITHUB_OUTPUT"
54+
{
55+
echo "stable=$(yq '.stable' fedora-versions.yml)"
56+
echo "rechunker=$(yq '.rechunker' fedora-versions.yml)"
57+
} >> "$GITHUB_OUTPUT"
58+
59+
build-base:
60+
needs: setup
61+
# Skip if the upstream minimal build failed; allow all other triggers.
62+
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
63+
runs-on: native
64+
timeout-minutes: 120
65+
strategy:
66+
fail-fast: false
67+
matrix:
68+
fedora_version: ${{ fromJson(needs.setup.outputs.versions) }}
69+
outputs:
70+
tag: ${{ steps.params.outputs.tag }}
71+
72+
steps:
73+
- name: Checkout repository
74+
uses: actions/checkout@v4
75+
76+
- name: Resolve build parameters
77+
id: params
78+
run: |
79+
TAG=$(date +%Y%m%d-%H%M)
80+
{
81+
echo "tag=${TAG}"
82+
echo "image_base=${REGISTRY}/hypervisor-bootc"
83+
} >> "$GITHUB_OUTPUT"
84+
85+
- name: Install cosign
86+
run: |
87+
if ! command -v cosign >/dev/null; then
88+
sudo curl -fsSL \
89+
https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 \
90+
-o /usr/local/bin/cosign
91+
sudo chmod +x /usr/local/bin/cosign
92+
fi
93+
cosign version
94+
95+
- name: Render policy.json
96+
run: |
97+
sed -e "s|__REGISTRY_NAMESPACE__|bensmith|g" \
98+
policy-hypervisor.json.template > policy.json
99+
cat policy.json
100+
101+
- name: Fetch cosy
102+
run: |
103+
mkdir -p bin man
104+
curl -fsSL https://raw.githubusercontent.com/BenSmith/cosy/main/cosy -o bin/cosy
105+
curl -fsSL https://raw.githubusercontent.com/BenSmith/cosy/main/cosy.1 -o man/cosy.1
106+
107+
- name: Build base hypervisor
108+
env:
109+
VERSION: ${{ matrix.fedora_version }}
110+
run: |
111+
sudo podman build \
112+
--pull=always \
113+
--tls-verify=false \
114+
--security-opt=label=disable \
115+
--security-opt=seccomp=unconfined \
116+
--cap-add=all \
117+
--ipc=host \
118+
--build-arg BASE_IMAGE=${REGISTRY}/fedora-bootc-minimal:${VERSION} \
119+
-f hypervisor.Containerfile \
120+
-t localhost/hypervisor-bootc:build \
121+
.
122+
123+
- name: Rechunk base image
124+
env:
125+
RECHUNKER: ${{ needs.setup.outputs.rechunker }}
126+
run: |
127+
sudo podman run --rm --privileged \
128+
-v /var/lib/containers:/var/lib/containers \
129+
quay.io/fedora/fedora-bootc:${RECHUNKER} \
130+
/usr/libexec/bootc-base-imagectl rechunk \
131+
localhost/hypervisor-bootc:build \
132+
localhost/hypervisor-bootc:rechunked
133+
134+
- name: Tag and push base
135+
id: push_base
136+
env:
137+
IMAGE_BASE: ${{ steps.params.outputs.image_base }}
138+
VERSION: ${{ matrix.fedora_version }}
139+
TAG: ${{ steps.params.outputs.tag }}
140+
STABLE: ${{ needs.setup.outputs.stable }}
141+
run: |
142+
VERSIONED="${VERSION}-${TAG}"
143+
FLOATING="${VERSION}"
144+
145+
sudo podman tag localhost/hypervisor-bootc:rechunked "${IMAGE_BASE}:${VERSIONED}"
146+
sudo podman push --tls-verify=false \
147+
--digestfile /tmp/digest.txt "${IMAGE_BASE}:${VERSIONED}"
148+
DIGEST=$(cat /tmp/digest.txt)
149+
150+
sudo skopeo copy --src-tls-verify=false --dest-tls-verify=false \
151+
"docker://${IMAGE_BASE}@${DIGEST}" "docker://${IMAGE_BASE}:${FLOATING}"
152+
if [ "${VERSION}" = "${STABLE}" ]; then
153+
sudo skopeo copy --src-tls-verify=false --dest-tls-verify=false \
154+
"docker://${IMAGE_BASE}@${DIGEST}" "docker://${IMAGE_BASE}:latest"
155+
fi
156+
157+
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"
158+
159+
- name: Sign base
160+
# Best-effort: sign if a key is configured and cosign succeeds,
161+
# but never fail the build over signing.
162+
continue-on-error: true
163+
env:
164+
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_SECRET }}
165+
IMAGE_BASE: ${{ steps.params.outputs.image_base }}
166+
DIGEST: ${{ steps.push_base.outputs.digest }}
167+
run: |
168+
if [ -z "${COSIGN_PRIVATE_KEY:-}" ]; then
169+
echo "COSIGN_SECRET not set — skipping image signing."
170+
exit 0
171+
fi
172+
cosign sign -y \
173+
--key env://COSIGN_PRIVATE_KEY \
174+
--tlog-upload=false \
175+
--allow-http-registry \
176+
--allow-insecure-registry \
177+
"${IMAGE_BASE}@${DIGEST}"
178+
179+
- name: Summary
180+
env:
181+
IMAGE_BASE: ${{ steps.params.outputs.image_base }}
182+
VERSION: ${{ matrix.fedora_version }}
183+
TAG: ${{ steps.params.outputs.tag }}
184+
STABLE: ${{ needs.setup.outputs.stable }}
185+
run: |
186+
{
187+
echo "## Base hypervisor build complete (F${VERSION})"
188+
echo ""
189+
echo "- \`${IMAGE_BASE}:${VERSION}-${TAG}\`"
190+
echo "- \`${IMAGE_BASE}:${VERSION}\`"
191+
if [ "${VERSION}" = "${STABLE}" ]; then
192+
echo "- \`${IMAGE_BASE}:latest\`"
193+
fi
194+
} >> "$GITHUB_STEP_SUMMARY"
195+
196+
build-variant:
197+
needs: [setup, build-base]
198+
runs-on: native
199+
timeout-minutes: 120
200+
201+
strategy:
202+
fail-fast: false
203+
matrix:
204+
variant:
205+
- name: amd
206+
image: hypervisor-amd
207+
containerfile: hypervisor-amd.Containerfile
208+
prefix: ''
209+
floating: ''
210+
- name: nvidia-negativo17
211+
image: hypervisor-nvidia
212+
containerfile: hypervisor-nvidia-negativo17.Containerfile
213+
prefix: 'negativo17-'
214+
floating: 'negativo17'
215+
- name: nvidia-rpmfusion
216+
image: hypervisor-nvidia
217+
containerfile: hypervisor-nvidia-rpmfusion.Containerfile
218+
prefix: 'rpmfusion-'
219+
floating: 'rpmfusion'
220+
fedora_version: ${{ fromJson(needs.setup.outputs.versions) }}
221+
222+
steps:
223+
- name: Decide whether to build this variant
224+
id: gate
225+
env:
226+
SELECTION: ${{ inputs.variants }}
227+
EVENT: ${{ github.event_name }}
228+
NAME: ${{ matrix.variant.name }}
229+
run: |
230+
# workflow_run and schedule always build all variants.
231+
# workflow_dispatch respects the user's selection.
232+
if [ "$EVENT" != "workflow_dispatch" ] || [ "$SELECTION" = "all" ]; then
233+
BUILD=true
234+
elif [ "$SELECTION" = "none" ]; then
235+
BUILD=false
236+
elif [ "$SELECTION" = "nvidia" ] && [[ "$NAME" == nvidia-* ]]; then
237+
BUILD=true
238+
elif [ "$SELECTION" = "$NAME" ]; then
239+
BUILD=true
240+
else
241+
BUILD=false
242+
fi
243+
echo "build=${BUILD}" >> "$GITHUB_OUTPUT"
244+
245+
- name: Checkout repository
246+
if: steps.gate.outputs.build == 'true'
247+
uses: actions/checkout@v4
248+
249+
- name: Render policy.json
250+
if: steps.gate.outputs.build == 'true'
251+
run: |
252+
sed -e "s|__REGISTRY_NAMESPACE__|bensmith|g" \
253+
policy-hypervisor.json.template > policy.json
254+
255+
- name: Install cosign
256+
if: steps.gate.outputs.build == 'true'
257+
run: |
258+
if ! command -v cosign >/dev/null; then
259+
sudo curl -fsSL \
260+
https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 \
261+
-o /usr/local/bin/cosign
262+
sudo chmod +x /usr/local/bin/cosign
263+
fi
264+
cosign version
265+
266+
- name: Fetch cosy
267+
if: steps.gate.outputs.build == 'true'
268+
run: |
269+
mkdir -p bin man
270+
curl -fsSL https://raw.githubusercontent.com/BenSmith/cosy/main/cosy -o bin/cosy
271+
curl -fsSL https://raw.githubusercontent.com/BenSmith/cosy/main/cosy.1 -o man/cosy.1
272+
273+
- name: Build variant
274+
if: steps.gate.outputs.build == 'true'
275+
env:
276+
IMAGE: ${{ matrix.variant.image }}
277+
CONTAINERFILE: ${{ matrix.variant.containerfile }}
278+
VERSION: ${{ matrix.fedora_version }}
279+
run: |
280+
sudo podman build \
281+
--pull=always \
282+
--tls-verify=false \
283+
--security-opt=label=disable \
284+
--security-opt=seccomp=unconfined \
285+
--cap-add=all \
286+
--ipc=host \
287+
--build-arg BASE=${REGISTRY}/hypervisor-bootc:${VERSION} \
288+
-f "${CONTAINERFILE}" \
289+
-t "localhost/${IMAGE}:build" \
290+
.
291+
292+
- name: Rechunk variant
293+
if: steps.gate.outputs.build == 'true'
294+
env:
295+
IMAGE: ${{ matrix.variant.image }}
296+
RECHUNKER: ${{ needs.setup.outputs.rechunker }}
297+
run: |
298+
sudo podman run --rm --privileged \
299+
-v /var/lib/containers:/var/lib/containers \
300+
quay.io/fedora/fedora-bootc:${RECHUNKER} \
301+
/usr/libexec/bootc-base-imagectl rechunk \
302+
"localhost/${IMAGE}:build" \
303+
"localhost/${IMAGE}:rechunked"
304+
305+
- name: Tag and push variant
306+
if: steps.gate.outputs.build == 'true'
307+
id: push
308+
env:
309+
BASE_TAG: ${{ needs.build-base.outputs.tag }}
310+
IMAGE: ${{ matrix.variant.image }}
311+
PREFIX: ${{ matrix.variant.prefix }}
312+
FLOATING: ${{ matrix.variant.floating }}
313+
VERSION: ${{ matrix.fedora_version }}
314+
STABLE: ${{ needs.setup.outputs.stable }}
315+
run: |
316+
IMAGE_BASE="${REGISTRY}/${IMAGE}"
317+
VERSIONED="${PREFIX}${VERSION}-${BASE_TAG}"
318+
FLOATING_TAG="${PREFIX}${VERSION}"
319+
320+
sudo podman tag "localhost/${IMAGE}:rechunked" "${IMAGE_BASE}:${VERSIONED}"
321+
sudo podman push --tls-verify=false \
322+
--digestfile /tmp/digest.txt "${IMAGE_BASE}:${VERSIONED}"
323+
DIGEST=$(cat /tmp/digest.txt)
324+
325+
sudo skopeo copy --src-tls-verify=false --dest-tls-verify=false \
326+
"docker://${IMAGE_BASE}@${DIGEST}" "docker://${IMAGE_BASE}:${FLOATING_TAG}"
327+
328+
if [ "${VERSION}" = "${STABLE}" ]; then
329+
STABLE_FLOATING="${FLOATING:-latest}"
330+
sudo skopeo copy --src-tls-verify=false --dest-tls-verify=false \
331+
"docker://${IMAGE_BASE}@${DIGEST}" "docker://${IMAGE_BASE}:${STABLE_FLOATING}"
332+
fi
333+
334+
{
335+
echo "image_base=${IMAGE_BASE}"
336+
echo "versioned_tag=${VERSIONED}"
337+
echo "floating_tag=${FLOATING_TAG}"
338+
echo "digest=${DIGEST}"
339+
} >> "$GITHUB_OUTPUT"
340+
341+
- name: Sign variant
342+
# Best-effort: sign if a key is configured and cosign succeeds,
343+
# but never fail the build over signing.
344+
if: steps.gate.outputs.build == 'true'
345+
continue-on-error: true
346+
env:
347+
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_SECRET }}
348+
IMAGE_BASE: ${{ steps.push.outputs.image_base }}
349+
DIGEST: ${{ steps.push.outputs.digest }}
350+
run: |
351+
if [ -z "${COSIGN_PRIVATE_KEY:-}" ]; then
352+
echo "COSIGN_SECRET not set — skipping image signing."
353+
exit 0
354+
fi
355+
cosign sign -y \
356+
--key env://COSIGN_PRIVATE_KEY \
357+
--tlog-upload=false \
358+
--allow-http-registry \
359+
--allow-insecure-registry \
360+
"${IMAGE_BASE}@${DIGEST}"
361+
362+
- name: Summary
363+
if: steps.gate.outputs.build == 'true'
364+
env:
365+
NAME: ${{ matrix.variant.name }}
366+
IMAGE_BASE: ${{ steps.push.outputs.image_base }}
367+
VERSIONED_TAG: ${{ steps.push.outputs.versioned_tag }}
368+
FLOATING_TAG: ${{ steps.push.outputs.floating_tag }}
369+
run: |
370+
{
371+
echo "## Variant ${NAME} (F${{ matrix.fedora_version }}) complete"
372+
echo ""
373+
echo "- \`${IMAGE_BASE}:${VERSIONED_TAG}\`"
374+
echo "- \`${IMAGE_BASE}:${FLOATING_TAG}\`"
375+
} >> "$GITHUB_STEP_SUMMARY"

0 commit comments

Comments
 (0)