Release Process#
This document describes how to prepare, publish, and follow up on a Newton release. It is intended for release engineers and maintainers.
Overview#
Newton follows PEP 440 versioning; see Versioning in the compatibility guide for details.
Releases are published to PyPI and documentation is deployed to GitHub Pages.
Version source of truth#
The version string lives in the [project] table of pyproject.toml.
All other version references (PyPI metadata, documentation) are derived from
this file. At runtime, newton/_version.py reads the version from
installed package metadata via importlib.metadata.
Dependency versioning strategy#
pyproject.toml generally specifies minimum compatible versions
(e.g. warp-lang>=1.12.0). uv.lock pins the latest known-good
versions for reproducible installs.
mujoco and mujoco-warp instead use compatible-release pins on
both main and release branches (e.g. mujoco~=3.5.0) to allow
3.5.x updates while excluding 3.6.0 and later. MuJoCo follows
custom versioning from 3.5.0 onward; its third component is
MINOR_OR_PATCH and guarantees API backward compatibility.
Deprecation and removal timeline#
The user-facing deprecation and removal policy lives in
Deprecation Policy. Release engineers should ensure that every
deprecation, removal, or other breaking change in a minor release is
reflected in CHANGELOG.md and the API documentation, and that
deprecations emit a runtime DeprecationWarning where applicable.
Release progress record#
Maintain a top-level checklist such as RELEASE_X_Y_PROGRESS.md throughout
the release. It may remain uncommitted. Record release refs, PRs and
backports, validation results, tags, approvals, publication URLs, exceptions,
and remaining actions. A dedicated worktree can help keep release changes
separate from main, but is not required.
Pre-release planning#
☐ |
Determine target version ( |
☐ |
Review the previous release branch, preparation PRs, and lightweight tags for the current conventions. |
☐ |
Select release dependency versions and confirm their availability on
public PyPI: warp-lang, mujoco, mujoco-warp, newton-usd-schemas. Land
release-ready versions on |
☐ |
When the stable Warp version for the upcoming Newton release is
published before the branch cut, stabilize it on |
☐ |
Set timeline: code freeze → RC1 → testing window → GA. |
☐ |
Conduct public API audit:
Run the |
Code freeze and release branch creation#
☐ |
Fetch |
☐ |
On main: bump the version in |
☐ |
On release-X.Y: bump the version in |
☐ |
On release-X.Y: update dependencies in |
☐ |
Run the |
☐ |
Manually trigger the minimum-dependency and multi-GPU CI
workflows on the # Minimum-dependency tests (lowest compatible PyPI versions)
gh workflow run minimum_deps_tests.yml --ref release-X.Y
# Multi-GPU tests (g7e.12xlarge = 4× L40S GPUs)
gh workflow run aws_gpu_tests.yml --ref release-X.Y \
-f instance-type=g7e.12xlarge
|
☐ |
Push tag |
☐ |
RC1 published to PyPI (approve in GitHub environment). |
Release candidate stabilization#
Bug fixes merge to main first, then are cherry-picked to
release-X.Y. Cherry-pick relevant commits from main onto a feature
branch and open a pull request targeting release-X.Y — never push
directly to the release branch.
Review changes on main since the branch point and agree on the backport
scope. Release-milestone PRs should normally be included; record picks and
exclusions in the progress checklist.
Prefer sequential cherry-picks in main order with git cherry-pick -x
and keep the backport PR unsquashed. Keep change/revert pairs together. A bulk
merge is appropriate only when every intervening commit belongs in the release.
Finalize the changelog on release-X.Y and reconcile it to main after
release, as described in Post-release.
For each new RC, repeat the version, generated-file, validation, and tag steps used for RC1.
ASV runs the same benchmark definition on the base and head. If the base lacks an API used by a new benchmark, verify that the head passed and document the incompatibility. Any head failure or unexplained result blocks the release.
Testing criteria#
The release engineer and maintainers decide which issues must be fixed before GA and which can ship as known issues documented in the release materials. Features marked experimental have a lower bar — regressions in experimental APIs do not necessarily block a release.
As a guideline, an RC is typically ready for GA when:
All examples run without crashes, excessive warnings, or visual artifacts (
uv run -m newton.examples <name>).Testing covers Windows and Linux, all supported Python versions, and both latest and minimum-spec CUDA drivers (see system requirements in the installation guide).
PyPI installation of the RC works in a clean, isolated
uvenvironment: dependency resolution succeeds,import newtonworks, and package metadata plusnewton.__version__both reportX.Y.ZrcN.No unexpected regressions compared to the previous release have been identified.
☐ |
All release-targeted fixes cherry-picked from |
☐ |
Re-run the |
☐ |
Prepare draft GitHub Release notes: summary, a few highlights, link
to |
☐ |
Testing criteria satisfied. |
☐ |
No outstanding release-blocking issues. |
Final GA release#
Before proceeding, obtain explicit go/no-go approval from the maintainers. Do not start the final release steps until sign-off is confirmed.
All steps below are performed on the release-X.Y branch unless noted otherwise.
☐ |
Go/no-go approval obtained from maintainers. |
☐ |
Finalize |
☐ |
Update |
☐ |
Verify all dependency pins in |
☐ |
Bump the version in |
☐ |
Regenerate |
☐ |
Run pre-commit, focused release tests, and a clean wheel/source build.
Verify the built metadata reports exactly |
☐ |
Confirm programmatically that |
☐ |
Merge the GA preparation PR, then create lightweight tag
|
☐ |
In the tag-triggered Release workflow, open the waiting Publish Python
distribution to PyPI job, choose Review deployments, select the
|
☐ |
Review the draft GitHub Release notes before publishing. Keep them
concise: summary, a few highlights, link to |
☐ |
GitHub Release un-drafted and published. |
☐ |
Docs live at |
☐ |
Release announcement posted. |
Check the target version through the PyPI JSON API before tagging:
uv run --no-project --isolated --python 3.12 python -c \
"import json, urllib.request; print(sorted(json.load(urllib.request.urlopen('https://pypi.org/pypi/newton/json'))['releases']))"
After approval, verify the artifact from a clean environment:
uv run --no-project --isolated --python 3.12 --with newton==X.Y.Z \
python -c "import importlib.metadata as m, newton; print(m.version('newton')); print(newton.__version__); print(newton.__file__)"
If the docs workflow passes but /stable/ is stale, retry the versioned page,
stable page, and switcher.json after a few minutes. Inspect gh-pages
only to distinguish deployment failure from propagation delay.
Post-release#
☐ |
Merge the |
☐ |
Verify PyPI installation works in a clean environment. |
☐ |
Verify published docs render correctly. |
Micro releases#
Micro releases continue cherry-picking fixes to the existing
release-X.Y branch. For example, 1.0.1 follows 1.0.0.
Follow the same Final GA release flow — bump version, update changelog,
tag, and push. There is no need to create a new branch or bump main.