buildstream: run the pytest suite as a NixOS VM test

buildbox-casd finds `buildbox-fuse` on PATH and defaults to real
FUSE-based staging, which needs `/dev/fuse` and a working mount path
that the Nix build sandbox doesn't provide, hence the
`BUILDBOX_STAGER=copy-or-link` workaround forcing the hardlink/copy
fallback stager, and the `/usr/bin/env sh` shebang patch for the dummy
buildbox-casd scripts in tests/internals/cascache.py.

Add nixosTests.buildstream and point passthru.tests.pytest at it
instead: so the suite exercises the actual FUSE-backed staging path.

The main derivation no longer builds the pytest/test-fixture inputs at
all (they're only needed by the VM test), keeping just
`versionCheckHook` for the existing install-check.

`bst` is a buildPythonApplication, so its own site-packages only
contains buildstream's own files, not the propagated runtime deps
(protobuf, grpcio, click, ...) that only reach the wrapped `bst`
script's own PYTHONPATH; `toPythonModule` reinterprets it as a regular
library so `withPackages` pulls in its full dependency closure for
`pytest` to import from.

The default `diskSize = "auto"` only sizes the VM's root filesystem to
fit the system closure, with no scratch space; the suite builds real
CAS/cache artifacts under pytest's basetemp for hundreds of
parametrized cases, easily exceeding that. Bumped disk/memory sizing
to comfortably cover a full run.

Verified this run passes: `nix-build -E 'let pkgs = import ./. {}; in
pkgs.nixosTests.buildstream.test'` completes successfully.

Assisted-by: Claude <noreply@anthropic.com>
This commit is contained in:
Dom Rodriguez
2026-09-28 00:05:32 +01:00
parent 751359fcc0
commit 2151ee2fcb
3 changed files with 84 additions and 40 deletions

View File

@@ -380,6 +380,7 @@ in
budgie = runTest ./budgie.nix;
buildbot = runTest ./buildbot.nix;
buildkite-agents = runTest ./buildkite-agents.nix;
buildstream = runTest ./buildstream.nix;
bulwark = runTest ./bulwark.nix;
c2fmzq = runTest ./c2fmzq.nix;
caddy = runTest ./caddy.nix;

View File

@@ -0,0 +1,71 @@
{ pkgs, ... }:
let
bst = pkgs.buildstream;
# `bst` is a buildPythonApplication; its own site-packages only contains
# buildstream's own files, not the propagated runtime deps (protobuf,
# grpcio, click, ...) that only reach the wrapped `bst` script's PYTHONPATH.
# `toPythonModule` reinterprets it as a regular library so its full
# dependency closure gets merged in by `withPackages` below.
bstModule = pkgs.python3.pkgs.toPythonModule bst;
# Test fixture plugin package used by test_source_mirror_plugin[pip]; upstream
# normally installs this via tox before running the pip-origin plugin loading test.
samplePlugins = pkgs.python3Packages.buildPythonPackage {
pname = "sample-plugins";
version = "1.2.3";
pyproject = true;
build-system = [ pkgs.python3Packages.setuptools ];
src = "${bst.src}/tests/plugins/sample-plugins";
dontCheck = true;
};
in
{
name = "buildstream";
meta.maintainers = with pkgs.lib.maintainers; [ shymega ];
nodes.machine =
{ pkgs, ... }:
{
# The default "auto" diskSize only sizes the root filesystem to fit
# the system closure, with no scratch space; the suite builds real
# CAS/cache artifacts under pytest's basetemp (`./tmp`, per
# setup.cfg) for hundreds of parametrized cases, which exhausts that
# in a few minutes (`OSError: could not create numbered dir`).
virtualisation.diskSize = 16 * 1024;
virtualisation.memorySize = 2048;
environment.systemPackages = [
(pkgs.python3.withPackages (
ps: with ps; [
bstModule
pexpect
pyftpdlib
pytest
pytest-datafiles
pytest-env
pytest-timeout
pytest-xdist
samplePlugins
]
))
bst
pkgs.buildbox
pkgs.gitMinimal
];
};
testScript = ''
machine.succeed("cp -r ${bst.src} /tmp/src && chmod -R u+w /tmp/src")
# The dummy buildbox-casd scripts spawned by tests/internals/cascache.py use
# an `/usr/bin/env sh` shebang, which doesn't exist here either.
machine.succeed(
"sed -i 's|#!/usr/bin/env sh|#!${pkgs.runtimeShell}|'"
+ " /tmp/src/tests/internals/cascache.py"
)
machine.succeed("cd /tmp/src && HOME=/root pytest")
'';
}

View File

@@ -3,7 +3,7 @@
python3Packages,
fetchFromGitHub,
gitUpdater,
runtimeShell,
nixosTests,
# buildInputs
buildbox,
@@ -15,8 +15,6 @@
installShellFiles,
# tests
addBinToPathHook,
gitMinimal,
versionCheckHook,
# Optional features
@@ -73,46 +71,16 @@ python3Packages.buildPythonApplication (finalAttrs: {
patch
];
# The dummy buildbox-casd scripts spawned by tests/internals/cascache.py use
# an `/usr/bin/env sh` shebang, which doesn't exist in the Nix build sandbox.
postPatch = ''
substituteInPlace tests/internals/cascache.py \
--replace-fail '#!/usr/bin/env sh' '#!${runtimeShell}'
'';
# /dev/fuse is not available inside the Nix build sandbox, so buildbox-casd's
# default FUSE-based staging strategy cannot work here. Force the hardlink/copy
# stager instead (this is a real, supported buildbox-casd staging mode, not a
# workaround: https://gitlab.com/BuildGrid/buildbox/buildbox/-/blob/main/casd/buildboxcasd_server.cpp).
preCheck = ''
export BUILDBOX_STAGER=copy-or-link
'';
# default FUSE-based staging strategy cannot work here, and the shebang used
# by tests/internals/cascache.py's dummy buildbox-casd scripts
# (`/usr/bin/env sh`) doesn't exist there either. The pytest suite is run as
# a NixOS VM test instead, where both of those are available; see
# `passthru.tests.pytest`.
pythonImportsCheck = [ "buildstream" ];
nativeCheckInputs = [
addBinToPathHook
buildbox
gitMinimal
python3Packages.pexpect
python3Packages.pyftpdlib
python3Packages.pytest-datafiles
python3Packages.pytest-env
python3Packages.pytest-timeout
python3Packages.pytest-xdist
python3Packages.pytestCheckHook
versionCheckHook
# Test fixture plugin package used by test_source_mirror_plugin[pip]; upstream
# normally installs this via tox before running the pip-origin plugin loading test.
(python3Packages.buildPythonPackage {
pname = "sample-plugins";
version = "1.2.3";
pyproject = true;
build-system = [ python3Packages.setuptools ];
src = "${finalAttrs.src}/tests/plugins/sample-plugins";
dontCheck = true;
})
];
postInstall = ''
@@ -123,8 +91,12 @@ python3Packages.buildPythonApplication (finalAttrs: {
versionCheckProgram = "${placeholder "out"}/bin/bst";
passthru.updateScript = gitUpdater {
ignoredVersions = "dev";
passthru = {
updateScript = gitUpdater {
ignoredVersions = "dev";
};
tests.pytest = nixosTests.buildstream;
};
meta = {