uv run ruff check . and uv run pytest -q are clean. Regenerate tests/mr_examples.py
only if the modern_robotics pin changed (step 5).
With CoppeliaSim open (4.9 or later; 0.1 was verified on 4.10.0) and the stock UR5 model
loaded at /UR5 (Model browser > robots > non-mobile > UR5.ttm; no tip dummy needed),
run the simulator tests: SCREWS_COPPELIASIM=1 uv run pytest -q -m coppelia
(SCREWS_COPPELIASIM_PORT=<port> for an instance started with -GzmqRemoteApi.rpcPort=<port>).
If a run is killed mid-way the simulation can be left waiting on a dead stepping
client; Scene.start() stops such a simulation first, so a rerun recovers by itself.
Bump the version in screws/_version.py, pyproject.toml and CITATION.cff (they must
agree; tests/test_readme_table.py pins the release number), set date-released in
CITATION.cff, and turn the changelog's "Unreleased" into the release's heading.
If screws/aliases.py changed, regenerate the table with
uv run python tools/print_alias_table.py and paste it into docs/guide/names.md.
If the modern_robotics dev pin changed, re-harvest the docstring examples:
uv run python tools/harvest_mr_examples.py.
Commit, then tag and push the tag: git tag v<version> && git push origin v<version>.
The Publish to PyPI workflow (.github/workflows/publish.yml) checks that the tag
matches pyproject.toml and _version.py, runs the suite, builds, and uploads.
It uses the PYPI_API_TOKEN repository secret when set, else PyPI trusted publishing
(register the workflow as a publisher for screws on pypi.org, environment pypi).
Fallback by hand: uv build && uvx twine upload dist/* (uv publish ignores ~/.pypirc).
Watch it: gh run watch. Then make a GitHub release of the tag, its notes the changelog
section: gh release create v<version> --verify-tag --title v<version> --notes-file <file>.
Zenodo archives each GitHub release (not each tag) and gives it a DOI of its own. The
concept DOI in the README and CITATION.cff, 10.5281/zenodo.23873253, stays the same and
resolves to the newest, so nothing in the repo changes for it.