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
12 changes: 12 additions & 0 deletions .claude/skills/bump-versions/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: bump-versions
description: Refresh dev-tool pins in pyproject.toml, the uv pin in ci.yaml, and GitHub Actions SHA pins. Manual stand-in for Dependabot.
disable-model-invocation: true
---

Use [../../../docs/ai/bump-versions.md](../../../docs/ai/bump-versions.md) as
the source of truth for this skill.

This skill takes no arguments.

When this wrapper and the shared doc differ, follow the shared doc.
42 changes: 40 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ jobs:
continue-on-error: ${{ matrix.python-version != '3.12' }}

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
fetch-depth: 1

- uses: actions/setup-python@v6
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: ${{ matrix.python-version }}

Expand Down Expand Up @@ -56,3 +56,41 @@ jobs:

- name: Check package metadata
run: .venv/bin/twine check dist/*

# Verify the declared lower bounds in [project.dependencies] stay true instead
# of aspirational. Runs on the lowest supported Python (the floors are the
# first releases with cp312 wheels, so they neither install nor mean anything
# on 3.13/3.14 — that axis is covered by the `checks` matrix at latest deps).
min-versions:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
fetch-depth: 1

- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"

- name: Pin direct deps to their floors
# uv reads the floors straight from pyproject (single source of truth)
# and pins each DIRECT dep to its lowest version; --no-deps keeps
# transitive deps out of the constraints file so pip resolves those
# itself below — mirroring a user whose direct deps sit at our floors.
run: |
python -m pip install uv==0.11.27 # bump alongside the [dev] pins
uv pip compile --resolution lowest-direct --no-deps \
-o min-constraints.txt pyproject.toml
cat min-constraints.txt

- name: Install with pip (pip resolves the transitive graph)
run: |
python -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/pip install -c min-constraints.txt -e ".[dev]"

- name: Run tests
run: .venv/bin/pytest -q -m ""
10 changes: 5 additions & 5 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
contents: read
actions: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
fetch-depth: 0
Expand All @@ -26,7 +26,7 @@ jobs:
echo "Ref: $GITHUB_REF Sha: $GITHUB_SHA"
exit 1
fi
- uses: actions/setup-python@v6
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install package + dev tools
Expand All @@ -50,7 +50,7 @@ jobs:
run: .venv/bin/python -m build
- name: Check package metadata
run: .venv/bin/twine check dist/*
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: dist
path: dist/*
Expand All @@ -66,10 +66,10 @@ jobs:
actions: read
id-token: write
steps:
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: dist
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
#with:
# repository-url: https://test.pypi.org/legacy/
73 changes: 73 additions & 0 deletions docs/ai/bump-versions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Bump Versions

Refresh the pinned dev tooling and GitHub Actions SHAs. Run every few months
or before a release. This skill does the work of Dependabot (ecosystems
`pip` + `github-actions`) manually, as one deliberate bump-everything session
instead of a stream of PRs. If the manual runs get tedious, consider migrating
to Dependabot — but note two things it will NOT handle: the `uv==` pin inside
a `run:` script line in `ci.yaml`, and config migrations that a tool bump
requires (it only surfaces those as red CI on its PRs).

## What gets bumped

1. **`[dev]` exact pins** in `pyproject.toml` (`==` versions).
2. **The `uv==` pin** in the `min-versions` job of `.github/workflows/ci.yaml`
— it lives in a shell line, cross-referenced by comments from the `[dev]`
section. Always bump it in the same pass.
3. **GitHub Actions SHA pins** in `.github/workflows/*.yaml`
(`uses: owner/repo@<sha> # vX.Y.Z`).

Do NOT touch the lower bounds in `[project.dependencies]`. Those are
"supports Python >=3.12" floors, validated by the `min-versions` CI job, and
are only raised when code starts relying on a newer API — never as part of a
routine bump.

## Procedure

### 1. Dev pins (PyPI)

For each package in `[dev]` plus `uv`, look up the latest release:

```bash
curl -s https://pypi.org/pypi/<pkg>/json | python3 -c \
"import json,sys; print(json.load(sys.stdin)['info']['version'])"
```

Update the pins in `pyproject.toml` and the `uv==` line in `ci.yaml`.

### 2. Action SHA pins (GitHub)

For each `uses:` entry, find the latest tag and resolve it to the **peeled
commit SHA** — release tags are often annotated, and `git ls-remote` shows the
tag-object SHA on the bare ref. Pin the `^{}` (peeled) SHA when one is listed;
only when a tag has no `^{}` line is it lightweight and the bare SHA already
the commit:

```bash
git ls-remote --tags https://github.com/<owner>/<repo> | tail -20 # newest tags
git ls-remote https://github.com/<owner>/<repo> \
'refs/tags/<tag>' 'refs/tags/<tag>^{}'
```

Update to `owner/repo@<commit-sha> # <tag>` — keep the version comment
accurate, it is the only human-readable trace of what is pinned. Stay on the
same major unless release notes say the workflow inputs are unchanged.

### 3. Verify and run the suite

- Every changed pin must exist upstream: HTTP 200 from
`https://pypi.org/pypi/<pkg>/<version>/json`, and the commit SHA resolves via
`https://api.github.com/repos/<owner>/<repo>/commits/<sha>`.
- Reinstall and run the full check suite exactly as `ci.yaml` does: `pytest -q
-m ""`, `ruff check .` + `ruff format --check .`, `mypy --no-incremental`,
`pyright`, `deptry .`, `python -m build`, `twine check dist/*`.
- **Read the warnings, not just the exit codes.** Tool bumps can deprecate
config keys that still "work" (e.g. deptry 0.25 renamed
`pep621_dev_dependency_groups` → `optional_dependencies_dev_groups`).
Migrate `[tool.*]` config in the same pass so warnings never accumulate.

### 4. Report

Print a table of `package/action | old | new` plus any config migrations made,
and note anything held back (e.g. a major version skipped) with the reason.
Do not commit — leave the changes for the user to review.
1 change: 1 addition & 0 deletions docs/ai/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ working on the repo.

add-function
benchmark
bump-versions
changelog
check-docs
check-example
Expand Down
53 changes: 29 additions & 24 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,39 @@ classifiers = [
"Programming Language :: Python :: 3.14",
]

# Lower bounds are "supports Python >=3.12" floors, validated by the
# min-versions CI job (pins these floors, lets pip resolve the transitive graph,
# then runs the suite). Raise a floor when code starts relying on a newer API.
dependencies = [
"lmfit",
"asteval",
"numdifftools",
"emcee",
"tqdm",
"corner",
"numpy",
"pandas",
"scipy",
"ruamel.yaml",
"h5py",
"ipython",
"matplotlib",
"lmfit>=1.2",
"asteval>=1.0",
"numdifftools>=0.9.41",
"emcee>=3.1",
"tqdm>=4.66",
"corner>=2.2",
"numpy>=1.26",
"pandas>=2.1.1",
"scipy>=1.11.2",
"ruamel.yaml>=0.18",
"h5py>=3.10",
"ipython>=8.18",
"matplotlib>=3.8",
]

[project.optional-dependencies]
# NB: the min-versions CI job pins uv (see .github/workflows/ci.yaml) — bump it
# alongside these dev pins.
dev = [
"pre-commit",
"deptry",
"mypy",
"nbformat", # used by scripts/normalize_notebooks.py (pre-commit hook)
"nbstripout",
"pytest",
"pyright",
"ruff",
"build",
"twine",
"pre-commit==4.6.0",
"deptry==0.25.1",
"mypy==2.1.0",
"nbformat==5.10.4", # used by scripts/normalize_notebooks.py (pre-commit hook)
"nbstripout==0.9.1",
"pytest==9.1.1",
"pyright==1.1.411",
"ruff==0.15.20",
"build==1.5.0",
"twine==6.2.0",
]

# Optional notebook/visualization support
Expand Down Expand Up @@ -122,7 +127,7 @@ ignore = ["C901"]
[tool.deptry]
known_first_party = ["trspecfit"]
ignore_notebooks = true
pep621_dev_dependency_groups = ["dev"]
optional_dependencies_dev_groups = ["dev"]
# confidence interval estimation needs to work with standard install
# keep these as runtime deps even though used indirectly via lmfit
# py-spy is a CLI tool invoked via shell (see benchmark skill), not imported
Expand Down