Files
mroberts 37fc3fb291 Fix audit tool bootstrap and add per-run preflight
audit-code install-tools.sh:
- Buffer the opengrep release JSON before grep -m1; curl died with (23)
  under pipefail when grep quit early.
- Use ${m}: in the PowerShell block; $m: parsed as a scope-qualified var.
- On Arch, skip paru/yay when pacman -Q shows every package installed,
  since --needed still invokes sudo.
- Add --check-only (fast, installs nothing, non-zero naming missing tools)
  and --user-only (no system package managers, no sudo).

log-run.py (both skills): put the skill dir on sys.path so running it as
a script from any cwd no longer raises ModuleNotFoundError.

audit-terraform: move deps from requirements.txt into pyproject
dependency groups and add scripts/install-tools.sh (uv sync --group tools,
then check trivy, tflint, tofu, terragrunt, gh).

Both SKILL.md files gain a 0.5 Preflight step and call scripts through
uv run --project ${SKILL_DIR}. tools_unavailable is now a map of tool to
exact install command; audit-terraform skips trivy when absent and stops
with an install hint instead of crashing when tofu/terragrunt is missing.
2026-09-22 15:21:28 -05:00

59 lines
2.1 KiB
Python

"""Tests for scripts/install-tools.sh --check-only, run against a copy with stubbed binaries."""
from __future__ import annotations
import os
import shutil
import subprocess
from pathlib import Path
_SCRIPT = Path(__file__).resolve().parent.parent / "scripts" / "install-tools.sh"
_NATIVE_TOOLS = ("trivy", "tflint", "tofu", "terragrunt", "gh")
def _skill_copy(tmp_path: Path) -> Path:
skill = tmp_path / "skill"
(skill / "scripts").mkdir(parents=True)
shutil.copy(_SCRIPT, skill / "scripts" / "install-tools.sh")
return skill / "scripts" / "install-tools.sh"
def _stub(bin_dir: Path, name: str, body: str = "") -> None:
bin_dir.mkdir(parents=True, exist_ok=True)
path = bin_dir / name
path.write_text("#!/usr/bin/env bash\n" + body)
path.chmod(0o755)
def _check_only(script: Path, bin_dir: Path) -> subprocess.CompletedProcess:
# Only the commands the script itself needs, so real trivy/tofu on this host can't leak in.
core = bin_dir.parent / "core"
core.mkdir(exist_ok=True)
for tool in ("bash", "dirname"):
(core / tool).symlink_to(shutil.which(tool))
bin_dir.mkdir(exist_ok=True)
return subprocess.run(
["bash", str(script), "--check-only"],
capture_output=True, text=True, timeout=60, check=False,
env={**os.environ, "PATH": f"{bin_dir}:{core}"},
)
def test_check_only_on_empty_venv_fails_and_names_missing(tmp_path: Path) -> None:
script = _skill_copy(tmp_path)
r = _check_only(script, tmp_path / "bin")
assert r.returncode != 0
for name in ("python-hcl2", "trivy", "tflint", "tofu", "terragrunt"):
assert name in r.stdout, r.stdout
assert not (script.parent.parent / ".venv").exists(), "--check-only must not install anything"
def test_check_only_passes_when_everything_present(tmp_path: Path) -> None:
script = _skill_copy(tmp_path)
_stub(script.parent.parent / ".venv" / "bin", "python")
bin_dir = tmp_path / "bin"
for tool in _NATIVE_TOOLS:
_stub(bin_dir, tool)
r = _check_only(script, bin_dir)
assert r.returncode == 0, r.stdout + r.stderr