# Pre-commit hooks for cachekit # Install: pre-commit install # Run manually: pre-commit run --all-files default_install_hook_types: [pre-commit, commit-msg] # Hooks with no `stages` run at commit and push, never on the commit message. default_stages: [pre-commit, pre-push] repos: # Python formatting and linting with ruff - repo: https://github.com/astral-sh/ruff-pre-commit rev: c60c980e561ed3e73101667fe8365c609d19a438 # v0.15.9 # pragma: allowlist secret hooks: - id: ruff args: [--fix] name: Ruff lint - id: ruff-format name: Ruff format # Rust formatting and linting - repo: local hooks: # Python type checking with basedpyright # Uses venv directly to avoid uv run modifying uv.lock - id: basedpyright name: basedpyright entry: .venv/bin/basedpyright src/ --level error language: system types: [python] pass_filenames: false - id: cargo-fmt name: Cargo format entry: bash -c 'cd rust && cargo fmt --check' language: system files: \.rs$ pass_filenames: false - id: cargo-clippy name: Cargo clippy entry: bash -c 'cd rust && cargo clippy -- -D warnings' language: system files: \.rs$ pass_filenames: false # Makefile linting with checkmake (config in checkmake.ini) # Requires: go install github.com/checkmake/checkmake/cmd/checkmake@latest - id: checkmake name: checkmake (Makefile lint) entry: checkmake --config checkmake.ini Makefile language: system files: ^Makefile$ pass_filenames: false # Block internal development artifacts from public repo - repo: local hooks: - id: check-no-internal-docs name: Block internal docs from public repo entry: .hooks/check-no-internal-docs.sh language: script files: | (?x)^( docs/superpowers/| \.spec-workflow/specs/| strategy/| tooling/sessions/| sessions/tasks/| CALIBER_LEARNINGS\.md$| \.caliber/ ) pass_filenames: true # GitHub Actions workflow linting - repo: https://github.com/rhysd/actionlint rev: fd33e9f582a01a02885c93ae3775e1190cf63653 # v1.7.12 + fix for rhysd/actionlint#650; move to the next release tag # pragma: allowlist secret hooks: - id: actionlint # General file checks - repo: https://github.com/pre-commit/pre-commit-hooks rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0 # pragma: allowlist secret hooks: # Fuzz corpus seeds are opaque byte strings, not text — "fixing" their # whitespace or final newline silently changes the seed (and breaks # byte-exact StorageEnvelope seeds whose checksum must verify). - id: trailing-whitespace exclude: ^rust/fuzz/corpus/ - id: end-of-file-fixer exclude: ^rust/fuzz/corpus/ - id: check-yaml - id: check-added-large-files args: [--maxkb=1000] - id: check-merge-conflict # Secret scanning - prevent credential leaks # Uses Yelp's detect-secrets with high entropy detection - repo: https://github.com/Yelp/detect-secrets rev: 01886c8a910c64595c47f186ca1ffc0b77fa5458 # v1.5.0 # pragma: allowlist secret hooks: - id: detect-secrets args: - --baseline - .secrets.baseline exclude: | (?x)^( .*\.lock$| .*\.sum$| tests/fixtures/.*| docs/.*\.md$ )$ # Keeps internal references (ticket ids, secret-store paths, internal hosts and process # names) out of user-facing docs and commit messages. The patterns are generic on purpose: # a list of specific internal names would itself disclose them. # Scope rule: https://docs.cachekit.io/contributing/#what-belongs-in-these-docs - repo: local hooks: - id: no-internal-references name: No internal references in docs language: pygrep entry: '\b(?i:LAB)-[0-9]+|op://|\.ts\.net|(?i:\bk3s[\s_-]+(?:cluster|node|host)s?\b)|dev\.cachekit\.io|\bStage [0-9]|\bAC-[0-9]|github\.com/cachekit(?![\w-])' files: ^((packages|crates)/[^/]+/)?README[^/]*$|^docs/ types: [text] stages: [pre-commit] - id: no-retired-names name: No retired product names or wrong package names in docs # The hosted service is "CacheKit Cloud" in prose; `CachekitIO` is only a code identifier. # Naming rules: https://docs.cachekit.io/contributing/#names language: pygrep entry: '(?i:\bCachekitIO[ -](?:Cloud|SaaS|backend|service|server|API)s?\b)|\bSaaS\b|(?i:(?8 ------------------------")[0] lines = [line for line in text.splitlines() if line.strip() and not re.match(r"#(?:[ \t]|$)", line)] if lines and GIT_SUBJECT.fullmatch(lines[0]): lines = lines[1:] bad = [line for line in lines if P.search(line)] for line in bad: print(f"{sys.argv[1]}: {line}") sys.exit(1 if bad else 0) stages: [commit-msg]