Skip to content
This repository was archived by the owner on Sep 8, 2026. It is now read-only.

[architect] refactor: single source of truth for wizard step reachability — builder.py templates vs gresource.xml/recipe.json/defaults+layouts step classes - #211

Open
kubestellar-hive[bot] wants to merge 1 commit into
devfrom
arch/step-registry-drift-gate
Open

kubestellar-hive[bot] wants to merge 1 commit into
devfrom
arch/step-registry-drift-gate

Conversation

@kubestellar-hive

Copy link
Copy Markdown

Refactor

Claimed ground: tests/unit/test_step_registry.py (new file, the only file this PR touches). It reads — and does not modify — bootc_installer/utils/builder.py (templates), bootc_installer/bootc-installer.gresource.xml, recipe.json, and the step classes in bootc_installer/defaults/ and bootc_installer/layouts/.

builder.py's templates dict decides which wizard steps are ever constructed, but four other surfaces independently declare that a step exists:

  1. bootc_installer/defaults/meson.build sources — installs the module
  2. bootc_installer/meson.build blueprint list — compiles its .blp
  3. bootc_installer/bootc-installer.gresource.xml — embeds its .ui
  4. recipe.json steps.<key>.template — asks for it by name

Nothing made them agree with builder.templates, so step modules accumulated that ship, translate, and look production-ready but are never reachable — and the reverse drift only fails on the live ISO.

What this adds

tests/unit/test_step_registry.py — a static gate (stdlib ast/re/ElementTree only; it never imports bootc_installer.defaults.*, because the unit CI job installs only pytest and has no gi/GTK). Five checks:

check drift it catches
test_registered_classes_are_defined_where_builder_imports_them templates naming a class its module no longer defines
test_registered_step_resources_are_embedded_in_the_gresource registered step whose @Gtk.Template(resource_path=) is not in the gresource → wizard dies at construction on the ISO
test_bundled_recipe_only_names_registered_templates Builder.__load's if step["template"] in templates: drops an unknown/typo'd name silently, with no error
test_unregistered_step_classes_are_declared_dead a new step module that ships but is never registered
test_wizard_page_resources_have_a_python_consumer a gtk/default-*.ui embedded with no resource_path= referencing it

Step classes are identified by implementing get_finals() — the interface Builder.get_finals actually calls — not by name, so helper widgets and modals in the same modules (BootcDefaultDiskEntry, BootcDefaultDiskPartModal, BootcDefaultDiskConfirmModal) are correctly excluded.

Drift it records today

The two allowlists are subset-asserted, so nothing here needs updating when an entry goes away. They currently document five unreachable step classes — BootcDefaultNvidia, BootcDefaultVm, BootcDefaultNetwork, BootcDefaultTheme, BootcLayoutPreferences — plus gtk/default-hardware.ui, which is listed in meson.build:15 and gresource.xml:29 and has no Python consumer anywhere.

Relationship to #187 / PR #194

PR #194 deletes defaults/{keyboard,language,timezone}.py and their blueprints/tests. This PR touches none of those files and adds no second implementation of that cleanup — it fixes the mechanism that let those orphans accumulate, and covers the remaining cluster #194 does not address. The allowlists name those three classes and their .ui files so the gate is green whether or not #194 has landed; verified by re-running the suite against a simulated post-#194 tree.

Verification

  • All 5 checks mutation-tested: each was individually made to fail by injecting real drift (typo'd recipe.json template, .ui removed from gresource, renamed registered class, new unregistered step module, new orphan page resource), then restored to green.
  • Simulated PR cleanup: remove dead keyboard/language/timezone wizard steps #194 merged (deleted the three modules + their gresource entries): 5 passed.
  • Full unit suite: 719 passed, 2 skipped. The 5 test_image_helpers.py::TestImagesCatalogIntegrity failures are pre-existing and caused only by the fisherman submodule not being checked out locally; CI uses submodules: recursive.

No production code touched. No behavior change.

Refs #210


Filed by architect agent (ACMM L5 — hold-gated mode). Hold-gated: human review required.

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

…lity

builder.py's `templates` dict decides which wizard steps are ever
constructed, but four other surfaces independently declare that a step
exists: defaults/meson.build sources, meson.build's blueprint list,
bootc-installer.gresource.xml, and recipe.json's steps.<key>.template.
Nothing made them agree, so step modules accumulated that ship,
translate, and look production-ready but are never reachable.

Adds tests/unit/test_step_registry.py, a static (stdlib-only, no gi)
drift gate that makes builder.templates the declared authority:

- registered classes resolve to a real class in the imported module
- registered steps' @Gtk.Template resource_path is embedded in the
  gresource (otherwise the wizard dies at construction on the live ISO)
- recipe.json names only registered templates — Builder.__load's
  `if step["template"] in templates` drops unknown names silently
- step classes on disk (identified by get_finals(), the interface
  Builder.get_finals calls) are registered or explicitly declared dead
- every gtk/default-*.ui in the gresource has a resource_path consumer

The two allowlists are subset-asserted, so the gate is green whether or
not #194 has landed. They currently record five unreachable step classes
(nvidia, vm, network, theme, layouts/preferences) plus the orphaned
gtk/default-hardware.ui, which has no Python consumer at all.

No production code or behavior changes.

Refs #210

Signed-off-by: sec-check[bot] <sec-check[bot]@users.noreply.github.com>
@kubestellar-hive kubestellar-hive Bot added the hold Work is intentionally paused. label Sep 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

hold Work is intentionally paused.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants