Skip to content

tests: Check that GC keeps a V2 rollback in the 1.16 bridge test - #36

Draft
cgwalters-bot wants to merge 5 commits into
mainfrom
bot/composefs-gc-mixed-entries
Draft

cgwalters-bot wants to merge 5 commits into
mainfrom
bot/composefs-gc-mixed-entries

Conversation

@cgwalters-bot

Copy link
Copy Markdown
Collaborator

Stacked on forge #30 (bot/cfs-bridge-1164, itself on #18). Until those land this PR also shows their commits; only the last commit is new.

test-49 never ran a repository GC while a 1.16.0 install's V2 deployment was the rollback of a V1 one, which is what every such system looks like right after its first upgrade with current bootc. Its only GC ran after the rollback, with the V2 deployment booted, and without --prune-repo, so it only looked at boot binaries and could not report a removed object.

With the upgrade booted, the test now runs composefs-gc --prune-repo (the GC upgrades run) and checks that the rollback's boot entry, deployment state and EROFS image (still V2) survive, and that cfsctl fsck and cfsctl oci fsck of the rollback's bootc tag pass. Then it rolls back as before, which proves the V2 deployment still boots. The final --assert-no-op now includes --prune-repo.

Tested on a 16-core devspace (cgwalters-devspace-37011656929), Fedora 44 base, just test-composefs-bridge:

  • at this head: unsealed 1.16.0, sealed 1.16.0 and bls 1.16.4 all passed; the boot2 GC removed the 1.16.0 or 1.16.4 install's leftovers (53-56 objects) and fsck and oci fsck passed, and the final --prune-repo --assert-no-op found nothing;
  • that it catches a regression (run at c191f09b, this check before the tag prefix became a constant): with GC temporarily changed to drop a rollback whose EROFS format differs from the booted one's, unsealed 1.16.0 fails at the new boot2 check (GC removed the rollback's manifest, so bootc status can no longer read the rollback), while the test from tests: Cover bootc 1.16.4 and BLS in the 1.16 bridge test #30's head passes against the same broken GC;
  • dropping additional_roots for non-booted deployments alone is not caught, correctly: the V2 boot image is also reachable from the rollback's tagged manifest config, so nothing is lost.

Related: cgwalters-forge/tracker#259

Generated-by: https://github.com/cgwalters/#llms


Review draft in cgwalters-forge, not upstream yet. This section is removed when the PR is opened upstream.

  • Upstream: bootc-dev/bootc, base main
  • Board item: PVTI_lADOE9oHIs4BlJLczg9zlPg
  • Fork CI: off; the devspace testing described above is this PR's CI, and upstream CI runs once it is opened there

To review:

  • Approve, or comment /promote on a line of its own, to open it upstream, ready for review. Either covers only the commits pushed so far.
  • If upstream requires DCO, approving also signs off: promote adds Signed-off-by: Colin Walters <walters@verbum.org> to the commits lacking it (the bot's and yours; anyone else's only if you ask), with you as committer.
  • Add a /draft line (in the same comment or before) to open it upstream as a draft (/ready undoes that).
  • Close to drop it.
  • Edit the title and description freely: they become the upstream PR's. Review comments are squashed into the commits they concern, with a reply here.

It was excluded in bb674f1 because the published Fedora 44 image
shipped a bootc that deadlocked when running GC after a pull
(bootc-dev#2364). The fix (71ad2d3) is in 1.16.8, and
quay.io/fedora/fedora-bootc:44 now ships bootc 1.16.10, so the job
passes again.

Generated-by: AI
btrfs is one of the two filesystems where a sealed composefs system can
enforce fs-verity, but no CI job installed onto it. Add one Fedora 44
leg, sealed UKI with systemd-boot, so fs-verity enforcement on btrfs is
covered too. CentOS is left out as its kernel has no btrfs.

The leg is added with a computed include list rather than a new matrix
axis, so it's one job rather than multiplying the existing matrix.

Generated-by: AI
test-49-composefs-1-16-bridge was opt-in and required externally
prepared fixture images, so nothing ran it and the 1.16.0 UKI upgrade
path was untested in practice.

Build the fixtures from the tree instead. The stager is the current
UKI image with bootc swapped for the pinned 1.16.0 Koji RPM, and its
initramfs and UKI regenerated by that version, so the install, the
initramfs and the UKI arguments are all 1.16.0's. The bridge and
upgrade images are the existing test image and synthetic upgrade
image, labeled as the test expects. `just test-composefs-bridge`
does all of it and CI runs it for sealed and unsealed on Fedora 44
(Koji only has 1.16.0 as an fc45 build, which installs on 44).

It runs with the rest of the heavy jobs rather than on a schedule: it
takes about as long as a test-integration leg, and there's no
scheduled CI workflow whose failures anyone would see.

Generated-by: AI
The bridge test only pinned bootc 1.16.0, which generates V2 EROFS and
reads only the bare composefs= argument (as do 1.16.1 and 1.16.2), so it
stages the V2 fallback of a dual-format UKI. 1.16.3 already reads
composefs.digest= first but still generates V2, so switching to a
dual-format UKI fails there ("The UKI has the wrong composefs=
parameter"). 1.16.4 is the first release to generate V1 (composefs-rs
080f925), and on a repository it created itself it stages V1 directly
and the V2 fallback never comes into play. Nothing tested that path. BLS
installs weren't covered at all either, although there the old client
writes the boot entry for the new image itself (bare composefs= with a
V1 digest since 1.16.4).

The EROFS format comes from the repository's meta.json (V2 when
absent) and is never converted, so the 1.16.4 result does not carry over
to a system installed by 1.16.0-1.16.3 and then staged by
1.16.4-1.16.14; with a UKI that case fails (bootc-dev#2334) and
stays untested, as does 1.16.3. The docs now say which paths are covered.

Parametrize the test by the stager version, the format it is expected
to stage and the install mode (sealed or unsealed UKI, or BLS), and pin
bootc-1.16.4-1.fc44 next to 1.16.0. Rather than inferring the booted
format only from the UKI arguments, the test now reads it from the
composefs header of the booted EROFS image, which also works on BLS.

CI gains two legs: 1.16.4 sealed UKI and 1.16.4 BLS.

Generated-by: AI
After a 1.16.0 install is upgraded by current bootc, the booted
deployment and everything current bootc writes are V1, while the
rollback still boots from the V2 image the old client staged. Nothing
ran a repository GC in that state: the only GC in the test ran after
the rollback, with the V2 deployment booted, and without --prune-repo,
which only looks at boot binaries and so could never report a removed
object.

So with the upgrade booted, run the full GC that upgrades run, check
that the rollback's boot entry, deployment state and EROFS image survive
and that the repository and the rollback's tagged OCI image pass fsck,
then roll back as before to prove it still boots. The final
--assert-no-op check now covers the repository too.

Generated-by: AI
@cgwalters-bot

cgwalters-bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator Author

❌ dispatch handed back no result because required data was missing. Its reason:

Cannot safely refresh PR #36 with the current handback permissions. It stacks on PR #30 at bd84fec, but replacement handback accepts only main as base; including the parent series against main introduces protected .github/w
[Content truncated due to length]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant