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 as described in the versioning section of the installation guide.

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 specifies minimum compatible versions (e.g. warp-lang>=1.12.0). uv.lock pins the latest known-good versions for reproducible installs.

Exception: on the release branch, mujoco and mujoco-warp use compatible-release pins (e.g. mujoco~=3.5.0) to allow patch updates while locking the minor version. MuJoCo follows semantic versioning from 3.5.0 onward, so patch releases are safe to pick up automatically. main uses a version floor like other dependencies.

Deprecation timeline#

Following Warp’s deprecation policy, a deprecated feature is maintained for two full minor release cycles after deprecation (e.g. deprecated in 1.2.0 → removed in 1.4.0). Deprecations and removals only happen in minor releases, never in patch releases.

Pre-release planning#

Determine target version (X.Y.Z).

Confirm dependency versions and availability: warp-lang, mujoco, mujoco-warp, newton-usd-schemas, newton-actuators.

Set timeline: code freeze → RC1 → testing window → GA.

Conduct public API audit:

  • Review all new/changed symbols since the last release for unintended breaking changes.

  • Verify deprecated symbols carry proper deprecation warnings and migration guidance (see Deprecation timeline).

  • Confirm new public API has complete docstrings and is included in Sphinx docs (run docs/generate_api.py).

Communicate the timeline to the community.

Code freeze and release branch creation#

Create release-X.Y branch from main and push it.

On main: bump the version in pyproject.toml to X.(Y+1).0.dev0 and run docs/generate_api.py.

On release-X.Y: bump the version in pyproject.toml to X.Y.ZrcN and run docs/generate_api.py.

On release-X.Y: update dependencies in pyproject.toml from dev to RC versions where applicable, then regenerate uv.lock (uv lock) and commit it.

Push tag vX.Y.Zrc1. This triggers the release.yml workflow (build wheel → PyPI publish with manual approval).

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.

For each new RC (rc2, rc3, …) bump the version in pyproject.toml and run docs/generate_api.py, then tag and push. Resolve any cherry-pick conflicts or missing dependent cherry-picks that cause CI failures before tagging.

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 notes. Features explicitly 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 environment: pip install succeeds, import newton works, and examples and tests can be run from the installed wheel (pip install newton==X.Y.ZrcN).

  • No unexpected regressions compared to the previous release have been identified.

All release-targeted fixes cherry-picked from main.

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 CHANGELOG.md: rename [Unreleased][X.Y.Z] - YYYY-MM-DD. Review the entries for:

  • Missing entries — cross-check merged PRs since the last GA release (or patch) to catch changes that were not recorded in the changelog.

  • Redundant entries — consolidate or remove duplicates for changes within the same release period (e.g. a bug fix for a feature added in the same cycle should not appear as both an “Added” and a “Fixed” entry).

Update README.md documentation links to point to versioned URLs (e.g. /X.Y.Z/guide.html instead of /latest/).

Verify all dependency pins in pyproject.toml use stable (non-pre-release) versions.

Regenerate uv.lock (uv lock) and verify that no pre-release dependencies remain in the lock file.

Bump the version in pyproject.toml to X.Y.Z (remove the RC suffix) and run docs/generate_api.py.

Commit and push tag vX.Y.Z. Automated workflows trigger:

  • release.yml: builds wheel, publishes to PyPI (requires manual approval), creates a draft GitHub Release.

  • docs-release.yml: deploys docs to /X.Y.Z/ and /stable/ on gh-pages, updates switcher.json.

PyPI publish approved and verified: pip install newton==X.Y.Z.

GitHub Release un-drafted and published.

Docs live at /X.Y.Z/ and /stable/: verify links and version switcher.

Release announcement posted.

Post-release#

Merge back the changelog from release-X.Y to main: move entries included in the release from [Unreleased] to a new [X.Y.Z] section. ([Unreleased] is a permanent header in the changelog that always exists on main.)

Verify PyPI installation works in a clean environment.

Verify published docs render correctly.

Patch releases#

Patch 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.