From 54284f841a6caac9d1ef204a4bc50d299057672f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 26 Nov 2025 10:00:33 -0500 Subject: [PATCH] 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 --- .dockerignore | 2 ++ .github/workflows/ci.yml | 44 ++++++++++++++++++++++--- Dockerfile | 16 ++++++--- Justfile | 42 ++++++++++++++++++++--- contrib/packaging/install-rpm-and-setup | 2 +- 5 files changed, 90 insertions(+), 16 deletions(-) diff --git a/.dockerignore b/.dockerignore index 1f557997..07e97375 100644 --- a/.dockerignore +++ b/.dockerignore @@ -21,5 +21,7 @@ # Workaround for podman bug with secrets + remote # https://github.com/containers/podman/issues/25314 !podman-build-secret* +# Pre-built packages for builds that use them +!target/packages/ # And finally of course all the Rust sources !crates/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 063e62e2..61f98f60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,10 +113,40 @@ jobs: uses: ./.github/actions/bootc-ubuntu-setup - name: Build mdbook run: just build-mdbook + # Build packages for each test OS + package: + strategy: + fail-fast: false + matrix: + test_os: [fedora-42, fedora-43, fedora-44, centos-9, centos-10] + + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v6 + - name: Bootc Ubuntu Setup + uses: ./.github/actions/bootc-ubuntu-setup + + - name: Setup env + run: | + BASE=$(just pullspec-for-os ${{ matrix.test_os }}) + echo "BOOTC_base=${BASE}" >> $GITHUB_ENV + + - name: Build packages + run: just package + + - name: Upload package artifacts + uses: actions/upload-artifact@v5 + with: + name: packages-${{ matrix.test_os }} + path: target/packages/*.rpm + retention-days: 1 + # Build bootc from source into a container image FROM each specified base `test_os` # running unit and integration tests (using TMT, leveraging the support for nested virtualization # in the GHA runners) test-integration: + needs: package strategy: fail-fast: false matrix: @@ -149,12 +179,15 @@ jobs: echo "BOOTC_buildroot_base=${BUILDROOTBASE}" >> $GITHUB_ENV fi + - name: Download package artifacts + uses: actions/download-artifact@v5 + with: + name: packages-${{ matrix.test_os }} + path: target/packages/ + - name: Build container run: | - just build-integration-test-image - # Extra cross-check (duplicating the integration test) that we're using the right base - used_vid=$(podman run --rm localhost/bootc-integration bash -c '. /usr/lib/os-release && echo ${ID}-${VERSION_ID}') - test ${{ matrix.test_os }} = "${used_vid}" + just build-integration-test-image-from-package target/packages - name: Unit and container integration tests run: just test-container @@ -177,11 +210,12 @@ jobs: # Sentinel job for required checks - configure this job name in repository settings required-checks: if: always() - needs: [cargo-deny, validate, test-integration] + needs: [cargo-deny, validate, package, test-integration] runs-on: ubuntu-latest steps: - run: exit 1 if: >- needs.cargo-deny.result != 'success' || needs.validate.result != 'success' || + needs.package.result != 'success' || needs.test-integration.result != 'success' diff --git a/Dockerfile b/Dockerfile index d849c3ed..d881cfab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,11 @@ COPY . /src FROM scratch as packaging COPY contrib/packaging / +# This image captures pre-built packages from the context. +# By COPYing into a stage, we avoid SELinux issues with context bind mounts. +FROM scratch as packages +COPY target/packages/*.rpm / + FROM $base as base # Mark this as a test image (moved from --label build flag to fix layer caching) LABEL bootc.testimage="1" @@ -63,10 +68,11 @@ ARG rootfs= RUN --mount=type=bind,from=packaging,target=/run/packaging /run/packaging/configure-rootfs "${variant}" "${rootfs}" # Inject additional content COPY --from=packaging /usr-extras/ /usr/ -# Install the RPM built in the build stage -# This replaces the manual file deletion hack and COPY, ensuring proper package management -# Use rpm -Uvh with --oldpackage to allow replacing with dev version -COPY --from=build /out/*.rpm /tmp/ -RUN --mount=type=bind,from=packaging,target=/run/packaging --network=none /run/packaging/install-rpm-and-setup /tmp +# Install packages from the packages stage +# Using bind from a stage avoids SELinux issues with context bind mounts +RUN --mount=type=bind,from=packaging,target=/run/packaging \ + --mount=type=bind,from=packages,target=/build-packages \ + --network=none \ + /run/packaging/install-rpm-and-setup /build-packages # Finally, testour own linting RUN bootc container lint --fatal-warnings diff --git a/Justfile b/Justfile index df999244..2959374b 100644 --- a/Justfile +++ b/Justfile @@ -40,7 +40,13 @@ buildargs := "--build-arg=base=" + base + " --build-arg=variant=" + variant # Build the container image from current sources. # Note commonly you might want to override the base image via e.g. # `just build --build-arg=base=quay.io/fedora/fedora-bootc:42` -build: +build: package + podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} . + ./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}} + +# Build the container image using pre-existing packages from PATH +build-from-package PATH: + @just copy-packages-from {{PATH}} podman build {{base_buildargs}} -t {{base_img}}-bin {{buildargs}} . ./tests/build-sealed {{variant}} {{base_img}}-bin {{base_img}} {{buildroot_base}} @@ -65,12 +71,30 @@ _packagecontainer: echo "Building RPM with version: ${VERSION}" podman build {{base_buildargs}} {{buildargs}} --build-arg=pkgversion=${VERSION} -t localhost/bootc-pkg --target=build . -# Build a packages (e.g. RPM) into target/ +# Build packages (e.g. RPM) into target/packages/ # Any old packages will be removed. package: _packagecontainer - mkdir -p target - rm -vf target/*.rpm - podman run --rm localhost/bootc-pkg tar -C /out/ -cf - . | tar -C target/ -xvf - + mkdir -p target/packages + rm -vf target/packages/*.rpm + podman run --rm localhost/bootc-pkg tar -C /out/ -cf - . | tar -C target/packages/ -xvf - + chmod a+rx target target/packages + chmod a+r target/packages/*.rpm + podman rmi localhost/bootc-pkg + +# Copy pre-existing packages from PATH into target/packages/ +# Used to prepare for building with pre-built packages +copy-packages-from PATH: + #!/bin/bash + set -xeuo pipefail + if ! compgen -G "{{PATH}}/*.rpm" > /dev/null; then + echo "Error: No packages found in {{PATH}}" >&2 + exit 1 + fi + mkdir -p target/packages + rm -vf target/packages/*.rpm + cp -v {{PATH}}/*.rpm target/packages/ + chmod a+rx target target/packages + chmod a+r target/packages/*.rpm # This container image has additional testing content and utilities build-integration-test-image: build @@ -79,6 +103,14 @@ build-integration-test-image: build # Keep these in sync with what's used in hack/lbi 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 +# Build integration test image using pre-existing packages from PATH +build-integration-test-image-from-package PATH: + @just build-from-package {{PATH}} + cd hack && podman build {{base_buildargs}} -t {{integration_img}}-bin -f Containerfile . + ./tests/build-sealed {{variant}} {{integration_img}}-bin {{integration_img}} + # Keep these in sync with what's used in hack/lbi + 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 + # Build+test using the `composefs-sealeduki-sdboot` variant. test-composefs: # These first two are currently a distinct test suite from tmt that directly diff --git a/contrib/packaging/install-rpm-and-setup b/contrib/packaging/install-rpm-and-setup index 449072e9..a8a8efdc 100755 --- a/contrib/packaging/install-rpm-and-setup +++ b/contrib/packaging/install-rpm-and-setup @@ -7,7 +7,7 @@ RPM_DIR="${1:-/tmp}" # Install the RPM package # Use rpm -Uvh with --oldpackage to allow replacing with dev version rpm -Uvh --oldpackage "${RPM_DIR}"/*.rpm -rm -f "${RPM_DIR}"/*.rpm +# Note: we don't need to clean up the source directory since it's a bind mount # Regenerate initramfs if we have initramfs-setup kver=$(cd /usr/lib/modules && echo *)