Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
"nbsp",
"nopython",
"poethepoet",
"prek",
"prekignore",
"prereleased",
"pycode",
"pygments",
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/autofix.ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# The workflow name is load-bearing: autofix.ci only accepts a patch that was
# uploaded from a workflow named "autofix.ci". Do not rename it.
name: autofix.ci

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: |-
${{ github.ref != format('refs/heads/{0}', github.event.repository.default_branch) }}

on:
pull_request:
branches:
- main
- epic/*
- "[0-9]+.[0-9]+.x"
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

env:
FORCE_COLOR: true
PREK_COLOR: always

jobs:
autofix:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # the Jupyter kernel update diffs against the base branch
- uses: j178/prek-action@4e14d07f9231acabce116ccfca13b13dd9755ece # v3.0.0
with:
install-only: true
- id: prek
name: Run prek
continue-on-error: true
run: prek run --all-files
# The first run fails as soon as a hook rewrites a file, so it runs again
# against the fixed tree. A hook that only reports keeps the job red.
- if: steps.prek.outcome == 'failure'
name: Verify fixes
run: prek run --all-files
- if: >-
always() && !cancelled() &&
github.event_name == 'pull_request' &&
hashFiles('**/*.ipynb')
name: Update Jupyter kernels
uses: ComPWA/actions/update-jupyter-kernel@aa47e7f596961634fe54c446af2144a309501cda # PR #178 preview
with:
target-branch: origin/${{ github.event.pull_request.base.ref }}
upload-artifact: false
- if: always() && !cancelled()
name: Commit fixes
uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
style:
secrets:
token: ${{ secrets.PAT }}
uses: ComPWA/actions/.github/workflows/style.yml@13f1a3b0c831615fb49c008bcc48113da8a76477 # 4.0.2
uses: ComPWA/actions/.github/workflows/style.yml@aa47e7f596961634fe54c446af2144a309501cda # PR #178 preview
13 changes: 1 addition & 12 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
ci:
autofix_commit_msg: "MAINT: implement pre-commit autofixes"
autoupdate_commit_msg: "MAINT: upgrade lock files"
autoupdate_schedule: quarterly
skip:
- check-jsonschema
- tombi-format
- tombi-lint
- ty
- uv-lock

repos:
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes

- repo: https://github.com/ComPWA/policy
rev: 0.9.7
rev: a7f74b709e14037368cfa311cf5a7c999ef7c946 # PR #695 preview
hooks:
- id: check-dev-files

Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ uv sync --all-extras
source .venv/bin/activate
```

Formatting and linting checks are automatically performed when committing changes. This is done with [pre-commit](https://pre-commit.com). To install the hooks in your local repository, run install `pre-commit` with `uv`:
Formatting and linting checks are automatically performed when committing changes. This is done with [prek](https://prek.j178.dev), a drop-in replacement for [pre-commit](https://pre-commit.com) that reads the same `.pre-commit-config.yaml` file. To install the hooks in your local repository, [install `prek`](https://prek.j178.dev/installation) with `uv`:

```shell
uv tool install pre-commit --with pre-commit-uv --force-reinstall --python=3.13
uv tool install prek --force-reinstall
```

and [`pre-commit install`](https://pre-commit.com/#3-install-the-git-hook-scripts) **once**:
and run [`prek install`](https://prek.j178.dev/reference/cli/) **once**:

```shell
pre-commit install --install-hooks
prek install --prepare-hooks
```

[Poe the Poet](https://poethepoet.natn.io) is used as a task runner. Install it globally (within your home folder) with `uv`:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Binder](https://static.mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ComPWA/compwa.github.io/main)
[![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ComPWA/compwa.github.io/blob/main)
[![Open in Visual Studio Code](https://img.shields.io/badge/vscode-open-blue?logo=visualstudiocode)](https://open.vscode.dev/ComPWA/compwa.github.io)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/ComPWA/compwa.github.io/main.svg)](https://results.pre-commit.ci/latest/github/ComPWA/compwa.github.io/main)
[![prek](https://img.shields.io/badge/hooks-prek-261230.svg)](https://prek.j178.dev)
[![Spelling checked](https://img.shields.io/badge/cspell-checked-brightgreen.svg)](https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
Expand Down
112 changes: 85 additions & 27 deletions docs/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ pixi shell
:::
::::

In addition, [`pre-commit`](https://pre-commit.com) is used to enforce style checks and can be installed with::
In addition, [prek](https://prek.j178.dev) is used to enforce style checks and can be installed with:

```shell
uv tool install --python=3.13 --with pre-commit-uv pre-commit
pre-commit install --install-hooks
uv tool install prek
prek install --prepare-hooks
```

If you already had `pre-commit` installed in this repository, see {ref}`develop:Prek` for how to replace its Git hooks.

In `uv`-only projects, [Poe the Poet](https://poethepoet.natn.io) is used as task runner and can be installed with:

```shell
Expand Down Expand Up @@ -187,7 +189,7 @@ requirements can be installed with the last example.

### Pinning dependency versions

To ensure that developers use exactly the same versions of the package dependencies and developer requirements, some of the repositories provide lock files, such as [`uv.lock`](https://docs.astral.sh/uv/concepts/projects/sync) and [`pixi.lock`](https://pixi.prefix.dev/v0.63.2/workspace/lockfile). The constraint files are updated automatically with the [ComPWA/actions/.github/workflows/lock.yml](https://github.com/ComPWA/actions/blob/v4/.github/workflows/lock.yml) workflow using {ref}`develop:GitHub Actions`.
To ensure that developers use exactly the same versions of the package dependencies and developer requirements, some of the repositories provide lock files, such as [`uv.lock`](https://docs.astral.sh/uv/concepts/projects/sync) and [`pixi.lock`](https://pixi.prefix.dev/v0.63.2/workspace/lockfile). The constraint files are updated automatically with the [ComPWA/actions/.github/workflows/lock.yml](https://github.com/ComPWA/actions/blob/v4/.github/workflows/lock.yml) workflow using {ref}`develop:GitHub Actions`. That workflow also bumps the hook revisions in `.pre-commit-config.yaml` with `uvx prek autoupdate`, which is what the {ref}`local <develop:checks>` `poe upgrade` task does as well.

:::{note}
Constraint files ensure that the framework is _deterministic and reproducible_ (up to
Expand Down Expand Up @@ -315,42 +317,54 @@ notebooks with Julia kernels into your {ref}`documentation<develop:Documentation

## Automated coding conventions

Where possible, we define and enforce our coding conventions through automated tools, instead of describing them in documentation. These tools perform their checks when you commit files locally (see {ref}`develop:Pre-commit`), when {ref}`running checks locally <develop:checks>`, and when you make a {ref}`pull request <develop:Collaboration>`.
Where possible, we define and enforce our coding conventions through automated tools, instead of describing them in documentation. These tools perform their checks when you commit files locally (see {ref}`develop:Prek`), when {ref}`running checks locally <develop:checks>`, and when you make a {ref}`pull request <develop:Collaboration>`.

The tools are mainly configured through [`pyproject.toml`](https://github.com/ComPWA/ampform/blob/main/pyproject.toml) and the workflow files under [`.github`](https://github.com/ComPWA/ampform/blob/main/.github). These configuration files are kept up to date through the [ComPWA/policy](https://compwa.github.io/policy) repository, which essentially defines the developer environment across [all ComPWA repositories](https://github.com/orgs/ComPWA/repositories?q=archived%3Ano&type=all&language=&sort=name).

If you run into persistent linting errors, this may mean we need to further specify our conventions. In that case, it's best to {ref}`create an issue <develop:Issue management>` or a {ref}`pull request <develop:Collaboration>` at [ComPWA/policy](https://github.com/ComPWA/policy) and propose a policy change that can be formulated through those config files.

### Pre-commit
(pre-commit)=

### Prek

All {ref}`style checks <develop:Style checks>` are enforced through [prek](https://prek.j178.dev), a drop-in replacement for [pre-commit](https://pre-commit.com). It reads the same [{file}`.pre-commit-config.yaml`](https://github.com/ComPWA/ampform/blob/main/.pre-commit-config.yaml) file and the same hook definitions, so only the command and the local set-up differ. Install it once as a global tool with [`uv`](https://docs.astral.sh/uv):

```shell
uv tool install prek
```

All {ref}`style checks <develop:Style checks>` are enforced through a tool called
[{command}`pre-commit`](https://pre-commit.com). It's best to activate this tool locally
as well. This has to be done only once, after you clone the repository:
It's best to activate the hooks locally as well. This has to be done only once, after you clone the repository:

```shell
pre-commit install --install-hooks
prek install --prepare-hooks
```

:::{margin} Initializing pre-commit
The first time you run {command}`pre-commit` after installing or updating its checks, it
may take some time to initialize.
:::{margin} Initializing prek
The `--prepare-hooks` flag installs the hook environments right away, instead of on your first commit. This may take some time, but prek creates the environments with `uv` and in parallel, so it is considerably faster than `pre-commit` was.
:::

Upon committing, {command}`pre-commit` runs a set of checks as defined in the file
[{file}`.pre-commit-config.yaml`](https://github.com/ComPWA/ampform/blob/main/.pre-commit-config.yaml)
over all staged files. You can also quickly run all checks over _all_ indexed files in
the repository with the command:
Upon committing, prek runs a set of checks as defined in the file [{file}`.pre-commit-config.yaml`](https://github.com/ComPWA/ampform/blob/main/.pre-commit-config.yaml) over all staged files. You can also quickly run all checks over _all_ indexed files in the repository with the command:

```shell
pre-commit run -a
prek run --all-files
```

Whenever you {ref}`submit a pull request <develop:Collaboration>`, this command is
automatically run
[on GitHub actions](https://github.com/ComPWA/ampform/actions/workflows/ci.yml)
and [on pre-commit.ci](https://results.pre-commit.ci/install/github/18435973) , ensuring
that all files in the repository follow the same conventions as set in the config files
of these tools.
:::{admonition} Coming from `pre-commit`
:class: tip
The Git hooks under `.git/hooks` are installed per developer and are not tracked by Git, so no policy update can replace them for you. If you previously ran `pre-commit install`, the shims there still call `pre-commit`. Either run `prek install --prepare-hooks` again to overwrite them, or let [`policy migrate`](https://compwa.github.io/policy/check-dev-files/migrations.html) detect and replace them:

```shell
uvx --from git+https://github.com/ComPWA/policy --refresh policy migrate
```

You can then uninstall the old tool with `uv tool uninstall pre-commit`. The `pre-commit-uv` package is no longer needed either: prek uses `uv` natively.
:::

:::{warning}
prek has a [workspace mode](https://prek.j178.dev/workspace/) that discovers _nested_ `.pre-commit-config.yaml` files, which `pre-commit` does not. If a repository ships such a file as a test fixture, list its directory in a [`.prekignore`](https://prek.j178.dev/workspace/) file, so that prek does not run it as a real project.
:::

Whenever you {ref}`submit a pull request <develop:Collaboration>`, the same checks are run automatically [on GitHub Actions](https://github.com/ComPWA/ampform/actions/workflows/ci.yml), ensuring that all files in the repository follow the same conventions as set in the config files of these tools. Fixes that the hooks make are committed back to your branch by {ref}`autofix.ci <develop:autofix.ci>`.

### Checks

Expand All @@ -368,6 +382,38 @@ Poe the Poet is installed through the `dev` dependency group. However, since the
uv tool install poethepoet
```

The task that runs all {ref}`style checks <develop:Style checks>` is `style`. It is a thin wrapper around `prek run --all-files`, so these three commands are equivalent:

::::{tab-set}
:::{tab-item} uv

```shell
poe style
```

:::
:::{tab-item} Pixi

```shell
pixi run style
```

:::
:::{tab-item} prek

```shell
prek run --all-files
```

:::
::::

Repositories with lock files additionally define an `upgrade` task, which runs `prek autoupdate -j8` through the `_upgrade-prek` helper task, next to the helper tasks that upgrade the lock files themselves (see {ref}`develop:Pinning dependency versions`):

```shell
poe upgrade
```

### GitHub Actions

All {ref}`style checks <develop:Style checks>`, testing of the
Expand All @@ -378,6 +424,18 @@ All {ref}`style checks <develop:Style checks>`, testing of the
[`.github`](https://github.com/ComPWA/ampform/blob/main/.github) folder. All checks
performed for each PR have to pass before the PR can be merged.

#### autofix.ci

Most {ref}`style checks <develop:Style checks>` do not just report a problem, they fix it. Those fixes are committed back to your pull request by [autofix.ci](https://autofix.ci), a GitHub App that ComPWA repositories activate through a workflow file named {file}`.github/workflows/autofix.ci.yml`. The workflow runs `prek run --all-files`, updates the {ref}`Jupyter kernel names <develop:Jupyter Notebooks>`, and hands the resulting patch to the app, which pushes it as a commit authored by `autofix-ci[bot]`. This replaces [pre-commit.ci](https://pre-commit.ci), which ComPWA repositories used before and which runs `pre-commit` rather than prek.

There are a few things to be aware of:

- The workflow file has to be named exactly `autofix.ci`. The service uses that name to recognize the workflow it trusts, both in the action and on its own servers, so renaming the file silently disables the fixes.
- autofix.ci does apply fixes to pull requests from forks, which the previous push job could not do. It does _not_ apply a patch when the last four commits were authored by a bot, so a long series of automated commits has to be interrupted by a human commit.
- Since autofix.ci commits the fixes, the {ref}`style workflow <develop:GitHub Actions>` skips its own push job when it finds an `autofix.ci.yml` in the repository. Fixes are therefore never committed twice.

If a check only _reports_ a problem, such as a spelling mistake or a type error, there is nothing to commit and you have to fix it yourself. Run `poe style` locally to see the same output.

## Style checks

### Formatting
Expand All @@ -394,7 +452,7 @@ Ruff](https://beta.ruff.rs/docs/rules/#isort-i)). For other code, we use
they offer only limited configuration options, as to make formatting as conform as
possible.

{ref}`develop:Pre-commit` performs some additional formatting jobs. For instance, it
{ref}`develop:Prek` performs some additional formatting jobs. For instance, it
formats Jupyter notebooks with [nbQA](https://github.com/nbQA-dev/nbQA) and strips them
of any output cells with [`nbstripout`](https://github.com/kynan/nbstripout).

Expand All @@ -416,7 +474,7 @@ As a tool, we use
[cSpell](https://github.com/streetsidesoftware/cspell/blob/master/packages/cspell/README.md),
because it allows to check variable names in camel case and snake case. This way, a
spelling checker helps you avoid mistakes in the code as well! cSpell is enforced
through pre-commit.
through {ref}`prek <develop:Prek>`.

Accepted words are tracked through the
[`.cspell.json`](https://github.com/ComPWA/ampform/blob/main/.cspell.json) file. As with
Expand Down Expand Up @@ -558,7 +616,7 @@ poe docnblive
```

:::{tip}
Notebooks are automatically formatted through {ref}`pre-commit <develop:Pre-commit>` (see {ref}`develop:Formatting`). If you want to format the notebooks automatically as you're working, you can do so with [`jupyterlab-code-formatter`](https://jupyterlab-code-formatter.readthedocs.io), which is automatically {ref}`installed with the dev requirements <develop:Optional dependencies>`.
Notebooks are automatically formatted through {ref}`prek <develop:Prek>` (see {ref}`develop:Formatting`). If you want to format the notebooks automatically as you're working, you can do so with [`jupyterlab-code-formatter`](https://jupyterlab-code-formatter.readthedocs.io), which is automatically {ref}`installed with the dev requirements <develop:Optional dependencies>`.

For this, you need to set Ruff as the formatter (see [](#formatting)) for `jupyterlab-code-formatter`:

Expand Down
13 changes: 8 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -197,17 +197,20 @@ sequence = [
]

[tool.poe.tasks.style]
cmd = "pre-commit run --all-files"
cmd = "prek run --all-files"
executor = { group = "style" }
help = "Perform all linting, formatting, and spelling checks"

[tool.poe.tasks.upgrade]
executor = { type = "simple" }
help = "Upgrade lock files"
parallel = ["_upgrade-precommit", "_upgrade-uv"]
parallel = [
"_upgrade-prek",
"_upgrade-uv",
]

[tool.poe.tasks._upgrade-precommit]
cmd = "pre-commit autoupdate -j8"
[tool.poe.tasks._upgrade-prek]
cmd = "prek autoupdate -j8"
executor = { type = "simple" }

[tool.poe.tasks._upgrade-uv]
Expand Down Expand Up @@ -421,7 +424,7 @@ key-empty = "off"

[[tool.tombi.schemas]]
root = "tool.compwa.policy"
path = "https://raw.githubusercontent.com/ComPWA/policy/0.9.7/compwa-policy.schema.json"
path = "https://raw.githubusercontent.com/ComPWA/policy/a7f74b709e14037368cfa311cf5a7c999ef7c946/compwa-policy.schema.json"
include = ["pyproject.toml"]

[[tool.ty.overrides]]
Expand Down