Skip to content

Commit cb2bdcd

Browse files
committed
ci: Use cargo-nextest for integration tests
The nextest config (.config/nextest.toml) was previously dead code — tests were run via the libtest-mimic binary directly. Switch the Justfile targets and CI workflow to prefer nextest when available, so the parallelism controls (threads-required = 2 for privileged VM tests) actually take effect and prevent OOM kills on 16 GB CI runners. Also fix the nextest filter syntax: ~^foo never matches because nextest's ~ operator treats ^ as a literal character. Use /regex/ syntax instead. Assisted-by: OpenCode (Claude Opus 4) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent cef0e7e commit cb2bdcd

4 files changed

Lines changed: 50 additions & 9 deletions

File tree

.config/nextest.toml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ failure-output = "immediate"
1414
success-output = "never"
1515
status-level = "pass"
1616

17+
# Tests that pull OCI images need more time (especially on cold CI runners)
18+
[[profile.default.overrides]]
19+
filter = 'test(/digest_stability|oci_pull/)'
20+
slow-timeout = { period = "300s", terminate-after = 2 }
21+
1722
# Profile for integration tests — run with limited parallelism due to QEMU/KVM resources
1823
[profile.integration]
1924
test-threads = 2
@@ -30,7 +35,12 @@ path = "junit.xml"
3035
store-success-output = true
3136
store-failure-output = true
3237

33-
# VM tests boot an ephemeral QEMU instance per test, limit parallelism
38+
# Privileged tests boot an ephemeral QEMU instance per test — limit
39+
# parallelism to avoid OOM kills on 16 GB CI runners.
40+
# Requiring all 2 threads effectively serialises them.
41+
#
42+
# NOTE: use /regex/ syntax, not ~substring — the ~ operator treats ^ $ as
43+
# literal characters, so ~^foo never matches anything.
3444
[[profile.integration.overrides]]
35-
filter = 'test(~^vm_)'
36-
threads-required = 4
45+
filter = 'test(/^privileged_/)'
46+
threads-required = 2

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
- uses: actions/checkout@v6
5252
- uses: bootc-dev/actions/bootc-ubuntu-setup@main
5353
- uses: dtolnay/rust-toolchain@stable
54+
- uses: taiki-e/install-action@nextest
5455
- uses: Swatinem/rust-cache@v2
5556
- run: just test-integration
5657

@@ -114,6 +115,7 @@ jobs:
114115
libvirt: true
115116

116117
- uses: dtolnay/rust-toolchain@stable
118+
- uses: taiki-e/install-action@nextest
117119

118120
- uses: Swatinem/rust-cache@v2
119121

Justfile

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,37 @@ cfsctl_features := env("COMPOSEFS_CFSCTL_FEATURES", "pre-6.15")
5454
_test_image := if base_image =~ "debian" { "localhost/composefs-rs-test-debian:latest" } else if base_image =~ "stream9" { "localhost/composefs-rs-test-c9s:latest" } else { "localhost/composefs-rs-test:latest" }
5555

5656
# Run unprivileged integration tests against the cfsctl binary (no root, no VM)
57-
test-integration: build
58-
CFSCTL_PATH=$(pwd)/target/debug/cfsctl cargo run -p integration-tests --bin cfsctl-integration-tests -- --skip privileged_
57+
# Prefers nextest for parallelism control and better UX; falls back to direct harness.
58+
test-integration *ARGS: build
59+
#!/usr/bin/env bash
60+
set -euo pipefail
61+
export CFSCTL_PATH=$(pwd)/target/debug/cfsctl
62+
if command -v cargo-nextest &> /dev/null; then
63+
cargo nextest run -p integration-tests -E 'not test(/^privileged_/)' {{ ARGS }}
64+
else
65+
cargo test -p integration-tests --test cfsctl-integration-tests -- --skip privileged_ {{ ARGS }}
66+
fi
5967
6068
# Build the test container image for VM-based integration tests
6169
_integration-container-build:
6270
podman build --build-arg base_image={{base_image}} --build-arg cfsctl_features={{cfsctl_features}} -t {{_test_image}} .
6371

6472
# Run all integration tests including privileged VM tests (requires podman + libvirt)
65-
test-integration-vm: build _integration-container-build
66-
COMPOSEFS_TEST_IMAGE={{_test_image}} \
67-
CFSCTL_PATH=$(pwd)/target/debug/cfsctl \
68-
cargo run -p integration-tests --bin cfsctl-integration-tests
73+
# Uses nextest with the integration profile for parallelism control of VM tests.
74+
test-integration-vm *ARGS: build _integration-container-build
75+
#!/usr/bin/env bash
76+
set -euo pipefail
77+
export COMPOSEFS_TEST_IMAGE={{_test_image}}
78+
export CFSCTL_PATH=$(pwd)/target/debug/cfsctl
79+
if command -v cargo-nextest &> /dev/null; then
80+
cargo nextest run -P integration -p integration-tests {{ ARGS }}
81+
else
82+
cargo test -p integration-tests --test cfsctl-integration-tests -- {{ ARGS }}
83+
fi
84+
85+
# Install cargo-nextest if not already installed
86+
install-nextest:
87+
@which cargo-nextest > /dev/null 2>&1 || cargo install cargo-nextest --locked
6988

7089
# Run everything: checks + full integration tests including VM
7190
ci: check test-integration-vm

crates/integration-tests/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,27 @@
22
name = "integration-tests"
33
publish = false
44
description = "Integration tests for composefs-rs (not published)"
5+
autobins = false
6+
autotests = false
57

68
edition.workspace = true
79
license.workspace = true
810
repository.workspace = true
911
rust-version.workspace = true
1012
version.workspace = true
1113

14+
# The integration test runner is declared as both [[bin]] (for the container
15+
# image build) and [[test]] (so nextest discovers the libtest-mimic tests).
16+
# Cargo warns about the shared source file — this is harmless.
1217
[[bin]]
1318
name = "cfsctl-integration-tests"
1419
path = "src/main.rs"
1520

21+
[[test]]
22+
name = "cfsctl-integration-tests"
23+
path = "src/main.rs"
24+
harness = false
25+
1626
[[bin]]
1727
name = "test-cleanup"
1828
path = "src/cleanup.rs"

0 commit comments

Comments
 (0)