permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<sha>
with: { persist-credentials: false }
- uses: astral-sh/setup-uv@<sha>
- run: uv sync --locked
- run: uv run ruff check --output-format=github
- run: uv run ruff format --check
- run: uv run pyright
- run: uv run pytest --cov --cov-report=xmlPoints that are frequently omitted:
uv sync --lockedfails when the lockfile does not matchpyproject.toml, catching manual edits.setup-uvcaches by default on GitHub-hosted runners.- An application tests the one version its
.python-versionnames. A library runs the job over a matrix of every minor version from itsrequires-pythonfloor up, passing each tosetup-uvaspython-version. permissionsset at the top limits the workflow’sGITHUB_TOKEN; once any permission is listed, every unlisted one isnone, and a job that needs to write asks for that by name.persist-credentials: falsestopscheckoutleaving the token in.git/configfor every later step.pre-commitis used locally for formatting and quick checks; enforcement belongs in CI, since hooks can be bypassed.- Actions pinned to commit SHAs rather than tags, since tags are mutable.
- PyPI trusted publishing (OIDC) removes long-lived API tokens from CI secrets.
- Dependabot or Renovate for dependency and action updates.
- zizmor audits the workflow files themselves, for unpinned actions, template injection from untrusted input, over-broad permissions and persisted credentials.