[One Package Per Day] Pre-Commit

By khoanc, at: Aug. 12, 2024, 3:28 p.m.

Estimated Reading Time: 13 min read

[One Package Per Day] Pre-Commit
[One Package Per Day] Pre-Commit

[One Package Per Day] Pre-Commit


Pre-commit hooks are an essential tool for maintaining code quality and preventing issues before they enter a codebase. The "Pre-commit" package automates the execution of these hooks, ensuring that code standards are met every time a developer commits changes to a repository.

With "Pre-commit," you can set up a series of checks that run automatically, catching potential errors and enforcing consistent coding practices. This package simplifies the process by providing a wide variety of built-in hooks and support for creating custom ones, allowing you to tailor it to your project's specific needs.

In this post, we'll explore how to get started with "Pre-commit," its key features, and how it can enhance your development workflow by automating code quality checks.

 

Installation

Provide a step-by-step guide on how to install the "Pre-commit" package. Include commands for installing it via pip and any prerequisites needed for setting it up.

pip install pre-commit

 

Getting Started

Explain how to initialize and configure "Pre-commit" in a project. Discuss how to set up a .pre-commit-config.yaml file with example configurations.

# .pre-commit-config.yaml

repos:
  - repo: https://github.com/psf/black
    rev: 23.7.0 # Use the latest stable version
    hooks:
      - id: black
        args: [--line-length=88] # Adjust line length to your preference

  - repo: https://github.com/pycqa/flake8
    rev: 6.1.0 # Use the latest stable version
    hooks:
      - id: flake8
        args: [--max-line-length=88] # Adjust line length to match Black

  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.5 # Use the latest stable version
    hooks:
      - id: bandit
        args: ["--skip=B101"] # Skip the B101 test for assert statements

  - repo: https://github.com/PyCQA/isort
    rev: 5.12.0 # Use the latest stable version
    hooks:
      - id: isort
        args: ["--profile=black"] # Use Black profile for compatibility

 

 

Key Features

Highlight some key features of the "Pre-commit" package:

  • Extensibility: Ability to add custom hooks.
     
  • Wide range of built-in hooks: Include linting, code formatting, and more.
     
  • Cross-language support: Works with Python, JavaScript, and other languages.
     

Use Cases

Discuss practical use cases where "Pre-commit" adds value to a development workflow:

  • Enforcing coding standards.
     
  • Automatically fixing formatting issues.
     
  • Running security checks before code commits.
     

Best Practices

Offer tips on how to make the most out of "Pre-commit":

  • Regularly update hook versions.
     
  • Use the --all-files flag to run hooks across the entire codebase.
     
  • Combine with CI/CD pipelines for consistent quality checks.
     

Customization

The "Pre-commit" package offers great flexibility, allowing developers to create custom hooks that cater to specific project requirements. Custom hooks can be written in any language and are easily integrated into the pre-commit framework.


Creating a Custom Hook

To create a custom hook, follow these steps:

  1. Write the Hook Script: Create a script that performs the desired checks or actions. For example, a Python script to check for TODO comments might look like this:

    #!/usr/bin/env python
    import sys

    def main():
        for filename in sys.argv[1:]:
            with open(filename) as f:
                for i, line in enumerate(f, 1):
                    if 'TODO' in line:
                        print(f"TODO found in {filename}:{i}")
                        return 1
        return 0

    if __name__ == '__main__':
        sys.exit(main())

  2. Add the Hook to .pre-commit-config.yaml: Define your custom hook in the configuration file, specifying the path to your script.

    repos:
      - repo: local
        hooks:
          - id: check-todo
            name: Check for TODO comments
            entry: path/to/check_todo.py
            language: python
            files: \.py$
  3. Install and Run: Install the pre-commit hooks and run them to test your custom script.

    pre-commit install
    pre-commit run --all-files


This flexibility allows you to automate checks that are unique to your project, ensuring that all developers adhere to the same standards.

 

Integration

"Pre-commit" seamlessly integrates with version control systems like Git, making it easy to include in your existing workflows. Here are some integration tips:


Git Integration

  • Automatic Hook Installation: By running pre-commit install, the necessary hooks are added to your local Git configuration. This ensures that the hooks run automatically with each commit.
     

  • CI/CD Integration: Integrate "Pre-commit" into your CI/CD pipelines to enforce checks on every commit and pull request. This ensures that code quality is maintained across all branches and contributors.

    For example, in a GitHub Actions workflow, you can add a step to run pre-commit hooks:

    jobs:
      lint:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - name: Set up Python
            uses: actions/setup-python@v2
            with:
              python-version: 3.x
          - name: Install dependencies
            run: |
              python -m pip install --upgrade pip
              pip install pre-commit
          - name: Run Pre-commit
            run: pre-commit run --all-file

 

Common Errors

While using "Pre-commit," you may encounter some common errors. Here are solutions and troubleshooting tips for them:

  1. Hook Not Installed:

    • Error Message: The pre-commit hook is not installed. Run 'pre-commit install'.
       
    • Solution: Run pre-commit install in your repository to ensure the hooks are installed.
       
  2. Hook Failures:

    • Error Message: Hook failed with exit code 1.
       
    • Solution: Check the output for specific errors. It usually indicates that a file does not meet the required standards. Fix the issues and commit again.
       
  3. Missing Dependencies:

    • Error Message: Command '...' not found.
       
    • Solution: Ensure all dependencies required by the hooks are installed. You can specify additional dependencies in your .pre-commit-config.yaml file using the additional_dependencies key.
    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: v3.3.0
      hooks:
        - id: flake8
          additional_dependencies: [flake8==3.9.0]
  4. Invalid Configuration:

    • Error Message: Invalid .pre-commit-config.yaml
       
    • Solution: Check the syntax and structure of your .pre-commit-config.yaml file. Use online YAML validators to ensure the configuration is valid.
       

By addressing these common issues, you can ensure a smoother experience while using the "Pre-commit" package.

 

Pros and Cons

Provide a balanced view of the "Pre-commit" package:

Pros

  • Enhances code quality.
     
  • Reduces manual code review efforts.
     
  • Supports a wide range of hooks.
     

Cons

  • Initial setup time.
     
  • Potential slowdowns with many hooks.

 

Comparison with Other Packages

When it comes to maintaining code quality and enforcing standards in a project, several tools are available. Let's compare "Pre-commit" with other popular tools like Husky and Talisman, highlighting their features, use cases, and how they differ.


Pre-commit vs. Husky

Husky is a popular tool primarily used in JavaScript projects to manage Git hooks. Here's how it compares to "Pre-commit":

  • Language Support:

    • Pre-commit: Supports multiple programming languages, including Python, JavaScript, Ruby, and more. It's versatile and can be used in projects with diverse tech stacks.
       
    • Husky: Primarily designed for JavaScript/Node.js projects, offering deep integration with npm/yarn scripts.
       
  • Configuration:

    • Pre-commit: Uses a .pre-commit-config.yaml file for configuration, which is language-agnostic and easily understandable.
       
    • Husky: Configuration is often done in package.json or via a separate configuration file (.huskyrc), which is more familiar to Node.js developers.
       
  • Built-in Hooks:

    • Pre-commit: Offers a wide range of built-in hooks for various tasks such as linting, formatting, and security checks.
       
    • Husky: Does not provide built-in hooks but allows execution of custom scripts, making it highly flexible for JavaScript projects.
       
  • Community and Ecosystem:

    • Pre-commit: Has a large community and supports many community-maintained hooks, making it suitable for various projects.
       
    • Husky: Well-adopted in the JavaScript ecosystem, with strong community support and frequent updates.

 

Pre-commit vs. Talisman

Talisman is a tool focused on preventing sensitive information from being committed to a repository. Here's how it stacks up against "Pre-commit":

  • Purpose:

    • Pre-commit: General-purpose tool that can enforce various code quality standards and checks.
       
    • Talisman: Specializes in scanning for secrets and sensitive data, like API keys and credentials, in code before commits.
       
  • Integration:

    • Pre-commit: Easily integrates with multiple languages and supports custom hooks for different tasks.
       
    • Talisman: Primarily a security tool that focuses on identifying potentially harmful data, making it a complementary tool rather than a direct competitor.
       
  • Use Cases:

    • Pre-commit: Ideal for teams looking to automate code quality checks and enforce coding standards.
       
    • Talisman: Best for teams prioritizing security and data protection, preventing leaks of sensitive information.

 

Useful Related Packages

Black

  • Description: Black is an opinionated code formatter for Python that ensures your code follows consistent style guidelines.

  • Use with Pre-commit: Automatically format Python files before committing, ensuring a consistent code style.

  • Pre-commit Configuration:

    - repo: https://github.com/psf/black
      rev: 23.7.0
      hooks:
        - id: black

 

Flake8

  • Description: Flake8 is a comprehensive tool for checking the style and quality of Python code, combining PEP 8 style guide enforcement with additional linting capabilities.

  • Use with Pre-commit: Identify and fix style violations, unused variables, and potential errors before committing.

  • Pre-commit Configuration:

    - repo: https://github.com/pycqa/flake8
      rev: 6.1.0
      hooks:
        - id: flake8

 

isort

  • Description: isort automatically sorts and formats import statements in Python files according to a specified order and style.

  • Use with Pre-commit: Maintain a consistent order of imports across your codebase.

  • Pre-commit Configuration:

    - repo: https://github.com/PyCQA/isort
      rev: 5.12.0
      hooks:
        - id: isort

 

bandit

  • Description: Bandit is a security linter for Python code, designed to find common security issues in Python applications.

  • Use with Pre-commit: Automatically scan code for potential security vulnerabilities before committing.

  • Pre-commit Configuration:

    - repo: https://github.com/PyCQA/bandit
      rev: 1.7.5
      hooks:
        - id: bandit
          args: ["--skip=B101"]

 

pytest

  • Description: Pytest is a popular testing framework for Python, known for its ease of use and powerful features.

  • Use with Pre-commit: Run tests automatically before committing to ensure code correctness.

  • Pre-commit Configuration:

    - repo: https://github.com/pre-commit/mirrors-pytest
      rev: v7.4.1
      hooks:
        - id: pytest

 

Conclusion

While "Pre-commit" offers a broad range of functionality that can be tailored to any project's needs, tools like Husky and Talisman are more specialized, catering to specific use cases or ecosystems. Choosing the right tool depends on the project's requirements, language, and focus areas. In many cases, using "Pre-commit" in combination with specialized tools like Talisman can provide comprehensive coverage for code quality and security.


Related

Django rest framework Django

[One Package Per Day] - Django Filter

Read more
Subscribe

Subscribe to our newsletter and never miss out lastest news.