fix(tags): exclude molecule scenarios from tag scan; clarify ADR enforcement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
24b5e9361e
commit
2e5a1e1e23
3 changed files with 22 additions and 2 deletions
|
|
@ -90,6 +90,7 @@ keeps building groups from the `group` output field, the single source of truth.
|
|||
opt-in/playbook tags. `scripts/check-tags.py` (run by `make lint`, covered by
|
||||
`tests/test_check_tags.py`) scans `roles/` and `playbooks/` and fails on any tag
|
||||
outside `{role directory names} ∪ {tests/tags.yml entries}`.
|
||||
Molecule scenario files (`roles/*/molecule/**`) are excluded from the scan — they are test orchestration, not the production run-targeting surface this standard governs.
|
||||
|
||||
## Extending the vocabulary
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ leaves a paper trail.
|
|||
- Targeted runs are predictable: only two kinds of tags exist, one of them mechanical.
|
||||
- Over-tagging is structurally resisted (closed list + lint enforcement).
|
||||
- Intersection targeting is unavailable by design.
|
||||
- Authors must keep role tags = role names; the linter enforces it.
|
||||
- Authors must keep role tags = role names. The linter enforces the *vocabulary* (every tag must be a known role name or an approved tag); the role-tag-equals-role-name rule itself is a convention the linter does not separately check.
|
||||
|
||||
## Related
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ def role_names(repo=REPO):
|
|||
|
||||
def collect_tags(node):
|
||||
"""Recursively collect every static tag string under any 'tags:' key."""
|
||||
# Matches any dict key literally named `tags`; Ansible-tag semantics assumed.
|
||||
tags = set()
|
||||
if isinstance(node, dict):
|
||||
for key, value in node.items():
|
||||
|
|
@ -81,7 +82,12 @@ def iter_yaml_files(repo=REPO, scan_dirs=SCAN_DIRS):
|
|||
if not base.is_dir():
|
||||
continue
|
||||
for ext in ("*.yml", "*.yaml"):
|
||||
yield from sorted(base.rglob(ext))
|
||||
for path in sorted(base.rglob(ext)):
|
||||
# Molecule scenarios are test orchestration, not the production
|
||||
# run-targeting surface this standard governs (ADR-019). Skip them.
|
||||
if "molecule" in path.relative_to(base).parts:
|
||||
continue
|
||||
yield path
|
||||
|
||||
|
||||
def find_violations(used, allowed):
|
||||
|
|
|
|||
|
|
@ -70,3 +70,16 @@ def test_find_violations_flags_unknown_tag():
|
|||
|
||||
def test_find_violations_empty_when_all_allowed():
|
||||
assert ct.find_violations({"base", "firewall"}, {"base", "firewall"}) == []
|
||||
|
||||
|
||||
def test_iter_yaml_files_skips_molecule(tmp_path):
|
||||
role = tmp_path / "roles" / "demo"
|
||||
(role / "tasks").mkdir(parents=True)
|
||||
(role / "tasks" / "main.yml").write_text("---\n")
|
||||
mol = role / "molecule" / "default"
|
||||
mol.mkdir(parents=True)
|
||||
(mol / "verify.yml").write_text("---\n")
|
||||
found = list(ct.iter_yaml_files(repo=tmp_path, scan_dirs=("roles",)))
|
||||
names = [p.name for p in found]
|
||||
assert "main.yml" in names
|
||||
assert "verify.yml" not in names
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue