6 Checks before every commit

Read the tutorial. Build it yourself is the other way to read this part.

This walk goes through rahuldave/cheesecracker on GitHub. This part starts from the code at step-05. The code before this part

To look at this code on your machine, run these commands. The first one makes a clone, if this folder has none:

[ -d cheesecracker ] || git clone https://github.com/rahuldave/cheesecracker
cd cheesecracker
git fetch --quiet --tags --force origin
git switch --detach step-05

just check works only when someone runs it. pre-commit runs checks before every git commit.

just setup

just check works only when someone runs it. pre-commit runs checks before every git commit, and stops the commit when a check fails. The checks are in .pre-commit-config.yaml.

6.1 pre-commit, in the group lint

pre-commit runs checks on the files of a commit, before git makes it. pre-commit calls each check a hook. git has hooks of its own, scripts that it runs before a commit, and a later move installs one of them to start pre-commit.

.pre-commit-config.yaml names the repository that each hook comes from, and the exact version to use. The first time pre-commit runs, it downloads each hook and installs it in a folder of its own. A failed check stops the commit. If a hook fixes a file, the commit stops too, and the fixed file waits for git add before the next try.

pre-commit checks the code, and the server does not need it to run. So it goes into the group lint, with ruff.

This change came from running uv add --group lint pre-commit.

uv run pre-commit --version

uv prints the version of pre-commit.

What changed

  • pyproject.toml: pre-commit, in the group lint. 1 line added. It comes from uv add --group lint pre-commit. The file
    • look at "pre-commit>=4.7.0",
  • uv.lock: the exact versions of pre-commit, and of the packages that it needs. 149 lines added, 1 removed. It comes from uv add --group lint pre-commit. The file

The diff of pyproject.toml
@@ -17,6 +17,7 @@ default-groups = "all"
 
 [dependency-groups]
 lint = [
+    "pre-commit>=4.7.0",
     "ruff>=0.17.1",
 ]
 test = [

This change on GitHub The code after it

6.2 the checks that run before every commit

pre-commit needs a list of checks. .pre-commit-config.yaml names two repositories of checks. The first, pre-commit-hooks, checks any file. The second, ruff-pre-commit, runs ruff's linter and formatter with the settings of pyproject.toml.

± See the new file .pre-commit-config.yaml

The new file .pre-commit-config.yaml names pre-commit-hooks at v6.0.0, with seven checks of any file, such as trailing-whitespace and detect-private-key. Then it names ruff-pre-commit at v0.17.1, with ruff-check and ruff-format.

pre-commit checks the files that git tracks, as they are in your folder. It skips a file that git does not track yet. The first run downloads the checks, which takes a minute.

uv run pre-commit run --all-files

pre-commit prints a line for each check, Passed or Skipped.

Every file of the project is in a commit here. check json says Skipped, because the project has no JSON file. Every other check says Passed.

What changed

  • .pre-commit-config.yaml: the checks that run before every commit. New, 22 lines. The file
    • look at - id: ruff-check

The diff of .pre-commit-config.yaml
@@ -0,0 +1,22 @@
+# The checks that run before every commit. `just hook` installs them as a git hook.
+# Run them on every file: uv run pre-commit run --all-files
+repos:
+  # Checks of any file
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v6.0.0
+    hooks:
+      - id: trailing-whitespace
+      - id: end-of-file-fixer
+      - id: check-yaml
+      - id: check-added-large-files
+        args: ["--maxkb=1000"]
+      - id: check-json
+      - id: check-merge-conflict
+      - id: detect-private-key
+
+  # ruff, with the settings in pyproject.toml: the linter, then the formatter
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: v0.17.1
+    hooks:
+      - id: ruff-check
+      - id: ruff-format

This change on GitHub The code after it

6.3 just hook installs the checks as a git hook

pre-commit runs before every commit only after it installs a hook in .git/hooks/. just setup never changes git, so the hook has a recipe of its own, hook. You run it once in each clone.

± See the change to justfile

The recipe hook, after the recipe setup, runs uv run pre-commit install.

just hook

pre-commit prints pre-commit installed at .git/hooks/pre-commit. From now on, git commit runs the checks first.

What changed

  • justfile: the recipe hook. 4 lines added. The file
    • look at uv run pre-commit install

The diff of justfile
@@ -11,6 +11,10 @@ default:
 setup:
     uv sync --locked
 
+# Install the git hook: the checks of .pre-commit-config.yaml before every commit. Once per clone
+hook:
+    uv run pre-commit install
+
 # Run the tests. Extra arguments go to pytest: just test tests/unit
 test *args:
     uv run pytest "$@"

This change on GitHub

This part ends at the code at step-06. The code after this part