Skip to content

Manual Test Runbook — D1: Pre-Commit Quality Gates

Owner: Sagar  |  Time: ~15 min  |  Sandbox: none (purely local)


Prerequisites

  • Local tooling installed:
    • Python 3.10+ with pip
    • terraform >= 1.6
    • tflint >= v0.50
    • trivy >= 0.50
    • git configured to use the repo's hooks (default after clone)
  • pre-commit installed and hooks wired up:

    pip install pre-commit
    pre-commit install --install-hooks
    
  • Working directory: repo root.

  • Clean working tree (git status shows no pending changes).

Steps

Part A — clean baseline (~2 min)

  1. Run the full hook chain (both stages) against the existing tree to confirm the repo is already clean:
pre-commit run --all-files --hook-stage pre-commit
pre-commit run --all-files --hook-stage pre-push
  1. Both invocations must exit 0. If anything fails on a clean tree, fix it before continuing — D1 should not be merged with a failing baseline.

Part B — planted bad commits (~8 min)

Each sub-step plants a different class of violation, attempts a commit, and asserts the right gate fires. Restore the working tree between sub-steps.

  1. Hardcoded secret (gitleaks fast lane):
mkdir -p tests/scratch && cat > tests/scratch/bad_secret.tf <<'EOF'
resource "azurerm_key_vault_secret" "leak" {
  name         = "demo"
  key_vault_id = "/subscriptions/.../vaults/dev"
  value        = "AKIAIOSFODNN7EXAMPLEAAAA"
}
EOF
git add tests/scratch/bad_secret.tf
git commit -m "test: planted secret"

Expected: commit rejected by gitleaks. The error names tests/scratch/bad_secret.tf and the matched rule.

Cleanup: git restore --staged tests/scratch/bad_secret.tf && rm -rf tests/scratch.

  1. Bad Terraform syntax (terraform_validate):
echo 'resource "azurerm_resource_group" "bad" { name = }' > tests/scratch/bad_syntax.tf
git add tests/scratch/bad_syntax.tf
git commit -m "test: planted syntax error"

Expected: commit rejected by terraform_validate (parse error pointing at the missing argument value).

Cleanup: git restore --staged tests/scratch/bad_syntax.tf && rm -rf tests/scratch.

  1. Unformatted Terraform (terraform_fmt):
cat > tests/scratch/bad_fmt.tf <<'EOF'
resource "azurerm_resource_group" "fmt" {
name="ugly"
location="eastus"
}
EOF
git add tests/scratch/bad_fmt.tf
git commit -m "test: planted fmt drift"

Expected: commit rejected by terraform_fmt. Pre-commit auto-rewrites the file in place; re-add + retry commits cleanly.

Cleanup: git restore --staged tests/scratch/bad_fmt.tf && rm -rf tests/scratch.

  1. Non-conventional commit message (conventional-pre-commit):
git commit --allow-empty -m "WIP stuff"

Expected: commit rejected with a list of accepted types (feat, fix, chore, …).

  1. Public-network storage (heavy lane — checkov + tfsec):
mkdir -p tests/scratch && cat > tests/scratch/public_sa.tf <<'EOF'
resource "azurerm_storage_account" "leaky" {
  name                            = "snowopsd1demo"
  resource_group_name             = "rg-demo"
  location                        = "eastus"
  account_tier                    = "Standard"
  account_replication_type        = "LRS"
  allow_nested_items_to_be_public = true
  public_network_access_enabled   = true
  min_tls_version                 = "TLS1_0"
}
EOF
git add tests/scratch/public_sa.tf
git commit -m "test: planted public storage"

Expected: the commit hooks (fast) accept it because checkov + tfsec are wired to pre-push. Simulate the push stage:

pre-commit run --all-files --hook-stage pre-push

Expected: terraform_checkov and/or terraform_tfsec flag the storage account (HIGH severity findings on public access + weak TLS). Exit code is non-zero.

Cleanup: git reset HEAD~1 --soft && git restore --staged tests/scratch/public_sa.tf && rm -rf tests/scratch.

  1. Filesystem-level secret (trivy fs, pre-push stage):
mkdir -p tests/scratch && cat > tests/scratch/aws_key.txt <<'EOF'
AKIAIOSFODNN7EXAMPLEAAAA
wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEYAA
EOF
git add tests/scratch/aws_key.txt
pre-commit run --all-files --hook-stage pre-push

Expected: trivy-fs flags the file. Exit code non-zero.

Cleanup: git restore --staged tests/scratch/aws_key.txt && rm -rf tests/scratch.


Part C — clean commit (smoke) (~2 min)

  1. Restore the tree fully and assert a benign change passes the whole chain:
git checkout -- .
git clean -fd tests/scratch 2>/dev/null || true
echo "" >> docs/README.md
git add docs/README.md
git commit -m "chore: smoke-test D1 gates"

Expected: commit succeeds. pre-commit run --hook-stage pre-push is clean.

  1. Optional final cleanup:

    git reset HEAD~1 --hard
    

Pass criteria

  • pre-commit run --all-files on a clean tree exits 0 (both stages).
  • Each planted violation in Part B is blocked by the expected hook.
  • Conventional-commit hook rejects non-conforming commit messages.
  • Checkov + tfsec fire at the pre-push stage (not at commit-time).
  • Trivy fs flags secret content in the working tree.
  • Clean smoke commit in Part C goes through with zero hook failures.

Teardown

D1 has no cloud side-effects. Only local file cleanup:

rm -rf tests/scratch
git checkout -- .
git clean -fd tests/scratch 2>/dev/null || true

Sign-off

  • Tester: Sagar Chhabra__  |  Date: 26/05/2026  |  Result: PASS
  • Notes: pre-push shows some vulnerabilities on trivy step. It is expected as it's coming in examples and tests/scratch.