Phase 1a-c of REFACTORING-PLAN.md: - Extract devx.ci.wait_for_checks module (replaces inline polling in grm ci.yml) with 100% test coverage (26 tests) - Consolidate 5 Ansible check tools into composable devx.tools.ansible_checks/ subpackage with shared utilities (AnsibleFileFinder, AnsibleYAMLParser, ViolationReporter); old modules remain as thin backward-compat wrappers - Merge ci/discover_runners into molecule/discover_runners (canonical implementation with improved error logging); ci/discover_runners becomes a deprecated wrapper re-exporting from molecule All 2393 existing tests pass; new modules at 100% coverage. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
"""Validate Jinja2 expressions in Ansible files by rendering them.
|
|
|
|
Thin wrapper around :mod:`devx.tools.ansible_checks.jinja_expr` for
|
|
backward compatibility. The check logic lives in the subpackage; this
|
|
module preserves the CLI entry point and re-exports the internal
|
|
helpers so existing tests and imports continue to work.
|
|
|
|
Usage::
|
|
|
|
python -m devx.tools.check_jinja_expr
|
|
python -m devx.tools.check_jinja_expr --path ansible/playbooks/deploy-observability.yml
|
|
|
|
Exit code 0 if all renderable expressions pass, 1 if any fail.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import click
|
|
|
|
from devx.tools.ansible_checks.jinja_expr import (
|
|
EXPR_PATTERN, # noqa: F401 — re-exported for backward compat
|
|
MOCK_CONTEXT, # noqa: F401
|
|
_check_file, # noqa: F401
|
|
_default_ansible_dirs, # noqa: F401
|
|
_extract_expressions, # noqa: F401
|
|
_find_yaml_files, # noqa: F401
|
|
_render_expression, # noqa: F401
|
|
check_jinja_expr, # noqa: F401
|
|
)
|
|
|
|
|
|
@click.command()
|
|
@click.option(
|
|
"--path",
|
|
type=click.Path(exists=True, path_type=Path),
|
|
help="Check a specific file or directory (default: ansible/playbooks + ansible/roles).",
|
|
)
|
|
@click.option(
|
|
"--ansible-dir",
|
|
"ansible_dirs",
|
|
type=click.Path(exists=True, path_type=Path),
|
|
multiple=True,
|
|
default=None,
|
|
help="Override the default ansible directories (can be repeated). Defaults to ansible/playbooks and ansible/roles.",
|
|
)
|
|
def main(path: Path | None, ansible_dirs: tuple[Path, ...]) -> None:
|
|
"""Validate Jinja2 expressions in Ansible files."""
|
|
dirs = list(ansible_dirs) if ansible_dirs else _default_ansible_dirs()
|
|
all_violations = check_jinja_expr(path) if path else check_jinja_expr(None, dirs)
|
|
|
|
if all_violations:
|
|
click.echo("[check-jinja-expr] FAIL: invalid Jinja expressions found:")
|
|
for v in all_violations:
|
|
click.echo(f" - {v}")
|
|
click.echo("\nFix: test expressions with `ansible localhost -m debug -a 'msg={{ <expr> }}'`")
|
|
sys.exit(1)
|
|
else:
|
|
click.echo("[check-jinja-expr] OK: all Jinja expressions render correctly.")
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main()
|