I’ve been using pre-commit as my tool to set up hooks to run when I commit to
Git. It helps me catch gotchas such as fixing line endings, fixing whitespace,
refusing to commit on linter errors, and so on. Often, I’ve noticed with
working on teams is it’s fairly easy for a new contributor to forget to set up
pre-commit on their development machine. Heck, even I forget to run
pre-commit install
every time I clone a repository.
It makes sense to run pre-commit on every push: pre-commit in CI enforces that everyone is going to follow the the policy specified in your pre-commit configuration. If you don’t run pre-commit in your CI, could code quality suffer?
To make this happen, I’ve published a docker image and documented how to do this in my pre-commit-docker git repository. I will also describe how to use pre-commit-docker in this post.
§Using GitHub Actions
Add the following text to .github/workflowspre-commit.yml
:
name: Run pre-commit
on: push
jobs:
pre-commit:
runs-on: ubuntu-latest
container:
image: registry.gitlab.com/winny/pre-commit-docker:latest
env:
PRE_COMMIT_HOME: .pre-commit-cache
steps:
- uses: actions/checkout@v3
- name: Allow workspace
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Cache .pre-commit-cache
uses: actions/cache@v3
with:
path: |
.pre-commit-cache
key: ${{ runner.os }}-pre-commit-cache-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit
run: pre-commit run -a
Because of how pre-commit operates, removal of $PRE_COMMIT_HOME
causes
pre-commit
to download the hooks and runtimes from the internet. As a
result, I strongly encourage caching this folder. That is what the
actions/cache
action is doing in this example.
§Using GitLab CI
Add the following job to your .gitlab-ci.yml
.
pre-commit:
stage: test
image: registry.gitlab.com/winny/pre-commit-docker:latest
variables:
PRE_COMMIT_HOME: .pre-commit-cache
cache:
- key:
files: [.pre-commit-config.yaml]
paths: [.pre-commit-cache]
script:
- pre-commit run -a
Same story with the pre-commit.cache
key. This enables pre-commit to run
consistently fast for the majority of CI jobs.
§What’s in this docker image?
The docker image used in these pipelines includes pre-commit
. Any image that
includes pre-commit
should suffice. You can pull it via: docker pull registry.gitlab.com/winny/pre-commit-docker
. This will pull the images from
registry.gitlab.com.
You can see the Dockerfile here. It’s a Debian image that includes
pre-commit
. Here’s the gist of it:
FROM debian:bullseye-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends git pre-commit \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
So, pretty simple. One might modify this to include additional dependencies needed by the project’s specific pre-commit runs.
§That’s all
I’ve been using this pre-commit CI job at my job and for personal projects. It’s nice to know all CI jobs got my back here, and there’s one less thing I need to look for when reviewing others’ work.
Keep on, continuous integration.