Skip to content
Merged
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 .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

*.sh text eol=lf
*.traj binary

uv.lock linguist-generated=true
26 changes: 25 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,32 @@ updates:
directory: "/"
schedule:
interval: monthly
cooldown:
default-days: 7
groups:
github-actions:
patterns: ["*"]

- package-ecosystem: pip
# Keep the lower bounds in pyproject.toml as the oldest supported versions
# and refresh only uv.lock, which pins what development and CI use.
- package-ecosystem: uv
directory: "/"
schedule:
interval: monthly
versioning-strategy: lockfile-only
cooldown:
default-days: 7
groups:
python:
patterns: ["*"]
update-types: [minor, patch]

- package-ecosystem: pre-commit
directory: "/"
schedule:
interval: monthly
cooldown:
default-days: 7
groups:
pre-commit:
patterns: ["*"]
127 changes: 97 additions & 30 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,121 @@ name: CI

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read
permissions: {}

env:
FORCE_COLOR: "1"

jobs:
checks:
lint:
name: Lint and type check
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read

steps:
- name: Check out the repository
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml
persist-credentials: false

- name: Install the package and development tools
run: |
python -m pip install --upgrade pip
python -m pip install --group dev -e .
- name: Set up uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Lint
run: ruff check .
- name: Install the project
run: uv sync --locked

- name: Check formatting
run: ruff format --check .
- name: Run the pre-commit hooks
run: uv run --locked prek run --all-files --show-diff-on-failure

- name: Type check
run: mypy
run: uv run --locked mypy

test:
name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }}, ${{ matrix.resolution }})
runs-on: ${{ matrix.os }}
timeout-minutes: 15
permissions:
contents: read

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.14", "3.15"]
resolution: [locked]
include:
# The oldest dependency versions allowed by pyproject.toml.
- os: ubuntu-latest
python-version: "3.14"
resolution: lowest-direct
# The free-threaded (no-GIL) build.
- os: ubuntu-latest
python-version: "3.14t"
resolution: locked

steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
with:
python-version: ${{ matrix.python-version }}

- name: Test with the locked dependencies
if: matrix.resolution == 'locked'
run: uv run --locked --no-default-groups --group test pytest

- name: Test
run: pytest
- name: Test with the oldest allowed dependencies
if: matrix.resolution == 'lowest-direct'
run: uv run --resolution lowest-direct --no-default-groups --group test pytest

- name: Build distributions
run: python -m build
build:
name: Build distributions
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read

steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Validate distributions
run: python -m twine check dist/*
- name: Build the sdist and wheel
run: uv build --no-sources

- name: Smoke test the wheel
run: |
python -m pip install --force-reinstall --no-deps dist/*.whl
python -m template_python Codex
run: uv run --isolated --no-project --with dist/*.whl template-python CI

- name: Smoke test the sdist
run: uv run --isolated --no-project --with dist/*.tar.gz python -m template_python CI

all-green:
name: All checks passed
if: always()
needs: [lint, test, build]
runs-on: ubuntu-latest
timeout-minutes: 5
permissions: {}

steps:
- name: Fail if any required job did not succeed
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1
73 changes: 73 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Release

# Publishes to PyPI with trusted publishing when a GitHub release is published.
# Before the first release, add this repository as a trusted publisher on PyPI
# and create a "pypi" environment in the repository settings.

on:
release:
types: [published]

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

permissions: {}

jobs:
build:
name: Build distributions
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read

steps:
- name: Check out the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
with:
enable-cache: false

- name: Check the tag matches the project version
run: |
version="$(uv version --short)"
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
echo "::error::Tag ${GITHUB_REF_NAME} does not match version ${version}"
exit 1
fi

- name: Build the sdist and wheel
run: uv build --no-sources

- name: Upload the distributions
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: dist
path: dist/
if-no-files-found: error

publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
name: pypi
url: https://pypi.org/project/template-python/
permissions:
id-token: write # trusted publishing and PEP 740 attestations

steps:
- name: Download the distributions
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: dist
path: dist/

- name: Publish with trusted publishing and attestations
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
15 changes: 14 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,28 @@ repos:
rev: v6.0.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: end-of-file-fixer
- id: mixed-line-ending
args: [--fix=lf]
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.1
rev: v0.16.10
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format

- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.12.24
hooks:
- id: uv-lock

- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.30.1
hooks:
- id: zizmor
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
Loading
Loading