Add `cargo xtask local-rust-deps` which uses `cargo metadata` to find
local path dependencies outside the workspace (e.g., from [patch] sections)
and outputs podman bind mount arguments.
This enables a cleaner workflow for local development against modified
dependencies like composefs-rs:
1. Add a [patch] section to Cargo.toml with real local paths
2. Run `just build` - the Justfile auto-detects and bind-mounts them
Benefits over the previous BOOTC_extra_src approach:
- No manual env var needed
- Paths work for both local `cargo build` and container builds
- No /run/extra-src indirection or Cargo.toml path munging required
- Auto-detection means it Just Works™
The Justfile's build target now calls `cargo xtask local-rust-deps` to
get bind mount args, falling back gracefully if there are no external deps.
The old BOOTC_extra_src mechanism is still supported for backwards compat.
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Add support for bind-mounting an extra source directory into container
builds, primarily for developing against a local composefs-rs checkout.
Usage:
BOOTC_extra_src=$HOME/src/composefs-rs just build
The directory is mounted at /run/extra-src inside the container. When
using this, also patch Cargo.toml to use path dependencies pointing to
/run/extra-src/crates/....
Signed-off-by: Colin Walters <walters@verbum.org>
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Now that we're doing a "from scratch" build we don't
have the mtime issue, and so we can change our build system
to do everything in a single step.
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
In C9S there's something leaking files in `/tmp` so let's just
enforce use of tmpfs for `/run` at build time too.
But fix `RUN bootc container lint` to *not* have those mounts
becuase otherwise we don't actually see the leaked content.
Assisted-by: Cursor (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
The base image may be built from a compose that has newer packages
than what's available on the public mirrors. This causes version skew
where packages like bootupd have different versions between the base
image and our built image.
For example, bootupd 0.2.32 changed the EFI file layout from
/usr/lib/bootupd/updates/EFI/ to /usr/lib/efi/, and if we build
with an older bootupd from mirrors while the target image has
the newer layout, bootloader installation fails.
Enable the CentOS Stream compose repos with higher priority to ensure
we get matching versions.
xref https://gitlab.com/redhat/centos-stream/containers/bootc/-/issues/1174
Signed-off-by: Colin Walters <walters@verbum.org>
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
When using --mount=type=bind,target=/run/foo, podman/buildah creates
the mount point directory in the image layer even though the mounted
content is not committed. These empty directory stubs pollute /run
in the final image.
Fix by using --mount=type=tmpfs,target=/run with bind mounts nested
inside. This ensures /run remains empty in the committed layer.
Also move the lint invocation in Dockerfile.cfsuki to a separate RUN
command so it runs after the bind mount is released.
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Ensure all RUN instructions after the "external dependency cutoff point"
marker include `--network=none` right after `RUN`.
This enforces that external dependencies are clearly delineated in the early stages of the Dockerfile.
The check is part of `cargo xtask check-buildsys` and includes unit tests.
Assisted-by: OpenCode (Sonnet 4)
Signed-off-by: Colin Walters <walters@verbum.org>
The previous commit consolidated test content (nushell, cloud-init, etc.)
into the base image. This completes that work by removing the separate
`build-integration-test-image` target and updating all references.
Now `just build` produces the complete test-ready image directly,
simplifying the build pipeline and eliminating the intermediate
`localhost/bootc-integration` image.
Also adds SKIP_CONFIGS support for the coreos testing workflow, which
skips LBIs, test kargs, and install configs that would conflict with FCOS.
Signed-off-by: Colin Walters <walters@verbum.org>
Move all content from the derived test image (hack/Containerfile) into
the main Dockerfile base image. This includes nushell, cloud-init, and
the other testing packages from packages.txt.
This simplifies the build by avoiding the need to juggle multiple images
during testing workflows - the base image now contains everything needed.
Assisted-by: OpenCode (Claude Sonnet 4)
Signed-off-by: Colin Walters <walters@verbum.org>
# Conflicts:
# hack/Containerfile
We were previously trying to support a direct `podman/docker build`
*and* injecting externally built packages (for CI).
Looking to rework for sealed images it was too hacky; let's
just accept that a raw `podman build` no longer works, the canonical
entry for local build is `just build` which builds both a package
and a container.
This way CI and local work exactly the same.
Signed-off-by: Colin Walters <walters@verbum.org>
Pass SOURCE_DATE_EPOCH from git commit timestamp through to rpmbuild,
enabling bit-for-bit reproducible RPM builds. This is useful for
verification and caching.
Then fix the idempotency of the default `just build` to ensure
we're not incorrectly invalidating caches.
Add `just check-buildsys` command that builds packages twice and
verifies checksums match, confirming reproducibility. The CI package
job now uses this to catch regressions.
Assisted-by: OpenCode (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Main goal is to reduce signing logic duplication between the systemd-boot
and UKI generation.
However, this quickly snowballed into wanting to actually verify
by providing a custom secure boot keys to bcvk that things worked.
This depends on https://github.com/bootc-dev/bcvk/pull/170
Now as part of that, I ran into what I think are bugs in pesign;
this cuts things back over to using sbsign. I'll file a tracker for that
separately.
Finally as part of this, just remove the TMT example that builds
a sealed image but doesn't actually verify it works - it's already
drifted from what we do outside here. Ultimately what we need
is to shift some of this into the Fedora examples and we just
fetch it here anyways.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
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 <walters@verbum.org>
In order to debug failures more reliably we really always want a virtual
console.
It turns out the Fedora kernel configs for a while have done
9a0d7ce2af
which means hvc0 is available from very early boot.
I am probably going to argue to do this in all Fedora derivatives by
default soon but let's start here.
Signed-off-by: Colin Walters <walters@verbum.org>
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 <walters@verbum.org>
When commit cd8fa591 moved unit enablement to a systemd generator, it also
removed the installation of the fedora-bootc-destructive-cleanup script from
the Makefile. This was unintentional - while the symlink enablement should
be handled by the generator, the script itself still needs to be installed.
The trap is that because we weren't accurately removing old files
from the build, the old version was still there...until the new upstream
release.
Fix this in two ways:
First, continue to install the script on Fedora-like systems as before, but leave unit
enablement to the generator as intended.
Second, change how we remove prior state to clean out all files from
the RPM. (I did look at changing out the build system so we build
an RPM in this case which would be cleaner, but it's a large change)
Fixes: https://github.com/bootc-dev/bootc/issues/1748
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
Part 1: Use bcvk
For local tests, right now testcloud+tmt doesn't support UEFI, see
https://github.com/teemtee/tmt/issues/4203
This is a blocker for us doing more testing with UKIs.
In this patch we switch to provisioning VMs with bcvk, which
fixes this - but beyond that a really compelling thing about
this is that bcvk is *also* designed to be ergonomic and efficient
beyond just being a test runner, with things like virtiofs
mounting of host container storage, etc.
In other words, bcvk is the preferred way to run local virt
with bootc, and this makes our TMT tests use it.
Now a major downside of this though is we're effectively
implementing a new "provisioner" for tmt (bypassing the
existing `virtual`). In the more medium term I think we
want to add `bcvk` as a provisioner option to tmt.
Anyways for now, this works by discovers test plans via `tmt plan ls`,
spawning a separate VM per test, and then using uses tmt's connect
provisioner to run tests targeting these externally provisioned
systems.
Part 2: Rework the Justfile and Dockerfile
This adds `base` and `variant` arguments which are propagated through
the system, and we have a new `variant` for sealed composefs.
The readonly tests now pass with composefs.
Drop the continuous repo tests...as while we could keep
that it's actually a whole *other* entry in this matrix.
Assisted-by: Claude Code (Sonnet 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
build-sys: Run most parts with `--network=none`
Why? It just shows that we have put some thought into our
build system and care about reproducibility, hermetic builds etc.
And yes of course, `--network=bridge` should probably have been
required as an opt-in in Dockerfile, but oh well. It's not too
bad to sprinkle `--network=none` in some places. The biggest one
is wrapping `make`.
Signed-off-by: Colin Walters <walters@verbum.org>
- Change the install logic to detect UKIs and automatically
enable composefs
- Change the install logic to detect absence of bootupd
and default to installing systemd-boot
- Move sealing bits to the toplevel
- Add Justfile entrypoints
- Add basic end-to-end CI coverage (install + run) using
our integration tests
- Change lints to ignore `/boot/EFI`
Signed-off-by: Colin Walters <walters@verbum.org>
The rationale for having c9s by default was that it's
a lower bound (which is still true). But our CI covers
that; I'd rather now have the default be c10s be the default
as it will be the focus of features going forward.
Signed-off-by: Colin Walters <walters@verbum.org>
As we progress the composefs work along this is becoming more of a
general requirement. I think it still makes sense to leave it as
optional for now, but I think for the bulk of the cases we'll want to
go ahead and build the initramfs support in.
Signed-off-by: John Eckersberg <jeckersb@redhat.com>
As soon as we went from a single binary to shipping systemd units,
we can't just blindly `COPY /new /` as it will leak old files.
In the end as the comment says we probably need to go to
building packages eventually.
Signed-off-by: Colin Walters <walters@verbum.org>
The emphasis here is on trying to have
the `Justfile` be the default entrypoint,
wrapping other tools.
- Replace mentions of podman-bootc with bcvk
since I hope the latter supercedes the former
- Unify the unit test entrypoint
- Set up /var/tmp as a tmpdir to fix the etc merge
test (otherwise, selinux failures w/tmp)
- Run the unit+container tests in integration.yml
- Have `just validate` run in a container
Signed-off-by: Colin Walters <walters@verbum.org>
This adds scaffolding to install a stub binary which can
optionally be added into the initramfs;
prep for us doing real work during setup as we aim
to move to the native composefs backend.
The binary is *built* but is only installed by a
new `Makefile` target, so existing build system
users won't pick it up. Our development-only
`Dockerfile` gains a build option to use it
(and also ensures the initramfs is regenerated).
However previously we also discussed moving the fstab
logic into the initramfs:
https://github.com/bootc-dev/bootc/pull/1113
I might try doing that once this lands.
One notable thing is that even this trivial nearly-no-op
binary is still 4MB which I think is mostly due
to linking in a whole copy of prebuilt rust `std`.
In theory we could try going to `#[no_std]` but I
don't think it'll be viable once we start doing more here.
Probably most practical thing re size is `-Z build-std` + LTO.
Signed-off-by: Colin Walters <walters@verbum.org>
This is aligning with what I did in https://github.com/ostreedev/ostree/pull/3439
- What gets invoked in e.g. GHA should ideally most be `just` commands
that are easy to run locally too (with sudo in GHA, without sudo locally)
- Move the "core build" to the toplevel so that one can just `podman build`
directly too (without the Justfile) and have it do something useful
- The "always build and test in a container" helps for LLM-assisted coding
because what they can do is inherently sandboxed
Signed-off-by: Colin Walters <walters@verbum.org>