conventional-pre-commit

repository·main·Indexed 19 days ago

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

A tool and git pre-commit hook used to enforce the Conventional Commits specification on commit messages. It provides a CLI for validating commit message files, a Python API via the is_conventional function and ConventionalCommit class for programmatic validation, and configurable options for allowed types, scopes, and strictness levels.

Tokens
3.2K
Snippets
13
Records
14
Agent score
69%

What's inside conventional-pre-commit

  1. Set up conventional-pre-commit as a pre-commit hook

    main

    To use conventional-pre-commit to automatically validate your commit messages during the git commit process, follow these steps:

    1. Ensure pre-commit is installed on your system.
    2. Create a .pre-commit-config.yaml file at your repository root if it doesn't exist.
    3. Configure the default_install_hook_types to include commit-msg.
    4. Add the conventional-pre-commit repository to your repos list.
    5. Install the hooks using pre-commit install --install-hooks.

    Note: When used as a hook, the input file argument is automatically supplied by pre-commit using the current commit's message file.

    default_install_hook_types:
      - pre-commit
      - commit-msg
    
    repos:
      - repo: https://github.com/compilerla/conventional-pre-commit
        rev: <git sha or tag>
        hooks:
          - id: conventional-pre-commit
            stages: [commit-msg]
            args: []
  2. Configure conventional-pre-commit arguments

    main

    You can customize the behavior of conventional-pre-commit by passing arguments via the command line or through the args property in your .pre-commit-config.yaml file.

    Available Arguments:

    • --no-color: Disable color in output.
    • --force-scope: Force the commit to have a scope defined.
    • --scopes SCOPES: List of allowed scopes, separated by commas (e.g., api,client).
    • --strict: Force strict adherence to Conventional Commits. Disallows fixup! and merge commits.
    • --verbose: Print more detailed error output.
    • [types ...]: An optional list of types to support.

    Example configuration in .pre-commit-config.yaml:

    repos:
      - repo: https://github.com/compilerla/conventional-pre-commit
        rev: <git sha or tag>
        hooks:
          - id: conventional-pre-commit
            stages: [commit-msg]
            args: [--strict, --force-scope, feat, fix, chore, test, custom]
  3. Use is_conventional in Python code

    main

    You can import is_conventional from conventional_pre_commit.format to programmatically validate if a string follows the Conventional Commits format. You can optionally pass a list of allowed types.

    from conventional_pre_commit.format import is_conventional
    
    # Basic validation
    is_conventional("feat: this is a conventional commit") # Returns True
    is_conventional("nope: this is not a conventional commit") # Returns False
    
    # Validation with custom allowed types
    is_conventional("custom: this is a conventional commit", types=["custom"]) # Returns True
    from conventional_pre_commit.format import is_conventional
    
    # prints True
    print(is_conventional("feat: this is a conventional commit"))
    
    # prints False
    print(is_conventional("nope: this is not a conventional commit"))
    
    # prints True
    print(is_conventional("custom: this is a conventional commit", types=["custom"]))
  4. Configure ConventionalCommit types and scopes

    main

    You can customize the validation rules for ConventionalCommit by providing specific types and scopes during initialization.

    • Types: If you provide a list of types, they will be used for validation. Note that feat and fix are automatically included if they are present in the provided list or if the list is empty (using DEFAULT_TYPES).
    • Scopes: If scopes are provided, the regex will strictly match only those scopes. If scopes is empty, it allows any word character or specific delimiters within the parentheses.
    from conventional_pre_commit.format import ConventionalCommit
    
    # Only allow 'docs' type and 'api' scope
    cc = ConventionalCommit(
        commit_msg="docs(api): update readme",
        types=["docs"],
        scope_optional=False,
        scopes=["api"]
    )
    print(cc.is_valid())  # True
  5. Reference: conventional-pre-commit CLI options

    main

    The following options are available for the conventional-pre-commit command line interface:

    usage: conventional-pre-commit [-h] [--no-color] [--force-scope] [--scopes SCOPES] [--strict] [--verbose] [types ...] input
    
    Check a git commit message for Conventional Commits formatting.
    
    positional arguments:
      types            Optional list of types to support
      input            A file containing a git commit message
    
    options:
      -h, --help       show this help message and exit
      --no-color       Disable color in output.
      --force-scope    Force commit to have scope defined.
      --scopes SCOPES  List of scopes to support. Scopes should be separated by commas with no spaces (e.g. api,client).
      --strict         Force commit to strictly follow Conventional Commits formatting. Disallows fixup! and merge commits.
      --verbose        Print more verbose error output.
  6. Use conventional-pre-commit via CLI

    main

    You can install conventional-pre-commit via pip and run it directly from the command line to check a specific commit message file.

    Installation:

    pip install conventional-pre-commit

    Usage:

    conventional-pre-commit [types] input
    • [types]: An optional list of allowed Conventional Commit types (e.g., feat fix chore).
    • input: The path to the file containing the commit message to check.

    Example:

    conventional-pre-commit feat fix chore ci test .git/COMMIT_MSG
    pip install conventional-pre-commit
    conventional-pre-commit feat fix chore ci test .git/COMMIT_MSG
  7. Validate Conventional Commits with is_conventional()

    main

    For a quick boolean check without instantiating a class, use the is_conventional convenience function.

    is_conventional(input, types=None, optional_scope=True, scopes=[]) -> bool

    from conventional_pre_commit.format import is_conventional
    
    # Simple check
    valid = is_conventional("feat: something")
    
    # Custom types and required scope
    valid_custom = is_conventional(
        "custom: something", 
        types=["custom"], 
        optional_scope=False
    )
  8. Use the Commit class to inspect commit messages

    main

    The Commit class provides base functionality for inspecting and cleaning git commit messages. It can identify autosquash prefixes (like fixup! or squash!) and detect if a commit is a merge commit.

    Key methods:

    • clean(commit_msg): Removes comments (lines starting with #) and ignored verbose commit segments from the message.
    • has_autosquash_prefix(commit_msg): Returns True if the cleaned message starts with a git autosquash prefix (e.g., fixup! ).
    • is_merge(commit_msg): Returns True if the message indicates a merge (e.g., starts with Merge ).
    from conventional_pre_commit.format import Commit
    
    commit = Commit("fixup! feat: new feature")
    print(commit.has_autosquash_prefix())  # True
    
    merge_commit = Commit("Merge branch 'main'")
    print(merge_commit.is_merge())  # True
  9. Validate Conventional Commits with ConventionalCommit

    main

    The ConventionalCommit class (inheriting from Commit) implements checks for the Conventional Commits specification. It allows you to validate if a commit message follows the type(scope)!: subject format.

    Initialization

    ConventionalCommit(commit_msg, types, scope_optional, scopes)

    • commit_msg: The string to validate.
    • types: A list of allowed types. If feat or fix are provided, they are always included. If empty, it defaults to DEFAULT_TYPES.
    • scope_optional: Boolean indicating if the (scope) part is required.
    • scopes: A list of allowed specific scopes.

    Validation Methods

    • is_valid(commit_msg): Returns True if the message matches the required structure.
    • errors(commit_msg): Returns a list of strings identifying which components (type, scope, delim, subject, body) are missing from the message.
    • match(commit_msg): Returns the re.Match object if the message matches the regex pattern.
    from conventional_pre_commit.format import ConventionalCommit
    
    # Basic validation
    cc = ConventionalCommit("feat(ui): add button")
    print(cc.is_valid())  # True
    
    # Checking for errors
    bad_cc = ConventionalCommit("invalid: message")
    print(cc.errors())  # ['type', 'scope', 'delim', 'subject', 'body'] (depending on config)
  10. Format error messages with fail()

    main

    The fail function generates a formatted error string when a commit message does not adhere to the Conventional Commits specification. It includes the offending message, a warning, and a link to the specification. You can control whether ANSI color codes are included using the use_color parameter.

    from conventional_pre_commit.output import fail
    # Assuming a ConventionalCommit object 'commit' exists
    error_message = fail(commit, use_color=True)