diff --git a/.dockerignore b/.dockerignore index 349cd908..697adc05 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,6 @@ .cosa target !target/dev-rootfs +# These directories don't contribute to our container build +docs/ +plans/ diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 00000000..12991789 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,8 @@ +name: Python static analysis +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 diff --git a/Makefile b/Makefile index 65389672..db8b9db7 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,7 @@ test-tmt: validate: cargo fmt cargo clippy + ruff check .PHONY: validate vendor: diff --git a/hack/provision-derived.sh b/hack/provision-derived.sh index 9bdc1b80..2ba8173c 100755 --- a/hack/provision-derived.sh +++ b/hack/provision-derived.sh @@ -1,9 +1,26 @@ #!/bin/bash set -xeu -case "$1" in +variant=$1 +# I'm a big fan of nushell for interactive use, and I want to support +# using it in our test suite because it's better than bash. First, +# enable EPEL to get it. +. /usr/lib/os-release +if echo $ID_LIKE $ID | grep -q centos; then + dnf config-manager --set-enabled crb + dnf -y install epel-release epel-next-release +fi +# Ensure this is pre-created +mkdir -p -m 0700 /var/roothome +mkdir -p ~/.config/nushell +echo '$env.config = { show_banner: false, }' > ~/.config/nushell/config.nu +touch ~/.config/nushell/env.nu +dnf -y install nu +# And we also add pytest, to support running tests written in Python +dnf -y install python3-pytest +case "$variant" in tmt) # tmt wants rsync - dnf -y install cloud-init rsync && dnf clean all + dnf -y install cloud-init rsync ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants # And tmt wants to write to /usr/local/bin rm /usr/local -rf && ln -sr /var/usrlocal /usr/local && mkdir -p /var/usrlocal/bin @@ -14,3 +31,4 @@ case "$1" in echo "Unknown variant: $1" exit 1 ;; esac +dnf clean all && rm /var/log/* -rf diff --git a/plans/integration-run.fmf b/plans/integration-run.fmf index ce98bac5..1190fcd3 100644 --- a/plans/integration-run.fmf +++ b/plans/integration-run.fmf @@ -1,12 +1,18 @@ -# This tmt test just demonstrates local tmt usage. -# We'll hopefully expand it to do more interesting things in the -# future and unify with the other test plans. +# Run this via `make test-tmt` which will build a container, +# and a disk image from it. provision: how: virtual - # Generated by `cargo xtask ` + # Generated by make test-tmt image: file://./target/testvm/disk.qcow2 disk: 20 -summary: Basic smoke test +summary: Execute booted tests execute: how: tmt - script: bootc status + # There's currently two dynamic test frameworks; python and nushell. + # python is well known and understood. nushell is less well known, but + # is quite nice for running subprocesses and the like while making + # it easy to parse JSON etc. + script: | + set -xeu + pytest tests/booted/*.py + ls tests/booted/*-test-*.nu |sort -n | while read t; do nu $t; done diff --git a/tests/booted/.gitignore b/tests/booted/.gitignore new file mode 100644 index 00000000..bee8a64b --- /dev/null +++ b/tests/booted/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/tests/booted/001-test-status.nu b/tests/booted/001-test-status.nu new file mode 100644 index 00000000..49ce8c46 --- /dev/null +++ b/tests/booted/001-test-status.nu @@ -0,0 +1,8 @@ +use std assert +use tap.nu + +tap begin "verify bootc status --json looks sane" + +let st = bootc status --json | from json +assert equal $st.apiVersion org.containers.bootc/v1alpha1 +tap ok diff --git a/tests/booted/README.md b/tests/booted/README.md new file mode 100644 index 00000000..7c138d27 --- /dev/null +++ b/tests/booted/README.md @@ -0,0 +1,4 @@ +# Booted tests + +These are intended to run via tmt; use e.g. +`make test-tmt`. diff --git a/tests/booted/basic.py b/tests/booted/basic.py new file mode 100644 index 00000000..6253c13d --- /dev/null +++ b/tests/booted/basic.py @@ -0,0 +1,12 @@ +# Tests which are read-only/nondestructive + +import json +import subprocess + +def run(*args): + subprocess.check_call(*args) + +def test_bootc_status(): + o = subprocess.check_output(["bootc", "status", "--json"]) + st = json.loads(o) + assert st['apiVersion'] == 'org.containers.bootc/v1alpha1' diff --git a/tests/booted/tap.nu b/tests/booted/tap.nu new file mode 100644 index 00000000..096638fa --- /dev/null +++ b/tests/booted/tap.nu @@ -0,0 +1,15 @@ +# A simple nushell "library" for the +# "Test anything protocol": +# https://testanything.org/tap-version-14-specification.html +export def begin [description] { + print "TAP version 14" + print $description +} + +export def ok [] { + print "ok" +} + +export def fail [] { + print "not ok" +} diff --git a/xtask/src/xtask.rs b/xtask/src/xtask.rs index ba28f376..843f264c 100644 --- a/xtask/src/xtask.rs +++ b/xtask/src/xtask.rs @@ -146,6 +146,8 @@ fn man2markdown(sh: &Shell) -> Result<()> { #[context("test-integration")] fn test_tmt(sh: &Shell) -> Result<()> { cmd!(sh, "cargo run -p tests-integration run-vm prepare-tmt").run()?; + // cc https://pagure.io/testcloud/pull-request/174 + cmd!(sh, "rm -vf /var/tmp/tmt/testcloud/images/disk.qcow2").run()?; cmd!(sh, "tmt run plans -n integration-run").run()?; Ok(()) }