From 44b1ccca57e7dfb6f30ffab3bb4bc89a7f4285df Mon Sep 17 00:00:00 2001 From: Huijing Hei Date: Fri, 19 Dec 2025 17:30:46 +0800 Subject: [PATCH] tests: Add test `test-tmt-on-coreos` To workaround https://github.com/bootc-dev/bcvk/issues/174, will build `bootc-integration-coreos` container firstly and save it to `bootc.tar`, then load it to install. Signed-off-by: Huijing Hei --- .github/workflows/ci.yml | 16 +++++- Justfile | 20 +++++++ crates/xtask/src/tmt.rs | 41 ++++++++++++- hack/Containerfile | 7 +++ tmt/plans/tests-install.fmf | 27 +++++++++ .../test-on-ostree/test-install-on-ostree.sh | 57 +++++++++++++++++++ tmt/tests/test-install.fmf | 8 +++ 7 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 tmt/plans/tests-install.fmf create mode 100644 tmt/tests/install/test-on-ostree/test-install-on-ostree.sh create mode 100644 tmt/tests/test-install.fmf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4bb812a..103e8fbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,12 +197,24 @@ jobs: - name: Unit and container integration tests run: just test-container - - name: Run TMT tests + - name: Run TMT integration tests run: | if [ "${{ matrix.variant }}" = "composefs-sealeduki-sdboot" ]; then just test-composefs else - just test-tmt + just test-tmt integration + fi + just clean-local-images + + - name: Run TMT test about bootc install on coreos + run: | + # Only test fedora-43 on fedora-coreos:testing-devel + if [ "${{ matrix.test_os }}" = "fedora-43" ] && [ "${{ matrix.variant }}" = "ostree" ]; then + just build-testimage-coreos target/packages + just test-tmt-on-coreos plan-bootc-install-on-coreos + just clean-local-images + else + echo "skipped" fi - name: Archive TMT logs diff --git a/Justfile b/Justfile index 16a98be1..a8172c1d 100644 --- a/Justfile +++ b/Justfile @@ -66,6 +66,9 @@ _git-build-vars: echo "SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}" echo "VERSION=${VERSION}" +# Needed by bootc install on ostree +fedora-coreos := "quay.io/fedora/fedora-coreos:testing-devel" + # The default target: 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` @@ -179,6 +182,8 @@ validate: # # To run an individual test, pass it as an argument like: # `just test-tmt readonly` +# +# To run the integration tests, execute `just test-tmt integration` test-tmt *ARGS: build-integration-test-image _build-upgrade-image @just test-tmt-nobuild {{ARGS}} @@ -192,6 +197,19 @@ _build-upgrade-image: test-tmt-nobuild *ARGS: cargo xtask run-tmt --env=BOOTC_variant={{variant}} --upgrade-image={{integration_upgrade_img}} {{integration_img}} {{ARGS}} +# Build test container image for testing on coreos with SKIP_CONFIGS=1, +# without configs and no curl container image +build-testimage-coreos PATH: + @just build-from-package {{PATH}} + cd hack && podman build {{base_buildargs}} --build-arg SKIP_CONFIGS=1 -t {{integration_img}}-coreos -f Containerfile . + +# Run test bootc install on FCOS +# BOOTC_target is `bootc-integration-coreos`, it will be used for bootc install. +# Run `just build-testimage-coreos target/packages` to build test image firstly, +# then run `just test-tmt-on-coreos plan-bootc-install-on-coreos` +test-tmt-on-coreos *ARGS: + cargo xtask run-tmt --env=BOOTC_variant={{variant}} --env=BOOTC_target={{integration_img}}-coreos:latest {{fedora-coreos}} {{ARGS}} + # Cleanup all test VMs created by tmt tests tmt-vm-cleanup: bcvk libvirt rm --stop --force --label bootc.test=1 @@ -206,6 +224,8 @@ test-container: build-units build-integration-test-image clean-local-images: podman images --filter "label={{testimage_label}}" podman images --filter "label={{testimage_label}}" --format "{{{{.ID}}" | xargs -r podman rmi -f + podman image prune -f + podman rmi {{fedora-coreos}} -f # Print the container image reference for a given short $ID-VERSION_ID for NAME # and 'base' or 'buildroot-base' for TYPE (base image type) diff --git a/crates/xtask/src/tmt.rs b/crates/xtask/src/tmt.rs index 3a97fe4c..682381a7 100644 --- a/crates/xtask/src/tmt.rs +++ b/crates/xtask/src/tmt.rs @@ -137,6 +137,25 @@ fn build_firmware_args(sh: &Shell, image: &str) -> Result> { Ok(r) } +/// Detect VARIANT_ID from container image by reading os-release +/// Returns string like "coreos" or empty +#[context("Detecting distro from image")] +fn detect_variantid_from_image(sh: &Shell, image: &str) -> Result> { + let variant_id = cmd!( + sh, + "podman run --net=none --rm {image} bash -c '. /usr/lib/os-release && echo $VARIANT_ID'" + ) + .read() + .context("Failed to run image as container to detect distro")?; + + let variant_id = variant_id.trim(); + if variant_id.is_empty() { + return Ok(None); + } + + Ok(Some(variant_id.to_string())) +} + /// Check if a distro supports --bind-storage-ro /// CentOS 9 lacks systemd.extra-unit.* support required for bind-storage-ro fn distro_supports_bind_storage_ro(distro: &str) -> bool { @@ -269,6 +288,9 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> { // Detect distro from the image let distro = detect_distro_from_image(sh, image)?; + // Detect VARIANT_ID from the image + // As this can not be empty value in context, use "unknown" instead + let variant_id = detect_variantid_from_image(sh, image)?.unwrap_or("unknown".to_string()); let context = args .context @@ -276,11 +298,15 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> { .map(|v| format!("--context={}", v)) .chain(std::iter::once(format!("--context=running_env=image_mode"))) .chain(std::iter::once(format!("--context=distro={}", distro))) + .chain(std::iter::once(format!( + "--context=VARIANT_ID={variant_id}" + ))) .collect::>(); let preserve_vm = args.preserve_vm; println!("Using bcvk image: {}", image); println!("Detected distro: {}", distro); + println!("Detected VARIANT_ID: {variant_id}"); let firmware_args = build_firmware_args(sh, image)?; @@ -295,6 +321,14 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> { .run() .with_context(|| format!("Copying tmt files to {}", workdir))?; + // Workaround for https://github.com/bootc-dev/bcvk/issues/174 + // Save the container image to tar, this will be synced to tested OS + if variant_id == "coreos" { + cmd!(sh, "podman save -q -o {workdir}/tmt/tests/bootc.tar localhost/bootc-integration-coreos:latest") + .run() + .with_context(|| format!("Saving container image to tar"))?; + } + // Change to workdir for running tmt commands let _dir = sh.push_dir(workdir); @@ -387,7 +421,12 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> { distro ); } - + // Add --filesystem=xfs by default on fedora-coreos + if variant_id == "coreos" { + if distro.starts_with("fedora") { + opts.push("--filesystem=xfs".to_string()); + } + } opts }; diff --git a/hack/Containerfile b/hack/Containerfile index ea24df36..5ec8ab7f 100644 --- a/hack/Containerfile +++ b/hack/Containerfile @@ -18,7 +18,14 @@ EORUN # And the configs FROM extended +ARG SKIP_CONFIGS RUN --mount=type=bind,from=context,target=/run/context <}" +if [ -n "${SKIP_CONFIGS:-}" ]; then + echo "Skipping configs installation" + exit 0 +fi set -xeuo pipefail cd /run/context # For test-22-logically-bound-install diff --git a/tmt/plans/tests-install.fmf b/tmt/plans/tests-install.fmf new file mode 100644 index 00000000..197cbf47 --- /dev/null +++ b/tmt/plans/tests-install.fmf @@ -0,0 +1,27 @@ +discover: + how: fmf +execute: + how: tmt +# Because of the two issues, run tmt on github runner directly failed +# - selinux disabled on ubuntu (https://github.com/teemtee/tmt/issues/3364) +# - uefi firmware is not supported (https://github.com/teemtee/tmt/issues/4203) +provision: + how: virtual + hardware: + boot: + method: uefi + image: fedora-coreos-next + user: root + memory: 4096 + disk: 20 + +/plan-bootc-install-on-coreos: + summary: Execute bootc install on ostree OS + adjust: + - when: VARIANT_ID != coreos + enabled: false + because: this needs to start an ostree OS firstly + discover: + how: fmf + test: + - /tmt/tests/test-install/test-bootc-install-on-coreos diff --git a/tmt/tests/install/test-on-ostree/test-install-on-ostree.sh b/tmt/tests/install/test-on-ostree/test-install-on-ostree.sh new file mode 100644 index 00000000..507e1d75 --- /dev/null +++ b/tmt/tests/install/test-on-ostree/test-install-on-ostree.sh @@ -0,0 +1,57 @@ +# number: 50 +# tmt: +# summary: Test bootc install on ostree OS +# duration: 30m +# adjust: +# - when: VARIANT_ID != coreos +# enabled: false +# because: this needs to start an ostree OS firstly +# +#!/bin/bash +set -eux + +echo "Testing bootc install on ostree" + +# BOOTC_target is integration image +[ -n "$BOOTC_target" ] + +if [ "$TMT_REBOOT_COUNT" -eq 0 ]; then + echo "Running before first reboot" + pwd + ls -l + # Verify testing on ostree OS + if [ ! -f "/run/ostree-booted" ]; then + echo "Should be ostree OS" + exit 1 + fi + # workaround for https://github.com/bootc-dev/bcvk/issues/174 + bootc_tar=bootc.tar + [ -f ${bootc_tar} ] + podman load -q -i ${bootc_tar} + podman image exists ${BOOTC_target} && rm -f ${bootc_tar} + + # Run bootc install using the same stateroot for shared /var + stateroot=$(bootc status --json | jq -r .status.booted.ostree.stateroot) + podman run \ + --rm --privileged \ + -v /dev:/dev \ + -v /:/target \ + -v /var/lib/containers:/var/lib/containers \ + --pid=host \ + --security-opt label=type:unconfined_t \ + ${BOOTC_target} \ + bootc install to-existing-root \ + --stateroot=${stateroot} \ + --skip-fetch-check \ + --acknowledge-destructive \ + --karg=console=ttyS0,115200n8 + + bootc status + tmt-reboot +elif [ "$TMT_REBOOT_COUNT" -eq 1 ]; then + echo 'After the reboot' + booted=$(bootc status --json | jq -r .status.booted.image.image.image) + [ ${booted} == ${BOOTC_target} ] +fi + +echo "Run bootc install on ostree OS successfully" diff --git a/tmt/tests/test-install.fmf b/tmt/tests/test-install.fmf new file mode 100644 index 00000000..79394426 --- /dev/null +++ b/tmt/tests/test-install.fmf @@ -0,0 +1,8 @@ +/test-bootc-install-on-coreos: + summary: Test bootc install on coreos + duration: 30m + adjust: + - when: VARIANT_ID != coreos + enabled: false + because: this needs to start an ostree OS firstly + test: bash install/test-on-ostree/test-install-on-ostree.sh