From d8b50b8559991551fda4d164e9afa15ef2720556 Mon Sep 17 00:00:00 2001 From: gloskull Date: Fri, 17 Jul 2026 18:44:34 +0100 Subject: [PATCH] Add pre-commit quality hook suite --- .pre-commit-config.yaml | 11 ++++++ docs/PRE_COMMIT_QUALITY.md | 54 ++++++++++++++++++++++++++++ scripts/pre-commit-quality.sh | 68 +++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 .pre-commit-config.yaml create mode 100644 docs/PRE_COMMIT_QUALITY.md create mode 100755 scripts/pre-commit-quality.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4ae6b02 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,11 @@ +# Pre-commit hook suite for local code quality enforcement. +# Install with: pipx install pre-commit && pre-commit install +repos: + - repo: local + hooks: + - id: utility-contracts-quality-suite + name: Utility Contracts quality suite + entry: scripts/pre-commit-quality.sh + language: script + files: "^(contracts/|usage-dashboard/|scripts/pre-commit-quality\.sh|\.pre-commit-config\.yaml)" + pass_filenames: true diff --git a/docs/PRE_COMMIT_QUALITY.md b/docs/PRE_COMMIT_QUALITY.md new file mode 100644 index 0000000..28c803b --- /dev/null +++ b/docs/PRE_COMMIT_QUALITY.md @@ -0,0 +1,54 @@ +# Pre-Commit Quality Suite + +This repository includes a pre-commit hook suite that runs the same quality gates developers are expected to satisfy before opening a pull request. + +## Architecture + +The suite is intentionally local and deterministic: + +1. `.pre-commit-config.yaml` registers a single repository-local hook. +2. `scripts/pre-commit-quality.sh` executes the quality gates from the repository root. +3. The hook receives changed files from pre-commit and runs only the checks relevant to those paths. +4. Rust checks target the `contracts/Cargo.toml` workspace so the hook works even when invoked from another directory. +5. Usage dashboard linting runs only when `usage-dashboard/node_modules` is present, avoiding network installs inside commit hooks. + +## Quality Gates + +For changed Rust workspace files, the hook enforces: + +- `cargo fmt --all -- --check` for canonical Rust formatting. +- `cargo clippy --all-targets --all-features -- -D warnings` for warning-free Rust linting. +- `cargo test --all-features` for workspace tests. + +For changed usage dashboard files, the hook enforces `npm run lint` when dependencies are installed. + +## Installation + +Install pre-commit once, then enable the repository hooks: + +```bash +pipx install pre-commit +pre-commit install +``` + +Developers who already manage Python tools with another package manager can install `pre-commit` through that workflow instead. + +## Manual Execution + +Run the suite without creating a commit: + +```bash +pre-commit run --all-files +``` + +Or run the underlying script directly: + +```bash +scripts/pre-commit-quality.sh --all +``` + +## Operational Notes + +- The hook performs local validation only; production availability, monitoring dashboards, alerting, blue-green deployment, and canary analysis remain CI/CD and operations concerns. +- Security review is supported by making formatting, linting, and test failures visible before code reaches review. +- The hook does not install dependencies or modify source files, keeping commit latency predictable and avoiding hidden network work. diff --git a/scripts/pre-commit-quality.sh b/scripts/pre-commit-quality.sh new file mode 100755 index 0000000..e9a2c67 --- /dev/null +++ b/scripts/pre-commit-quality.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +CONTRACTS_DIR="$ROOT_DIR/contracts" +DASHBOARD_DIR="$ROOT_DIR/usage-dashboard" +RUN_ALL=false +FILES=() + +for arg in "$@"; do + case "$arg" in + --all) RUN_ALL=true ;; + *) FILES+=("$arg") ;; + esac +done + +run_step() { + local label="$1" + shift + + printf '\n🔍 %s\n' "$label" + "$@" +} + +has_changed_file() { + local pattern="$1" + local file + + "$RUN_ALL" && return 0 + for file in "${FILES[@]}"; do + [[ "$file" == $pattern ]] && return 0 + done + return 1 +} + +if [[ ! -d "$CONTRACTS_DIR" ]]; then + echo "❌ contracts workspace not found at $CONTRACTS_DIR" >&2 + exit 1 +fi + +export CARGO_TERM_COLOR="${CARGO_TERM_COLOR:-always}" + +if has_changed_file "contracts/*.rs" || has_changed_file "contracts/*/src/*.rs" || has_changed_file "contracts/*/tests/*.rs" || has_changed_file "contracts/*/Cargo.toml" || has_changed_file "contracts/Cargo.toml"; then + run_step "Rust formatting" \ + cargo fmt --manifest-path "$CONTRACTS_DIR/Cargo.toml" --all -- --check + + run_step "Rust clippy" \ + cargo clippy --manifest-path "$CONTRACTS_DIR/Cargo.toml" --all-targets --all-features -- -D warnings + + run_step "Rust tests" \ + cargo test --manifest-path "$CONTRACTS_DIR/Cargo.toml" --all-features +else + printf '\nℹ️ Skipping Rust checks because this commit does not change Rust workspace files.\n' +fi + +if has_changed_file "usage-dashboard/*.js" || has_changed_file "usage-dashboard/*.jsx" || has_changed_file "usage-dashboard/*.ts" || has_changed_file "usage-dashboard/*.tsx" || has_changed_file "usage-dashboard/package.json"; then + if [[ -d "$DASHBOARD_DIR/node_modules" ]]; then + run_step "Usage dashboard lint" \ + npm --prefix "$DASHBOARD_DIR" run lint + else + printf '\n⚠️ Skipping usage dashboard lint because %s is missing. Run npm install in usage-dashboard to enable it.\n' \ + "$DASHBOARD_DIR/node_modules" + fi +else + printf '\nℹ️ Skipping usage dashboard lint because this commit does not change dashboard files.\n' +fi + +printf '\n✅ Pre-commit quality suite passed.\n'