The pre-commit framework is an awesome utility to enforce coding standards and run sanity checks, such as preventing large files from being committed.
It's not just convenient to run locally on the developers' machines. By using pre-commit to run checks, linters, and formatters in our CI/CD workflows, it's straightfoward to ensure consistency, with our .pre-commit-config.yaml
becoming the single source of truth.
The official GitHub action for pre-commit is no longer actively maintained, and I often find that it is not versatile enough. Particularly in a repository that contains several components, each covered by a dedicated workflow, I'd like to
define the pre-commit setup and configuration in a single place,
cache dependencies and environments to the maximum degree possible,
and flexibly determine which files are processed by a given workflow run.
Here's a GitHub Actions workflow that meets these three requirements:
name: Lint
on:
push:
# exclude files covered by dedicated workflows
paths-ignore:
- 'component/**'
workflow_call:
inputs:
working-directory:
type: string
required: false
default: '.'
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
- uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: >
${{ format('pre-commit-{0}-{1}',
steps.setup-python.outputs.python-version,
hashFiles('.pre-commit-config.yaml')
) }}
- name: Install pre-commit
run: |
pip install --upgrade pip
pip install pre-commit
pre-commit install
- name: Run pre-commit hooks
working-directory: ${{ inputs.working-directory }}
run: |
git ls-files | xargs pre-commit run \
--show-diff-on-failure \
--color=always \
--files
This runs as a standalone workflow but can also be called by other workflows. If the main pre-commit workflow is stored as .github/workflows/lint.yml
, you can integrate it into other workflows as follows:
name: Component
on:
push:
paths:
- 'component/**'
jobs:
lint:
uses: ./.github/workflows/lint.yml
with:
working-directory: component