Skip to content

fix(tests): isolate from host /etc/hal0 + /var/lib/hal0 state — fixes 9 CI failures#67

Merged
thinmintdev merged 2 commits into
mainfrom
fix/test-isolation-ci-greens
May 21, 2026
Merged

fix(tests): isolate from host /etc/hal0 + /var/lib/hal0 state — fixes 9 CI failures#67
thinmintdev merged 2 commits into
mainfrom
fix/test-isolation-ci-greens

Conversation

@thinmintdev
Copy link
Copy Markdown
Contributor

Summary

Closes the remaining red CI test failures by fixing test isolation. After PR #63 made lint green, 9 test failures remained on main — all rooted in the same bug.

Root cause

ModelsConfig.roots and ModelsConfig.pull_root had hardcoded /var/lib/hal0/models defaults that ignored HAL0_HOME. When tests set HAL0_HOME via the tmp_hal0_home fixture, registry helpers (_pull_root, the auto-scan boot path) still wrote into the host FHS layout — failing with PermissionError on CI (where /var/lib/hal0 isn't writable) and host-state leakage on the LXC.

Two related papercuts surfaced once isolation was applied:

  1. The global app / client fixtures didn't compose with tmp_hal0_home, so TestClient-driven tests booted against host /etc/hal0/slots/*.toml and registered live upstreams — breaking the 4 test_v1_dispatch tests that assert an empty upstream catalog.
  2. test_help_lists_new_flags substring-matched --provider in result.output, but Click colours the leading dash in a separate ANSI sequence on coloured terminals.

Changes

  • src/hal0/config/schema.pyModelsConfig.roots and pull_root now use default_factory=lambda: str(paths.models_dir()). Production behaviour unchanged (resolves to /var/lib/hal0/models when HAL0_HOME is unset); tests now get a tmp-path default automatically.
  • tests/conftest.py — the app fixture takes tmp_hal0_home, so every client / app test is filesystem-isolated by default.
  • tests/cli/test_slot_create_flags.py::test_help_lists_new_flags — strip ANSI before substring assertions.
  • tests/api/test_config_model_roots.py::test_get_models_config_returns_defaults — assertion updated to reflect the new HAL0_HOME-aware defaults (previously inadvertently validating the bug).

Test plan

  • Previously-failing tests all pass — pytest tests/api/test_v1_dispatch.py tests/registry/test_curated_image_models.py tests/registry/test_pull.py tests/cli/test_slot_create_flags.py → 35/35
  • Full suite (minus tests/slots/test_integration.py, tests/openwebui/, tests/providers/test_moonshine_server.py which need a real environment / numpy) — 1003 passed, 0 failed
  • Production behaviour unchanged when HAL0_HOME is unset

🤖 Generated with Claude Code

The 9 CI test failures + 5 LXC test failures had the same root cause:
the schema's `pull_root` (and `roots`) defaults are hardcoded to
`/var/lib/hal0/models`, ignoring HAL0_HOME. When tests set HAL0_HOME
via the `tmp_hal0_home` fixture, registry helpers (`_pull_root`, the
auto-scan boot path) still wrote into the host FHS layout — failing
with PermissionError on CI (`/var/lib/hal0` not writable) and with
host-state leakage on the LXC.

Plus two related papercuts surfaced once isolation was applied:

1. The global `app` / `client` fixtures didn't compose with
   `tmp_hal0_home`, so TestClient-driven tests booted against the
   host's `/etc/hal0/slots/*.toml` and registered live upstreams —
   breaking the 4 `test_v1_dispatch` tests that assert an empty data
   array with no upstreams.
2. `test_help_lists_new_flags` matched `--provider` in `result.output`
   raw text, but Click splits the leading dash into a separate ANSI
   colour sequence on coloured terminals, breaking the substring match.

## Changes

- `src/hal0/config/schema.py`: `ModelsConfig.roots` and `pull_root`
  switch to `default_factory=lambda: str(paths.models_dir())` /
  `[str(paths.models_dir())]`. Production behaviour identical (the
  factory still resolves to `/var/lib/hal0/models` when HAL0_HOME is
  unset); tests now get a tmp-path default automatically.
- `tests/conftest.py`: the `app` fixture takes `tmp_hal0_home`, so
  every test using `client` / `app` is filesystem-isolated by default.
- `tests/cli/test_slot_create_flags.py::test_help_lists_new_flags`:
  strip ANSI before substring assertions.

## Test plan

- [x] Fixed 4× v1_dispatch failures on LXC
- [x] Fixed 1× test_curated_image_models::test_final_path_falls_back_to_default_layout on LXC + CI
- [x] Fixed 4× CI-only failures (test_curated_image_models::test_run_pull_*, test_pull.py::test_run_pull_*) — PermissionError on /var/lib/hal0
- [x] Fixed 1× CI-only test_slot_create_flags::test_help_lists_new_flags
- [x] No production-behaviour regressions: paths.models_dir() resolves to /var/lib/hal0/models when HAL0_HOME is unset

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev force-pushed the main branch 2 times, most recently from 0c4ce34 to 5458a0d Compare May 21, 2026 04:16
moonshine_server.py imports numpy at module top — it's a runtime dep
of the toolbox container, not of hal0's dev extras. CI was erroring at
collection time with ModuleNotFoundError: No module named 'numpy'.
Skip the whole module when numpy is absent, matching how it ran before
(silently skipped rather than failed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev merged commit a53110d into main May 21, 2026
4 of 6 checks passed
thinmintdev added a commit that referenced this pull request May 21, 2026
The hal0-toolbox-vulkan image's ENTRYPOINT is llama-server itself
(packaging/toolbox/vulkan.Dockerfile:154). The smoke-test job was
running `docker run image /bin/bash -c '...'`, which passes /bin/bash
as the first arg to llama-server, producing:

    error: invalid argument: /bin/bash

Override the entrypoint to /bin/bash for the proof-of-life check.

Closes the slot-integration CI failure that was inherited by every
PR off main (#64, #67).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev deleted the fix/test-isolation-ci-greens branch May 22, 2026 04:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant