GRM-51: refactor: convert shell scripts and inline workflow scripts to Python

This commit is contained in:
2026-06-22 05:53:31 +00:00
parent bec7b59671
commit b6e87a519b
28 changed files with 1582 additions and 219 deletions
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""Project setup: install Python deps, Ansible collections, and pre-commit hooks.
Replaces the previous ``scripts/setup.sh`` with a tested Python equivalent.
Usage::
python3 scripts/setup.py --bin .venv/bin
"""
from __future__ import annotations
import subprocess # nosec B404
from pathlib import Path
import click
def _run(cmd: list[str], bin_dir: str) -> None:
"""Run a command, streaming output to stdout/stderr."""
click.echo(f" $ {' '.join(cmd)}")
subprocess.run(cmd, check=True) # nosec B603
def _install_python_deps(bin_dir: str) -> None:
"""Install the project with dev extras in editable mode."""
pip = str(Path(bin_dir) / "pip")
_run([pip, "install", "-e", ".[dev]"], bin_dir)
def _install_ansible_collections(bin_dir: str) -> None:
"""Install required Ansible Galaxy collections."""
galaxy = str(Path(bin_dir) / "ansible-galaxy")
requirements = Path("ansible/requirements.yml")
if not requirements.exists():
click.echo(" ansible/requirements.yml not found — skipping collections.")
return
_run([galaxy, "collection", "install", "-r", str(requirements)], bin_dir)
def _install_pre_commit_hooks(bin_dir: str) -> None:
"""Install pre-commit hooks for commit-msg, pre-commit, and pre-push."""
pre_commit = str(Path(bin_dir) / "pre-commit")
for hook_type in ["pre-commit", "commit-msg", "pre-push"]:
_run([pre_commit, "install", "--hook-type", hook_type], bin_dir)
def _verify(bin_dir: str) -> None:
"""Print versions of installed tools for verification."""
grm = str(Path(bin_dir) / "grm")
pre_commit = str(Path(bin_dir) / "pre-commit")
for tool in [grm, pre_commit]:
try:
result = subprocess.run([tool, "--version"], capture_output=True, text=True, timeout=10) # nosec B603
if result.returncode == 0:
click.echo(f" {result.stdout.strip()}")
except (FileNotFoundError, subprocess.TimeoutExpired):
pass
@click.command()
@click.option("--bin", "bin_dir", default=".venv/bin", help="Path to the virtualenv bin directory.")
def main(bin_dir: str) -> None:
"""Install Python deps, Ansible collections, and pre-commit hooks."""
if not Path(bin_dir).exists():
raise click.ClickException(f"Bin directory not found: {bin_dir}. Run 'python3 -m venv .venv' first.")
click.echo("Installing Python dependencies...")
_install_python_deps(bin_dir)
click.echo("Installing Ansible collections...")
_install_ansible_collections(bin_dir)
click.echo("Installing pre-commit hooks...")
_install_pre_commit_hooks(bin_dir)
click.echo("")
click.echo("Setup complete.")
click.echo("Activate the virtual environment with one of:")
click.echo(" source .venv/bin/activate (generic)")
click.echo(" source activate.sh (bash)")
click.echo(" source activate.fish (fish)")
click.echo(" source activate.zsh (zsh)")
click.echo("")
_verify(bin_dir)
if __name__ == "__main__": # pragma: no cover
main() # pragma: no cover