[One Package Per Day] Pre-Commit
By khoanc, at: Aug. 12, 2024, 3:28 p.m.
[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:
-
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 sysdef 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 0if __name__ == '__main__':
sys.exit(main()) -
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$ -
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:
-
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.
- Error Message:
-
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.
- Error Message:
-
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 theadditional_dependencies
key.
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
hooks:
- id: flake8
additional_dependencies: [flake8==3.9.0] - Error Message:
-
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.
- Error Message:
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.
- 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.
-
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.
- Pre-commit: Uses a
-
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.
- Pre-commit: Offers a wide range of built-in hooks for various tasks such as linting, formatting, and security checks.
-
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: Has a large community and supports many community-maintained hooks, making it suitable for various projects.
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.
- Pre-commit: General-purpose tool that can enforce various code quality standards and checks.
-
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.
- Pre-commit: Easily integrates with multiple languages and supports custom hooks for different tasks.
-
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.
- Pre-commit: Ideal for teams looking to automate code quality checks and enforce coding standards.
Useful Related Packages
-
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
-
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
-
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
-
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"]
-
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.