Repository navigation
Allow .pre-commit-hooks.yaml hooks to extend repo: builtin hooks #2504
Description
Summary
Allow .pre-commit-hooks.yaml hooks to extend repo: builtin hooks through a prek-only extends field, for hook authors who publish a repository consumed by end users.
For each extended manifest hook, prek should load the referenced repo: builtin hook as the base implementation, apply the supported hook fields declared in .pre-commit-hooks.yaml, and execute that builtin hook with the resulting configuration.
The referenced hook must be a Rust-native hook available through the Explicit Builtin Repository. The manifest hook can customize its public identity, metadata, filters, arguments, and other supported hook options without requiring a wrapper executable, an external interpreter, or a separate hook environment.
Proposed syntax [.pre-commit-hooks.yaml]
- id: pytest-filename-conventions
name: Enforce pytest filename conventions
description: Ensures files under tests/ follow pytest naming conventions (test_*.py, __init__.py, or conftest.py).
extends:
repo: builtin
id: require-filename-pattern
files: '(^|/)tests/.+\.py$'
args:
- '^test_.*\.py$'
- '^__init__\.py$'
- '^conftest\.py$'
- id: text-unicode-replacement-char
name: No Unicode replacement characters
description: Forbids text files containing the Unicode replacement character U+FFFD.
extends:
repo: builtin
id: deny-pattern
args:
- "\uFFFD"
types: [text]For pytest-filename-conventions, prek should execute the builtin require-filename-pattern implementation while applying the manifest hook's name, description, files, and args.
For text-unicode-replacement-char, prek should execute the builtin deny-pattern implementation while applying the manifest hook's name, description, args, and types.
Consumers could then use the published hooks as normal remote hooks:
.pre-commit-config.yaml
repos:
- repo: https://github.com/example/prek-hooks
rev: v1.0.0
hooks:
- id: pytest-filename-conventions
- id: text-unicode-replacement-charEquivalent builtin configuration[.pre-commit-config.yaml]
The manifest hooks above should behave exactly like this direct repo: builtin configuration:
repos:
- repo: builtin
hooks:
- id: require-filename-pattern
name: Enforce pytest filename conventions
description: Ensures files under tests/ follow pytest naming conventions (test_*.py, __init__.py, or conftest.py).
files: '(^|/)tests/.+\.py$'
args:
- '^test_.*\.py$'
- '^__init__\.py$'
- '^conftest\.py$'
- id: deny-pattern
name: No Unicode replacement characters
description: Forbids text files containing the Unicode replacement character U+FFFD.
args:
- "\uFFFD"
types: [text]Required behavior
- Allow only
repo: builtinforextends.repo. - Require
extends.idto identify an existing hook available through the Explicit Builtin Repository. - Load the referenced builtin hook as the base implementation.
- Apply the supported hook fields from the
.pre-commit-hooks.yamlhook to that base hook. - Apply normal consumer configuration overrides after the manifest hook fields.
- Execute the referenced builtin Rust implementation using the final effective configuration.
- Use the manifest hook's top-level
idfor selection and output; useextends.idonly to select the builtin implementation. - Require
id,name, andextendsfor an extended manifest hook. - Do not require
entryorlanguage; rejectentry, and allowlanguageonly when set tosystem. - Execute the bundled Rust implementation without installing dependencies, creating a hook environment, or invoking an external interpreter.
- Apply the same argument support and compatibility checks as the equivalent direct
repo: builtinconfiguration. - Report clear validation errors for unknown builtin hook IDs and incompatible fields.
- Support extended hooks in
prek validate-manifestandprek try-repo. - Keep existing manifest hooks unchanged and document that
extendsis specific toprek.
Activity