feat(e2e): compose test software as a container layer instead of runtime install - #744
Conversation
…ime install rpm-ostree install --apply-live fails on images that ship rpm-ostreed.conf LockLayering=true (bluefin-lts does this deliberately — projectbluefin/bluefin-lts#492, PR #509), so the harness can no longer rely on installing the common suite's shell tools at runtime inside the VM. Add a compose stage to the reusable e2e workflow: - container/e2e-overlay/Containerfile + packages.list: derived layer FROM the target image that best-effort installs the tools the common suite validates (zsh, fish, fzf, bat, eza, fd-find, ripgrep, starship). - scripts/compose-e2e-image.sh: builds the overlay with podman and pushes it to GHCR. - e2e.yml `compose` job: pushes ghcr.io/<owner>/testsuite-e2e:run-<GITHUB_RUN_ID> and exports the composed ref; suite jobs boot it instead of the raw image. Compose failure is non-fatal — suite jobs fall back to the raw image and the legacy runtime-install path. - The runtime "Install shell tools for common suite" step is retained only as that fallback (compose_image=false input or repository variable E2E_COMPOSE_IMAGE=0); on the composed path it is replaced by a verification-only step. - Summary/screenshot naming keeps using the raw input image so run-scoped tags don't leak into artifact names. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KSjBPVDcnK71WveusaK7Nc
|
Holding this one deliberately while merging the other four testsuite PRs in this batch.
So I've queued #746, #747, #748 and #749, which are docs and test-only changes. This PR is different and I'd rather not merge it on a red lab. "compose test software as a container layer instead of runtime install" changes how the e2e suite builds its test images — which is precisely what Two ways forward, whichever is easier:
Worth fixing the reporting either way: a check that has been failing on 100% of PRs for days is indistinguishable from a check that's finding real bugs, and right now it's training everyone to ignore it. If the lab is expected to be offline, the reporter should skip or report neutral rather than fail. |
… var (projectbluefin#754) The installer suite's @luks scenario asserts that the projectbluefin/common#385 `rd.luks.name=` parsing fix holds on a real installed system. It gated on a `LUKS_ENABLED` environment variable — and nothing in the repo has ever set it. The suite runs through the `common|lifecycle|installer` branch of e2e.yml, which exports a fixed list (VM_IP, VM_USER, SSH_KEY, SSH_PORT, ZSTD_CHUNKED) and the reusable workflow exposes no input to add another, so a downstream repo cannot supply it either. `git grep LUKS_ENABLED` finds two lines, both readers, no writer. The scenario has therefore skipped on every run since it landed, and a skipped scenario reads as green: the assertion was never once exercised, while projectbluefin/dakota#651 tracked it as implemented. Replace the dead gate with a runtime probe. `target_uses_luks()` runs `lsblk -rno TYPE | grep -qx crypt` on the DUT — a booted LUKS system always has an unlocked dm-crypt mapping — and caches the answer on the context, so one SSH round trip covers the run. The scenario now runs exactly when the target is a LUKS install and still skips cleanly everywhere else, including on today's direct-kernel-boot QEMU lane where nothing changes. `LUKS_ENABLED` remains an explicit override in both directions, so an operator can force the scenario on to prove a regression or off to keep it out of a run. The behaviour change is what an unset variable means: "probe the target" rather than "no LUKS". No workflow change, deliberately: .github/workflows/e2e.yml is owned by open PR projectbluefin#744, and a probe is the better fix regardless — it cannot silently disagree with the machine it is describing. tests/unit/test_installer_environment.py pins the probe, the override, the caching, and a guard that fails if the gate reverts to reading an unset variable alone. 21 of its 23 tests fail against the previous implementation. Learning written back to docs/skills/ci-ops/e2e-workflow/ as a new references/installer-suite.md, with the general rule: an env-var gate is only as real as the plumbing that sets it — grep for the writer, or probe the DUT. Refs: projectbluefin/dakota#651, projectbluefin/common#385 Assisted-by: Claude Opus 5 via Claude Code Co-authored-by: Danathar <Danathar@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Motivation
rpm-ostree install --apply-livefails on images that deliberately lock runtime layering: bluefin-lts shipsrpm-ostreed.confwithLockLayering=true(projectbluefin/bluefin-lts#492, shipped in projectbluefin/bluefin-lts#509). The e2e harness currently layers the common suite's shell tools at runtime inside the booted VM, which breaks against such images. Per maintainer direction, the harness now composes the test software as a container layer at build time — following thepr-e2e.ymlpattern in bluefin-lts (Containerfile FROM base + RUN, pushed to GHCR with a run-scoped tag).Compose flow
composejob in the reusablee2e.yml(runs after the matrix resolve, before the suite jobs;packages: write):container/e2e-overlay/+scripts/compose-e2e-image.shatinputs.test_refscripts/compose-e2e-image.shbuildscontainer/e2e-overlay/Containerfilewith--build-arg BASE_IMAGE=<inputs.image>and pushesghcr.io/<owner>/testsuite-e2e:run-${GITHUB_RUN_ID}needs.compose.outputs.image || inputs.image(GHCR login added before the pull, since fresh run-scoped packages default to private).zsh fish fzf bat eza fd-find ripgrep starship(container/e2e-overlay/packages.list) — best-effort per package, mirroring the old step's warning-on-missing tolerance, and runsostree container commitwhen applicable.IMAGE_SLUG, gh-pages URL, artifact metadata) keep using the raw input image so run-scoped tags don't leak into artifact names.Fallback toggle
compose_imageworkflow input (defaulttrue), or repository variableE2E_COMPOSE_IMAGE=0, disables composing.continue-on-error+ warning): suite jobs automatically fall back to the raw image and the legacy runtime-install path.Runtime-install sites replaced / kept
e2e.yml"Install shell tools for common suite" — thesudo rpm-ostree install --apply-live/dnf installcalls inside the VM (the feat(common): add Bluefin-specific GSettings override validation #492 offender). Kept only as the legacy fallback step; on the composed path it becomes a verification-only step.scripts/install-kde-webdriver.sh(KDE suites) — dnf/source-build inside the VM; ABI-tied to the SUT per its own documented rationale, out of scope here.tests/dxdistroboxdnf install— runs inside a mutable container, unaffected by LockLayering.microdnfpatching and Flatpak preloads — container/Flatpak operations, not host layering.🤖 Generated with Claude Code
https://claude.ai/code/session_01KSjBPVDcnK71WveusaK7Nc
Generated by Claude Code