From d68245d319967bb1d30fbaa33f07e893a540f46f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 16 Nov 2025 11:48:43 -0500 Subject: [PATCH] Dockerfile: Use rpmbuild We were bit before by just doing a `COPY` of our binaries overtop of the base image because that doens't remove old files. Replace the pre-build approach with rpmbuild, and then change to do an rpm-based upgrade so that we fix that problem. Note that we still preserve incremental rebuilds by overriding some of the RPM build process. Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters --- .dockerignore | 3 + Dockerfile | 127 +++++------------------- Justfile | 24 +++++ contrib/packaging/bootc.spec | 50 +++++++++- contrib/packaging/build-rpm | 44 ++++++++ contrib/packaging/configure-rootfs | 46 +++++++++ contrib/packaging/configure-variant | 26 +++++ contrib/packaging/fedora-extra.txt | 2 + contrib/packaging/install-buildroot | 15 +++ contrib/packaging/install-rpm-and-setup | 24 +++++ 10 files changed, 258 insertions(+), 103 deletions(-) create mode 100755 contrib/packaging/build-rpm create mode 100755 contrib/packaging/configure-rootfs create mode 100755 contrib/packaging/configure-variant create mode 100755 contrib/packaging/install-buildroot create mode 100755 contrib/packaging/install-rpm-and-setup diff --git a/.dockerignore b/.dockerignore index 5f34ec97..1f557997 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,6 +8,9 @@ # Toplevel build bits !Makefile !Cargo.* +# License and doc files needed for RPM +!LICENSE-* +!README.md # We do build manpages from markdown !docs/ # We use the spec file diff --git a/Dockerfile b/Dockerfile index 82691c59..27b548c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,34 +10,26 @@ ARG base=quay.io/centos-bootc/centos-bootc:stream10 FROM scratch as src COPY . /src +# And this image only captures contrib/packaging separately +# to ensure we have more precise cache hits. +FROM scratch as packaging +COPY contrib/packaging / + FROM $base as base -# We could inject other content here +# Mark this as a test image (moved from --label build flag to fix layer caching) +LABEL bootc.testimage="1" # This image installs build deps, pulls in our source code, and installs updated # bootc binaries in /out. The intention is that the target rootfs is extracted from /out # back into a final stage (without the build deps etc) below. -FROM base as build +FROM base as buildroot # Flip this off to disable initramfs code ARG initramfs=1 -# This installs our package dependencies, and we want to cache it independently of the rest. -# Basically we don't want changing a .rs file to blow out the cache of packages. So we only -# copy files necessary -COPY contrib/packaging /tmp/packaging -RUN < /usr/lib/bootc/install/80-rootfs-override.toml < /usr/lib/bootc/install/80-ext4-composefs.toml </dev/null); then + VERSION="${VERSION#v}" + VERSION="${VERSION//-/.}" + else + COMMIT=$(git rev-parse HEAD | cut -c1-10) + COMMIT_TS=$(git show -s --format=%ct) + TIMESTAMP=$(date -u -d @${COMMIT_TS} +%Y%m%d%H%M) + VERSION="${TIMESTAMP}.g${COMMIT}" + fi + 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/ +# 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 - + # This container image has additional testing content and utilities build-integration-test-image: build cd hack && podman build {{base_buildargs}} -t localhost/bootc-integration-bin -f Containerfile . diff --git a/contrib/packaging/bootc.spec b/contrib/packaging/bootc.spec index 646ad619..114cd514 100644 --- a/contrib/packaging/bootc.spec +++ b/contrib/packaging/bootc.spec @@ -1,4 +1,5 @@ %bcond_without check +%bcond_with tests %if 0%{?rhel} >= 9 || 0%{?fedora} > 41 %bcond_without ostree_ext %else @@ -21,7 +22,8 @@ %endif Name: bootc -Version: 1.1.5 +# Ensure this local build overrides anything else. +Version: 99999.0.0 Release: 1%{?dist} Summary: Bootable container system @@ -84,17 +86,49 @@ Recommends: podman %description -n system-reinstall-bootc This package provides a utility to simplify reinstalling the current system to a given bootc image. +%if %{with tests} +%package tests +Summary: Integration tests for bootc +Requires: %{name} = %{version}-%{release} + +%description tests +This package contains the integration test suite for bootc. +%endif + %global system_reinstall_bootc_install_podman_path %{_prefix}/lib/system-reinstall-bootc/install-podman +%if 0%{?container_build} +# Source is already at /src, no subdirectory +%global _buildsubdir . +%endif + %prep +%if ! 0%{?container_build} %autosetup -p1 -a1 # Default -v vendor config doesn't support non-crates.io deps (i.e. git) cp .cargo/vendor-config.toml . %cargo_prep -N cat vendor-config.toml >> .cargo/config.toml rm vendor-config.toml +%else +# Container build: source already at _builddir (/src), nothing to extract +# RPM's %mkbuilddir creates a subdirectory; symlink it back to the source +cd .. +rm -rf %{name}-%{version}-build +ln -s . %{name}-%{version}-build +cd %{name}-%{version}-build +%endif %build +export SYSTEM_REINSTALL_BOOTC_INSTALL_PODMAN_PATH=%{system_reinstall_bootc_install_podman_path} +%if 0%{?container_build} +# Container build: use cargo directly with cached dependencies +export CARGO_HOME=/var/roothome/.cargo +cargo build -j%{_smp_build_ncpus} --release %{?with_rhsm:--features rhsm} \ + --bin=bootc --bin=system-reinstall-bootc \ + %{?with_tests:--bin tests-integration} +make manpages +%else # Build the main bootc binary %if %new_cargo_macros %cargo_build %{?with_rhsm:-f rhsm} @@ -104,7 +138,6 @@ rm vendor-config.toml # Build the system reinstallation CLI binary %global cargo_args -p system-reinstall-bootc -export SYSTEM_REINSTALL_BOOTC_INSTALL_PODMAN_PATH=%{system_reinstall_bootc_install_podman_path} %if %new_cargo_macros # In cargo-rpm-macros, the cargo_build macro does flag processing, # so we need to pass '--' to signify that cargo_args is not part @@ -118,18 +151,24 @@ export SYSTEM_REINSTALL_BOOTC_INSTALL_PODMAN_PATH=%{system_reinstall_bootc_insta %endif make manpages +%endif +%if ! 0%{?container_build} %cargo_vendor_manifest # https://pagure.io/fedora-rust/rust-packaging/issue/33 sed -i -e '/https:\/\//d' cargo-vendor.txt %cargo_license_summary %{cargo_license} > LICENSE.dependencies +%endif %install %make_install INSTALL="install -p -c" %if %{with ostree_ext} make install-ostree-hooks DESTDIR=%{?buildroot} %endif +%if %{with tests} +install -D -m 0755 target/release/tests-integration %{buildroot}%{_bindir}/bootc-integration-tests +%endif mkdir -p %{buildroot}/%{dirname:%{system_reinstall_bootc_install_podman_path}} cat >%{?buildroot}/%{system_reinstall_bootc_install_podman_path} < /tmp/rpmbuild/SPECS/bootc.spec + SPEC_FILE=/tmp/rpmbuild/SPECS/bootc.spec +else + SPEC_FILE="${SRC_DIR}/contrib/packaging/bootc.spec" +fi + +# Build RPM +rpmbuild -bb \ + --define "_topdir /tmp/rpmbuild" \ + --define "_builddir ${SRC_DIR}" \ + --define "container_build 1" \ + --with tests \ + --nocheck \ + "${SPEC_FILE}" + +# Copy built RPMs to output directory +ARCH=$(uname -m) +mkdir -p "${OUTPUT_DIR}" +cp /tmp/rpmbuild/RPMS/${ARCH}/*.rpm "${OUTPUT_DIR}/" +rm -rf /tmp/rpmbuild diff --git a/contrib/packaging/configure-rootfs b/contrib/packaging/configure-rootfs new file mode 100755 index 00000000..1e6d8ebd --- /dev/null +++ b/contrib/packaging/configure-rootfs @@ -0,0 +1,46 @@ +#!/bin/bash +# Configure rootfs type for bootc installation +set -xeuo pipefail + +VARIANT="${1:-}" +ROOTFS="${2:-}" + +# Support overriding the rootfs at build time +CONFIG_DIR="/usr/lib/bootc/install" +mkdir -p "${CONFIG_DIR}" + +# Do we have an explicit build-time override? Then write it. +if [ -n "$ROOTFS" ]; then + cat > "${CONFIG_DIR}/80-rootfs-override.toml" < "${CONFIG_DIR}/80-ext4-composefs.toml" <