Skip to content

[quality] test: unit coverage for files/installer/repart.d target-disk layout (tests/unit/test_repart_layout.py) - #41

Merged
castrojo merged 1 commit into
mainfrom
quality/test-installer-repart-layout
Sep 5, 2026
Merged

castrojo merged 1 commit into
mainfrom
quality/test-installer-repart-layout

Conversation

@kubestellar-hive

Copy link
Copy Markdown
Contributor

Test Improvement

Adds tests/unit/test_repart_layout.py — pure static coverage for the systemd-repart recipe the live installer follows when partitioning the target disk.

Claimed ground (for overlap checks by later work):

  • new file: tests/unit/test_repart_layout.py
  • files under test (read-only): files/installer/repart.d/10-esp.conf, 20-root-a.conf, 30-var.conf
  • cross-file reads: elements/**/*.bst (grep for the Label= stamped on the installer media data partition) and files/os/sysupdate.d/50-root.transfer ([Target] MatchPattern)
  • no production file is modified, and no Justfile recipe or workflow is added

Why

Nothing in CI parses files/installer/repart.d/ today. A bad Type=, an inverted size bound, or a CopyBlocks= source that no longer matches the label stamped on the installer media data partition surfaces only as a failed or silently mis-partitioned install — after a 180-minute image build.

Invariants covered (18 tests, 1 strict xfail)

  • each config parses and holds exactly one [Partition] section; filenames are NN-name.conf with unique ordering prefixes
  • the layout is exactly one esp, one root, one var
  • SizeMinBytes always set, never greater than SizeMaxBytes
  • GPT labels unique, so sysupdate Path=auto stays unambiguous
  • ESP is vfat, ≥100M, and capped
  • root CopyBlocks= addresses the media by /dev/disk/by-partlabel/…, and some element under elements/ actually stamps that label (bluefin-installer-data)
  • root grows its filesystem and is capped; var is xfs, FactoryReset=yes, growable and uncapped as the tail partition
  • the installed root label appears in the [Target] MatchPattern of 50-root.transfer

The strict xfail

test_every_sysupdate_root_target_is_provisioned_by_the_installer is xfail(strict=True). It records the A/B gap already documented in docs/MVP_1_0_READINESS.md and docs/skills/gap-analysis-distros.md: 50-root.transfer names root-a and root-b, but the installer provisions only root-a, so systemd-sysupdate has no inactive slot to stage into. Strict means the test turns red the moment root-b lands, prompting whoever adds it to enable the guard. This PR does not attempt the fix — that is production change, out of scope for quality.

Verification

$ python3 -m pytest tests/unit/test_repart_layout.py -q
18 passed, 1 xfailed in 0.10s

Mutation-checked: rewriting CopyBlocks= to an unstamped label, and setting root SizeMinBytes=32G above SizeMaxBytes=16G, each fail the expected test.

Runner

No Justfile change is included on purpose — open PR #30 already adds test-unit: python3 -m pytest tests/unit -q, which picks this module up automatically. Deliberately disjoint from the other open server PRs: #38 (files/bin/system-container), #30 (.github/scripts/docs-checks.py), #34 (project.conf/Justfile release-version), #40 (CPU-arch identity), #36/#37/#29 (sysupdate keyring, k3s kubeconfig mode, sshd), #22/#25/#26/#27 (PXE, bluefin-server-installer.bst).


Filed by quality agent (hold-gated mode). Human review required — do not merge without review, and do not remove the hold label.

— hive: agent=quality backend=copilot model=claude-opus-5

…k layout

Adds tests/unit/test_repart_layout.py, a pure static test module over the
systemd-repart recipe the live installer follows when partitioning the
target disk. Nothing in CI parsed these files before, so a bad Type=, an
inverted size bound, or a CopyBlocks= source that no longer matches the
label stamped on the installer media data partition could only surface as
a failed or mis-partitioned install.

Covered invariants:
  - every files/installer/repart.d/*.conf parses and holds exactly one
    [Partition] section, with an NN-name.conf ordering prefix that is unique
  - the layout is exactly one esp, one root and one var partition
  - SizeMinBytes is always set and never exceeds SizeMaxBytes
  - GPT labels are unique, so sysupdate Path=auto stays unambiguous
  - ESP is vfat, at least 100M, and capped
  - root CopyBlocks= addresses the installer media by partition label, and
    some element under elements/ actually stamps that label
  - root grows its filesystem and is capped; var is growable, xfs,
    FactoryReset=yes and uncapped as the tail partition
  - the installed root label is among the [Target] MatchPattern labels in
    files/os/sysupdate.d/50-root.transfer

One strict xfail records the A/B slot gap already documented in
docs/MVP_1_0_READINESS.md: 50-root.transfer names root-a and root-b but the
installer provisions only root-a. Strict means the test flips to a failure
the moment root-b is added, prompting the guard to be enabled.

No production files are touched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: sec-check[bot] <sec-check[bot]@users.noreply.github.com>

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New static tests genuinely check repart.d/*.conf invariants against real cross-file sources (elements/*.bst, sysupdate transfer), with an honest xfail(strict=True) for a documented known gap. CI green.


Generated by Claude Code

@castrojo castrojo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved by @castrojo for Hive auto-merge on green CI.

@castrojo
castrojo merged commit 7398026 into main Sep 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold Work is intentionally paused.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants