| 1 | # Local DevSecOps guardrail enforcement (pre-commit / pre-push). |
| 2 | # |
| 3 | # DevSecOps Guardrails epic (jmservera/SquadScope-Coordinator#33), issue #544. |
| 4 | # Mirrors the CI gates so violations are caught before they reach a PR: |
| 5 | # - ruff (lint + format) -> matches the Lint workflow |
| 6 | # - checkov (IaC/Actions) -> matches the Checkov workflow |
| 7 | # - pytest (unit tests) -> matches the CI test job |
| 8 | # - docker build -> verifies a Containerfile/Dockerfile if present |
| 9 | # |
| 10 | # Fast checks (ruff) run on every commit. Slower checks (checkov, pytest, |
| 11 | # docker build) run on push to keep the commit loop quick. |
| 12 | # |
| 13 | # Install (one-time): |
| 14 | # pip install pre-commit |
| 15 | # pre-commit install --hook-type pre-commit --hook-type pre-push |
| 16 | # |
| 17 | # Run on demand: |
| 18 | # pre-commit run --all-files |
| 19 | # |
| 20 | # Tool versions are pinned to match CI (ruff 0.15.7, checkov 3.2.533). When you |
| 21 | # bump a version in CI, bump the matching `rev`/dependency here too. |
| 22 | # |
| 23 | # Emergency bypass (hotfixes only): |
| 24 | # git commit --no-verify |
| 25 | # git push --no-verify |
| 26 | # Bypassing skips LOCAL hooks only — the CI gates still run. Follow up by fixing |
| 27 | # any skipped findings; never weaken a CI gate to land a change. |
| 28 | |
| 29 | default_install_hook_types: [pre-commit, pre-push] |
| 30 | default_stages: [pre-commit] |
| 31 | |
| 32 | repos: |
| 33 | # ── Ruff: Python lint + format (matches CI `ruff check` / `ruff format --check`) |
| 34 | - repo: https://github.com/astral-sh/ruff-pre-commit |
| 35 | rev: v0.15.7 |
| 36 | hooks: |
| 37 | - id: ruff |
| 38 | name: ruff (lint, autofix) |
| 39 | args: [--fix] |
| 40 | - id: ruff-format |
| 41 | name: ruff (format) |
| 42 | |
| 43 | # ── Checkov: IaC / container / GitHub Actions misconfiguration scan (pre-push) |
| 44 | - repo: https://github.com/bridgecrewio/checkov |
| 45 | rev: "3.2.533" |
| 46 | hooks: |
| 47 | - id: checkov |
| 48 | name: checkov (IaC / Actions scan) |
| 49 | stages: [pre-push] |
| 50 | # Trigger on workflow / container changes; the hook always scans the |
| 51 | # whole repo (`checkov -d .`) to mirror CI rather than per-file. |
| 52 | files: ^(\.github/workflows/.*\.ya?ml|.*Dockerfile.*|.*Containerfile.*)$ |
| 53 | pass_filenames: false |
| 54 | args: |
| 55 | - --framework |
| 56 | - github_actions |
| 57 | - dockerfile |
| 58 | - secrets |
| 59 | - --skip-path |
| 60 | - node_modules |
| 61 | - --skip-path |
| 62 | - .venv |
| 63 | - --skip-path |
| 64 | - public |
| 65 | - --skip-path |
| 66 | - resources |
| 67 | - --skip-path |
| 68 | - themes |
| 69 | - --compact |
| 70 | - --quiet |
| 71 | |
| 72 | # ── Local hooks (use repo-installed tooling) |
| 73 | - repo: local |
| 74 | hooks: |
| 75 | # pytest: run the unit suite before pushing (matches the CI test job). |
| 76 | - id: pytest |
| 77 | name: pytest (unit tests) |
| 78 | entry: python3 -m pytest tests/ -q |
| 79 | language: system |
| 80 | stages: [pre-push] |
| 81 | pass_filenames: false |
| 82 | always_run: true |
| 83 | |
| 84 | # docker build: verify a Containerfile/Dockerfile builds, when one exists. |
| 85 | # No-op today (the repo ships no container file); activates automatically |
| 86 | # once a Containerfile/Dockerfile is added. |
| 87 | - id: docker-build |
| 88 | name: docker build (Containerfile, if present) |
| 89 | entry: scripts/hooks/docker_build_check.sh |
| 90 | language: script |
| 91 | stages: [pre-push] |
| 92 | pass_filenames: false |
| 93 | always_run: true |