Composite action that runs pre-commit hooks against the PR diff and posts a sticky comment with the result.
Replaces the style.yaml boilerplate currently duplicated across ~20 two-inc repos.
Copy this workflow verbatim into .github/workflows/style.yaml:
name: Style
on:
pull_request:
types: [opened, synchronize, reopened]
concurrency:
group: pre-commit-${{ github.ref_name }}
cancel-in-progress: true
jobs:
pre-commit:
runs-on: ${{ vars.RUNNER_STANDARD }}
timeout-minutes: 20
permissions:
contents: read
pull-requests: write
steps:
- uses: two-inc/pre-commit-action@main
with:
python-version: "3.12"| Input | Default | Description |
|---|---|---|
python-version |
3.12 |
Python version to install |
github-token |
${{ github.token }} |
Token used to post the sticky comment |
node-version |
unset | If set, install Node.js of this version and run npm ci before pre-commit. Needed for hybrid Python+Node repos whose hooks import packages from node_modules. |
- Checks out the PR with full history (
fetch-depth: 0) so pre-commit can diff againstorigin/${{ github.base_ref }}. - Installs
uvwith caching enabled, sets up Python. - Runs
uvx pre-commit run --from-ref ... --to-ref ...against the PR diff. Pre-commit is installed in an ephemeral environment; it manages each hook's isolated environment itself. - Posts the result as a sticky PR comment identified by the
pre-commitheader marker — the comment is updated in place across pushes instead of deleted and recreated. - Exits with pre-commit's exit code so the job reflects pass/fail.
The pre-commit run step exports PIP_EXTRA_INDEX_URL=https://europe-python.pkg.dev/tillit-api/two-pypi/simple/ so that hooks using language: python + additional_dependencies: ["two-dev-cli"] (or any other internal package) can install without extra wiring on the caller side. The index is anonymously readable, so it's harmless for repos that don't use internal packages.
If a local hook needs to shell out to a two-inc CLI (e.g. two lint), declare it as:
- repo: local
hooks:
- id: two-lint
name: two-lint
language: python
entry: two lint
additional_dependencies: ["two-dev-cli"]
pass_filenames: falseDo not use language: system for these hooks — the action runs pre-commit via uvx without syncing the project venv, so system hooks that shell out to project-installed binaries won't find them.
Alongside adopting this action, consumer repos should:
- Remove
pre-commitfrom[dependency-groups].dev— not needed. The action runs pre-commit viauvx, which installs it on the fly. Pre-commit isn't actually a project dependency. - Bump stale hook revisions if any use the removed
language: python_venvalias. Latest pre-commit (4.x) rejects this — it was deprecated in favour oflanguage: python. Fordocformatter, upgrade tov1.7.8or later.
The action deliberately drops two things that appeared in many existing style.yaml files:
- GCP Artifact Registry auth — not needed.
uvx pre-commitpulls pre-commit from public PyPI; no private-index access required. uv sync --group dev— not needed.uvxhandles the ephemeral environment.