Files
devx/docs/specs/DEVX-177.md
T
kireto ca55cfd29a
Post-merge / detect-and-configure (push) Successful in 9s
Post-merge / release-and-maintain (push) Successful in 1m3s
DEVX-177: fix: fail-open molecule selection and honest fast-path contract
2026-09-23 08:10:19 +00:00

3.6 KiB

DEVX-177: Honest molecule selection — fail-open coverage and real command contract

Problem

devx.molecule.molecule_changed and devx.ci.fast_molecule violate the S09/REQ-9 honesty contract in three ways:

  1. Silent skips. detect_changed_roles only knows four playbooks and ansible/roles/. Changes to restore.yml, deploy-sso-bridge.yml, upgrade-postgres.yml, rolling-update-gitea.yml, update-alertmanager.yml, build-image.yml, playbooks/_tasks/, playbooks/tasks/, or ansible/group_vars/ trigger zero molecule coverage — the fast path passes by skipping work.
  2. Phantom targets. ROLE_TARGET_MAP includes sso_config (role moved to the sso-bridge repo) and emits molecule-crowdsec / molecule-disk-cleanup targets that do not exist in infra's Makefile. Playbook mappings also inject absent roles, so make molecule-changed can select nonexistent targets.
  3. Dishonest contract. fast_molecule documents "converge + verify only, no idempotence" and builds molecule test -s X --destroy=never --platform-name=... commands that nothing executes — CI actually runs full molecule test -s X via run_molecule_scenario.py (which does include idempotence where the scenario defines it).

Approach

REQ-1: Fail-open coverage in detect_changed_roles — add the missing playbook→role mappings; ansible/group_vars/** and any other ansible/playbooks/** file (including _tasks//tasks/) not explicitly mapped select all molecule-covered roles. ansible/environments/ stays unmapped (env data is covered by unit/deploy tests, not molecule) and is documented as such.

REQ-2: Selection only emits roles that exist — detect_changed_roles gains a roles_dir parameter; role names from file paths and playbook maps are kept only when <roles_dir>/<role> exists. Shared-path and fail-open "all roles" resolution returns only directories under roles_dir containing a molecule/ dir (untestable roles select nothing rather than phantom targets).

REQ-3: Honest fast-molecule contract — build_molecule_commands emits exactly what the CI runner executes (molecule test -s <scenario>); docstrings state the real sequence (full molecule test per scenario on changed roles, single platform as configured by the scenario) instead of the old "converge + verify only" claim.

Test Plan

  • Update test_molecule_changed.py: unmapped playbook → all present roles; group_vars change → all; mapped playbook → mapped roles only; role absent from roles_dir → filtered out; shared path → only roles with molecule/ dirs.
  • Update test_fast_molecule.py: emitted commands are molecule test -s <scenario> with no --destroy/--platform-name flags.
  • make pytest-cov (100% gate), make lint-all.

Deploy Plan

Merge → devx release publishes automatically → infra dep-PR bumps the pin; the honest selection takes effect on the next infra CI run.

Rollback Plan

Revert the squash commit; previous (under-covering) selection returns — acceptable short-term because coverage only widens with this change.

Acceptance Criteria

  • REQ-1: All ansible/playbooks/** and ansible/group_vars/** changes select molecule coverage; unmapped files fail open to all testable roles.
  • REQ-2: No nonexistent roles or make targets are emitted; sso_config no longer appears when absent from roles_dir.
  • REQ-3: build_molecule_commands output matches the executed CI command shape; module docstrings describe the real sequence.
  • Unit tests cover every new behavior; 100% coverage maintained.