Skip to content

GitLab CI template for pre-commit

This project implements a GitLab CI/CD template to integrate pre-commit in your pipelines.

Template explained

⚠ this template is not necessarily what you may think it is, please bear with us and read on!

What this template is designed for

A CI job in the build stage that runs the pre-commit framework and:

  • ignores the default .pre-commit-config.yaml file,
  • runs the pre-commit command with a sanitized list of pre-commit checks we think many teams can agree to implement as a sensible baseline.

What this template is not designed for

  • a way to enforce all developper/team pre-commits hooks in CI,
  • a way to implement checks that would've better been implemented through dedicated to-be-continuous templates.

How it is designed

The job follows adaptive pipeline workflow rules that balances speed vs. quality:

  • manually triggered and allowed to fail in non-MR feature branch pipelines,
  • triggered but don't fail the pipeline in Draft MR pipelines,
  • triggered and fails the pipeline in Ready MR and eternal branches pipelines.

Unless a specific .pre-commit-ci.yaml file is present in the repository, the template uses its own predefined following configuration:

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: check-merge-conflict
      - id: check-executables-have-shebangs
      - id: check-shebang-scripts-are-executable
      - id: destroyed-symlinks
      - id: end-of-file-fixer
      - id: fix-byte-order-marker
      - id: mixed-line-ending
      - id: trailing-whitespace

ℹ as stated above, this template will ignore the default .pre-commit-config.yaml configuration file, and will only take into account the custom .pre-commit-ci.yaml instead. This is done on purpose as we believe the pre-commit configuration in the developers environment will/should be different than the one run in CI/CD.

Building your own pre-commit image

Building a pre-configured image is a must for pipeline speed, reproducibility and supply-chain security.

To build a preconfigured image, use the following guidelines:

  • use the smallest base image possible
  • embed all required pre-commit hooks (reminder: use only basic checks)

See the sample Dockerfile in the sample folder.

Usage

This template can be used both as a CI/CD component or using the legacy include:project syntax.

Use as a CI/CD component

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the component
  - component: $CI_SERVER_FQDN/to-be-continuous/pre-commit/gitlab-ci-pre-commit@1.1.1
    # 2: set/override component inputs
    inputs:
      # ⚠ this is only an example
      build-args: "build --with-my-args"

Use as a CI/CD template (legacy)

Add the following to your .gitlab-ci.yml:

include:
  # 1: include the template
  - project: 'to-be-continuous/pre-commit'
    ref: '1.1.1'
    file: '/templates/gitlab-ci-pre-commit.yml'

variables:
  # 2: set/override template variables
  # ⚠ this is only an example
  PRE_COMMIT_SKIP: "check-byte-order-marker,no-commit-to-branch"
  PRE_COMMIT_ARGS: "-v --show-diff-on-failure"

Global configuration

The pre-commit template uses some global configuration used throughout all jobs.

Input / Variable Description Default value
pre-commit-image / PRE_COMMIT_IMAGE The Docker image used to run pre-commit registry.hub.docker.com/library/python:3-alpine

Jobs

pre-commit job

This job performs perfom pre-commit hooks check

It uses the following variable:

Input / Variable Description Default value
pre-commit-disabled / PRE_COMMIT_DISABLED Disable pre-commit run false
pre-commit-skip / PRE_COMMIT_SKIP pre-commit SKIP environment variable (see https://pre-commit.com/#temporarily-disabling-hooks) no-commit-to-branch
pre-commit-args / PRE_COMMIT_ARGS Additionnal arguments for the pre-commit run command ``
pre-commit-file / PRE_COMMIT_FILE pre-commit config file to use for the pre-commit run command .pre-commit-ci.yaml

Secrets management

Here are some advices about your secrets (variables marked with a 🔒):

  1. Manage them as project or group CI/CD variables:
    • masked to prevent them from being inadvertently displayed in your job logs,
    • protected if you want to secure some secrets you don't want everyone in the project to have access to (for instance production secrets).
  2. In case a secret contains characters that prevent it from being masked, simply define its value as the Base64 encoded value prefixed with @b64@: it will then be possible to mask it and the template will automatically decode it prior to using it.
  3. Don't forget to escape special characters (ex: $ -> $$).

Building your own pre-commit image

Building a pre-configured image is a must for pipeline speed, reproducibility and supply-chain security.

To build a preconfigured image, use the following guidelines:

  • use the smallest base image possible
  • embed all required pre-commit hooks (reminder: use only basic checks)

Bellow is an example Dockerfile to build such an image:

FROM registry.hub.docker.com/library/python:3-alpine

RUN mkdir /build

RUN apk add --no-cache git && \
    rm -rf /var/cache/apk/*

WORKDIR /build

RUN pip install --no-cache-dir pre-commit==3.5.0

RUN cat <<EOF > hook-install-config.yaml
repos:
    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: v4.5.0
      hooks:
        - id: no-commit-to-branch
        - id: trailing-whitespace
        - id: check-merge-conflict
        - id: check-yaml
        - id: end-of-file-fixer
        - id: fix-byte-order-marker
        - id: mixed-line-ending
EOF

COPY hook-install-config.yaml ./.pre-commit-config.yaml

RUN git init && \
    pre-commit install-hooks && \
    rm ./.pre-commit-config.yaml && \
    rm -rf .git

CMD ["--help"]

ENTRYPOINT ["pre-commit"]