pre-commit Framework

repository·main·Indexed 42 days ago

https://github.com/pre-commit/pre-commit.com

A framework for managing and maintaining multi-language pre-commit hooks. Features include support for repository-local hooks, language version overrides, file filtering via types and regular expressions, and integration with CI environments and Git 2.54+ hook configuration.

Tokens
12.3K
Snippets
41
Records
62
Agent score
50%

What's inside pre-commit

  1. Configure pre-commit cache location

    main

    By default, pre-commit stores its repository cache in ~/.cache/pre-commit. You can change this location using one of two environment variables:

    1. PRE_COMMIT_HOME: Sets the specific directory for the cache.
    2. XDG_CACHE_HOME: Sets the base cache directory; pre-commit will then use $XDG_CACHE_HOME/pre-commit.
  2. Filter files using `types` and `types_or`

    main

    Instead of error-prone regular expressions, you can use types to filter files based on tags discovered by the identify library (e.g., python, javascript, text, binary, executable).

    • types: An array of tags. All tags in the list must match (AND logic).
    • types_or: An array of tags. Any tag in the list can match (OR logic).
    • types, types_or, and files are evaluated together with AND logic.

    If you need to use a hook on files that don't match its default type, you must override the types setting.

    To see the tags for a specific file, use the identify-cli tool.

    # Match files that are in foo/ AND are either python or text
        files: ^foo/
        types: [file, python]
    
    # Match files in foo/ that are javascript, jsx, ts, OR tsx
        files: ^foo/
        types_or: [javascript, jsx, ts, tsx]
    
    # Overriding default types (e.g., using check-json on non-json files)
        -   id: check-json
            types: [file]  # override `types: [json]`
            files: \.(json|myext)$
  3. Use rust for hook environments

    main

    The hook repository must have a Cargo.toml that produces at least one binary. pre-commit installs it via cargo install --bins into the pre-commit cache. The entry must match the binary name.

    Dependencies:

    • Use {package_name}:{package_version} for library dependencies (used to build the hook).
    • Use cli:{package_name}:{package_version} for CLI dependencies (built separately).
  4. Use docker_image for lightweight docker hooks

    main

    The language: docker_image uses existing Docker images instead of building from a Dockerfile. This is a lightweight alternative and works well with repo: local hooks.

    • If the image has an ENTRYPOINT, no extra configuration is needed.
    • If you need to change the entrypoint or the image lacks one, specify it in the entry field.

    Supported formats for entry:

    1. entry: <image_tag> (uses image entrypoint)
    2. entry: --entrypoint <exe> <image_tag>
    3. entry: <image_tag> <exe>
    -   id: dockerfile-provides-entrypoint
        name: ...
        language: docker_image
        entry: my.registry.example.com/docker-image-1:latest
    -   id: dockerfile-no-entrypoint-1
        name: ...
        language: docker_image
        entry: --entrypoint my-exe my.registry.example.com/docker-image-2:latest
    -   id: dockerfile-no-entrypoint-2
        name: ...
        language: docker_image
        entry: my.registry.example.com/docker-image-3:latest my-exe
  5. Find existing hooks using Sourcegraph or GitHub

    main

    To find hooks compatible with your specific language or project type, you can use advanced search queries on Sourcegraph or GitHub. This is the recommended way to discover hooks that are already being used in successful projects.

    Using Sourcegraph

    Use these queries to find hooks targeting specific file types:

    • Python hooks: file:^\.pre-commit-hooks\.yaml$ "types: [python]"
    • Shell hooks: file:^\.pre-commit-hooks\.yaml$ "types: [shell]"
    • Popular configurations: file:^\.pre-commit-config\.yaml$

    Using GitHub

    Search for repositories that define hooks using the following query:

    • path:.pre-commit-hooks.yaml language:YAML
    Sourcegraph Python search:
    file:^\.pre-commit-hooks\.yaml$ "types: [python]"
    
    GitHub search:
    path:.pre-commit-hooks.yaml language:YAML
  6. Use pygrep for regex-based file matching

    main

    language: pygrep is a cross-platform Python implementation of grep. It is used to prevent commits by matching files against a regular expression.

    • Entry: The regex pattern.
    • Case Insensitivity: Start the entry with (?i) or use args: [-i].
    • Multiline: Use args: [--multiline].
    • Negation: Use args: [--negate] to require all files to match.
  7. Use r for hook environments

    main

    The hook repository must have a renv.lock file. pre-commit restores the environment using renv::restore().

    • Entry: The entry should be Rscript -e {expression} or Rscript path/relative/to/hook/root.
    • Isolation: The R Startup process is skipped (emulating --vanilla).
    • Dependencies: additional_dependencies are passed to pkg> add using Pkg REPL mode syntax.
    - id: foo-without-args
      name: ...
      language: julia
      entry: bin/foo.jl
    - id: bar-with-args
      name: ...
      language: julia
      entry: bin/bar.jl --arg1 --arg2
    - id: baz-with-extra-deps
      name: ...
      language: julia
      entry: bin/baz.jl
      additional_dependencies:
       - 'ExtraDepA@1'
       - 'ExtraDepB@2.4'
  8. Configure CI caching for pre-commit

    main

    Because pre-commit downloads and builds environments, using CI caching is highly recommended to speed up builds. Note that for immutable caches (like Azure Pipelines, CircleCI, or GitHub Actions), you should include the Python version and the .pre-commit-config.yaml hash in your cache key to ensure cache invalidation when configurations change.

    GitHub Actions Example:

        - name: set PY
          run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
        - uses: actions/cache@v3
          with:
            path: ~/.cache/pre-commit
            key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}

    GitLab CI Example:

    my_job:
      variables:
        PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
      cache:
        paths:
          - ${PRE_COMMIT_HOME}
  9. Use coursier for JVM-based hooks

    main
    The language: coursier requires a .pre-commit-channel folder in the hook repository containing coursier application descriptors. The entry must match an executable installed from that folder. This language supports repo: local and additional_dependencies (as of version 3.0.0).
  10. Use golang for hook environments

    main

    The hook repository must contain Go source code. pre-commit installs it via go install ./... into an isolated GOPATH. The entry must match an executable in the GOPATH/bin directory.

    Features:

    • Supports additional_dependencies (passed to go install).
    • Supports language_version (as of 3.0.0).
    • pre-commit will bootstrap go if it is not present.