Skip to content

Commit a53efec

Browse files
cgwaltershenrywang
authored andcommitted
ci: Split RPM building into separate job
This splits the RPM package building into a separate CI job that runs before the integration tests. The built packages are then downloaded and used by the integration test jobs, avoiding redundant builds. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters <[email protected]>
1 parent f687add commit a53efec

File tree

5 files changed

+98
-17
lines changed

5 files changed

+98
-17
lines changed

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,7 @@
2121
# Workaround for podman bug with secrets + remote
2222
# https://github.com/containers/podman/issues/25314
2323
!podman-build-secret*
24+
# Pre-built packages for builds that use them
25+
!target/packages/
2426
# And finally of course all the Rust sources
2527
!crates/

.github/workflows/ci.yml

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,40 @@ jobs:
114114
uses: ./.github/actions/bootc-ubuntu-setup
115115
- name: Build mdbook
116116
run: just build-mdbook
117+
# Build packages for each test OS
118+
package:
119+
strategy:
120+
fail-fast: false
121+
matrix:
122+
test_os: [fedora-42, fedora-43, centos-9, centos-10]
123+
124+
runs-on: ubuntu-24.04
125+
126+
steps:
127+
- uses: actions/checkout@v6
128+
- name: Bootc Ubuntu Setup
129+
uses: ./.github/actions/bootc-ubuntu-setup
130+
131+
- name: Setup env
132+
run: |
133+
BASE=$(just pullspec-for-os ${{ matrix.test_os }})
134+
echo "BOOTC_base=${BASE}" >> $GITHUB_ENV
135+
136+
- name: Build packages
137+
run: just package
138+
139+
- name: Upload package artifacts
140+
uses: actions/upload-artifact@v5
141+
with:
142+
name: packages-${{ matrix.test_os }}
143+
path: target/packages/*.rpm
144+
retention-days: 1
145+
117146
# Build bootc from source into a container image FROM each specified base `test_os`
118147
# running unit and integration tests (using TMT, leveraging the support for nested virtualization
119148
# in the GHA runners)
120149
test-integration:
150+
needs: package
121151
strategy:
122152
fail-fast: false
123153
matrix:
@@ -139,9 +169,15 @@ jobs:
139169
BASE=$(just pullspec-for-os base ${{ matrix.test_os }})
140170
echo "BOOTC_base=${BASE}" >> $GITHUB_ENV
141171
172+
- name: Download package artifacts
173+
uses: actions/download-artifact@v5
174+
with:
175+
name: packages-${{ matrix.test_os }}
176+
path: target/packages/
177+
142178
- name: Build container
143179
run: |
144-
just build-integration-test-image
180+
just build-integration-test-image-from-package target/packages
145181
# Extra cross-check (duplicating the integration test) that we're using the right base
146182
used_vid=$(podman run --rm localhost/bootc-integration bash -c '. /usr/lib/os-release && echo ${ID}-${VERSION_ID}')
147183
test ${{ matrix.test_os }} = "${used_vid}"
@@ -176,6 +212,7 @@ jobs:
176212
# This variant does composefs testing
177213
test-integration-cfs:
178214
continue-on-error: ${{ matrix.experimental }}
215+
needs: package
179216
strategy:
180217
fail-fast: false
181218
matrix:
@@ -208,12 +245,15 @@ jobs:
208245
echo "BOOTC_buildroot_base=${BUILDROOTBASE}" >> $GITHUB_ENV
209246
echo "BOOTC_variant="${{ matrix.variant }} >> $GITHUB_ENV
210247
248+
- name: Download package artifacts
249+
uses: actions/download-artifact@v5
250+
with:
251+
name: packages-${{ matrix.test_os }}
252+
path: target/packages/
253+
211254
- name: Build container
212255
run: |
213-
just build-integration-test-image
214-
# Extra cross-check (duplicating the integration test) that we're using the right base
215-
used_vid=$(podman run --rm localhost/bootc-integration bash -c '. /usr/lib/os-release && echo ${ID}-${VERSION_ID}')
216-
test ${{ matrix.test_os }} = "${used_vid}"
256+
just build-integration-test-image-from-package target/packages
217257
218258
- name: Unit and container integration tests
219259
run: just test-container
@@ -246,12 +286,13 @@ jobs:
246286
# Sentinel job for required checks - configure this job name in repository settings
247287
required-checks:
248288
if: always()
249-
needs: [cargo-deny, validate, test-integration, test-integration-cfs]
289+
needs: [cargo-deny, validate, package, test-integration, test-integration-cfs]
250290
runs-on: ubuntu-latest
251291
steps:
252292
- run: exit 1
253293
if: >-
254294
needs.cargo-deny.result != 'success' ||
255295
needs.validate.result != 'success' ||
296+
needs.package.result != 'success' ||
256297
needs.test-integration.result != 'success' ||
257298
needs.test-integration-cfs.result != 'success'

Dockerfile

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ COPY . /src
1515
FROM scratch as packaging
1616
COPY contrib/packaging /
1717

18+
# This image captures pre-built packages from the context.
19+
# By COPYing into a stage, we avoid SELinux issues with context bind mounts.
20+
FROM scratch as packages
21+
COPY target/packages/*.rpm /
22+
1823
FROM $base as base
1924
# Mark this as a test image (moved from --label build flag to fix layer caching)
2025
LABEL bootc.testimage="1"
@@ -63,10 +68,11 @@ ARG rootfs=
6368
RUN --mount=type=bind,from=packaging,target=/run/packaging /run/packaging/configure-rootfs "${variant}" "${rootfs}"
6469
# Inject additional content
6570
COPY --from=packaging /usr-extras/ /usr/
66-
# Install the RPM built in the build stage
67-
# This replaces the manual file deletion hack and COPY, ensuring proper package management
68-
# Use rpm -Uvh with --oldpackage to allow replacing with dev version
69-
COPY --from=build /out/*.rpm /tmp/
70-
RUN --mount=type=bind,from=packaging,target=/run/packaging --network=none /run/packaging/install-rpm-and-setup /tmp
71+
# Install packages from the packages stage
72+
# Using bind from a stage avoids SELinux issues with context bind mounts
73+
RUN --mount=type=bind,from=packaging,target=/run/packaging \
74+
--mount=type=bind,from=packages,target=/build-packages \
75+
--network=none \
76+
/run/packaging/install-rpm-and-setup /build-packages
7177
# Finally, testour own linting
7278
RUN bootc container lint --fatal-warnings

Justfile

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ buildargs := "--build-arg=base=" + base + " --build-arg=variant=" + variant
3939
# Build the container image from current sources.
4040
# Note commonly you might want to override the base image via e.g.
4141
# `just build --build-arg=base=quay.io/fedora/fedora-bootc:42`
42-
build:
42+
build: package
43+
podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} .
44+
./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}}
45+
46+
# Build the container image using pre-existing packages from PATH
47+
build-from-package PATH:
48+
@just copy-packages-from {{PATH}}
4349
podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} .
4450
./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}}
4551

@@ -64,12 +70,30 @@ _packagecontainer:
6470
echo "Building RPM with version: ${VERSION}"
6571
podman build {{base_buildargs}} {{buildargs}} --build-arg=pkgversion=${VERSION} -t localhost/bootc-pkg --target=build .
6672

67-
# Build a packages (e.g. RPM) into target/
73+
# Build packages (e.g. RPM) into target/packages/
6874
# Any old packages will be removed.
6975
package: _packagecontainer
70-
mkdir -p target
71-
rm -vf target/*.rpm
72-
podman run --rm localhost/bootc-pkg tar -C /out/ -cf - . | tar -C target/ -xvf -
76+
mkdir -p target/packages
77+
rm -vf target/packages/*.rpm
78+
podman run --rm localhost/bootc-pkg tar -C /out/ -cf - . | tar -C target/packages/ -xvf -
79+
chmod a+rx target target/packages
80+
chmod a+r target/packages/*.rpm
81+
podman rmi localhost/bootc-pkg
82+
83+
# Copy pre-existing packages from PATH into target/packages/
84+
# Used to prepare for building with pre-built packages
85+
copy-packages-from PATH:
86+
#!/bin/bash
87+
set -xeuo pipefail
88+
if ! compgen -G "{{PATH}}/*.rpm" > /dev/null; then
89+
echo "Error: No packages found in {{PATH}}" >&2
90+
exit 1
91+
fi
92+
mkdir -p target/packages
93+
rm -vf target/packages/*.rpm
94+
cp -v {{PATH}}/*.rpm target/packages/
95+
chmod a+rx target target/packages
96+
chmod a+r target/packages/*.rpm
7397

7498
# This container image has additional testing content and utilities
7599
build-integration-test-image: build
@@ -78,6 +102,14 @@ build-integration-test-image: build
78102
# Keep these in sync with what's used in hack/lbi
79103
podman pull -q --retry 5 --retry-delay 5s quay.io/curl/curl:latest quay.io/curl/curl-base:latest registry.access.redhat.com/ubi9/podman:latest
80104

105+
# Build integration test image using pre-existing packages from PATH
106+
build-integration-test-image-from-package PATH:
107+
@just build-from-package {{PATH}}
108+
cd hack && podman build {{base_buildargs}} -t {{integration_img}}-bin -f Containerfile .
109+
./tests/build-sealed {{variant}} {{integration_img}}-bin {{integration_img}}
110+
# Keep these in sync with what's used in hack/lbi
111+
podman pull -q --retry 5 --retry-delay 5s quay.io/curl/curl:latest quay.io/curl/curl-base:latest registry.access.redhat.com/ubi9/podman:latest
112+
81113
# Build+test using the `composefs-sealeduki-sdboot` variant.
82114
test-composefs:
83115
# These first two are currently a distinct test suite from tmt that directly

contrib/packaging/install-rpm-and-setup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ RPM_DIR="${1:-/tmp}"
77
# Install the RPM package
88
# Use rpm -Uvh with --oldpackage to allow replacing with dev version
99
rpm -Uvh --oldpackage "${RPM_DIR}"/*.rpm
10-
rm -f "${RPM_DIR}"/*.rpm
10+
# Note: we don't need to clean up the source directory since it's a bind mount
1111

1212
# Regenerate initramfs if we have initramfs-setup
1313
kver=$(cd /usr/lib/modules && echo *)

0 commit comments

Comments
 (0)