6 Checks before every commit

Build it yourself. Read the tutorial 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

If you start at this part, make your clone as Get the project says, and then run this command. It puts in your clone the files that this part starts from. A file that the project deleted before this part stays, so delete it if git check lists it:

git fetch --quiet --tags --force origin; git rm -rq --cached --ignore-unmatch -- :/ && git restore --source step-05 --staged --worktree -- :/

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.

uv add --group lint pre-commit
uv run pre-commit --version

uv prints the version of pre-commit.

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check f3ad230bf911

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git fetch --quiet --tags --force origin; git restore --source step-05 --staged -- :/ && git restore --source f3ad230bf911 --staged --worktree -- :/

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 that uv add --group lint pre-commit makes in 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.

Apply the patch to .pre-commit-config.yaml, from the top of the project:

curl -fsSL https://github.com/rahuldave/cheesecracker/commit/009d77653eadfde09e438656cde77b5eac489115.diff | git apply --include=.pre-commit-config.yaml

Apply the patch, and read the two entries under repos. Each has an address, a version after rev, and its checks under hooks.

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.

.pre-commit-config.yaml is new, and git does not track it yet. So check yaml says (no files to check)Skipped. check json says Skipped, because the project has no JSON file.

ruff check checks only the Python files that git knows, which are those in a commit and those that are staged. A patch and an edit by hand stage nothing. So if you made every change here with patches or by hand, git knows none of the Python files, and ruff check says (no files to check)Skipped. A command that puts in the files of a part, at the top of a part or after a gap, stages them. If you ran one, ruff check says Passed. ruff format says Passed.

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check 009d77653ead

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git restore --source f3ad230bf911 --staged -- :/ && git restore --source 009d77653ead --staged --worktree -- :/

What changed

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

The patch to .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.

Apply the patch to justfile, from the top of the project:

curl -fsSL https://github.com/rahuldave/cheesecracker/commit/57ec2e24ecd4946823edbfad27bc2296f80e3847.diff | git apply --include=justfile

Read the recipe hook, after the recipe setup.

just hook

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

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check 57ec2e24ecd4

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git fetch --quiet --tags --force origin; git restore --source 009d77653ead --staged -- :/ && git restore --source step-06 --staged --worktree -- :/

What changed

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

The patch to 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