Skip to content

Commit 2567286

Browse files
Add release process documentation
Document the full release lifecycle — pre-release planning, code freeze and branch creation, RC stabilization, final release, post-release, and patch releases — with step-by-step instructions and checklists for each phase. Covers versioning strategy, dependency management, changelog workflow, and CI automation (release.yml, docs-release.yml).
1 parent caf54d2 commit 2567286

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

docs/guide/release.rst

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
.. SPDX-FileCopyrightText: Copyright (c) 2026 The Newton Developers
2+
.. SPDX-License-Identifier: CC-BY-4.0
3+
4+
Release Process
5+
===============
6+
7+
This document describes how to prepare, publish, and follow up on a Newton
8+
release. It is intended for release engineers and maintainers.
9+
10+
Overview
11+
--------
12+
13+
Newton uses `PEP 440 <https://peps.python.org/pep-0440/>`__ versioning
14+
(``Major.Minor.Micro``), consistent with warp-lang:
15+
16+
.. list-table::
17+
:widths: 25 30 45
18+
:header-rows: 1
19+
20+
* - Kind
21+
- Example
22+
- When
23+
* - Stable
24+
- ``1.0.0``
25+
- Tagged GA releases published to PyPI
26+
* - Release candidate
27+
- ``1.0.0rc1``
28+
- Pre-release builds for QA validation
29+
* - Development
30+
- ``1.1.0.dev0``
31+
- ``main`` between releases
32+
33+
Releases are published to `PyPI <https://pypi.org/p/newton>`__ and
34+
documentation is deployed to
35+
`GitHub Pages <https://newton-physics.github.io/newton/>`__.
36+
37+
Version source of truth
38+
^^^^^^^^^^^^^^^^^^^^^^^
39+
40+
The version string lives in ``newton/_version.py``. All other version
41+
references (PyPI metadata, documentation) are derived from this file.
42+
43+
Dependency versioning strategy
44+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45+
46+
``pyproject.toml`` specifies **minimum** compatible versions
47+
(e.g. ``warp-lang>=1.12.0``). ``uv.lock`` pins the **latest known-good**
48+
versions for reproducible installs.
49+
50+
Exception: on the **release branch**, ``mujoco`` and ``mujoco-warp`` are
51+
pinned to **exact** versions (e.g. ``mujoco==3.5.0``) because Newton is
52+
tightly coupled to the MuJoCo API surface. ``main`` uses a version floor
53+
like other dependencies.
54+
55+
56+
Pre-release planning
57+
--------------------
58+
59+
.. rubric:: Checklist
60+
61+
.. list-table::
62+
:widths: 5 95
63+
:header-rows: 0
64+
65+
* - ☐
66+
- Determine target version (``X.Y.Z``).
67+
* - ☐
68+
- Confirm dependency versions and availability: warp-lang, mujoco,
69+
mujoco-warp, newton-usd-schemas, newton-actuators.
70+
* - ☐
71+
- Set timeline: code freeze → RC1 → testing window → GA.
72+
* - ☐
73+
- Conduct public API audit:
74+
75+
- Review all new/changed symbols since the last release for unintended
76+
breaking changes.
77+
- Verify deprecated symbols carry proper deprecation warnings and
78+
migration guidance.
79+
- Confirm new public API has complete docstrings and is included in
80+
Sphinx docs (run ``docs/generate_api.py``).
81+
* - ☐
82+
- Communicate the timeline to contributors.
83+
84+
85+
Code freeze and release branch creation
86+
---------------------------------------
87+
88+
1. Create the ``release-X.Y`` branch from ``main``.
89+
2. On **main**: bump ``newton/_version.py`` to ``X.(Y+1).0.dev0`` and run
90+
``docs/generate_api.py``.
91+
3. On **release-X.Y**: bump ``newton/_version.py`` to ``X.Y.ZrcN`` and run
92+
``docs/generate_api.py``.
93+
4. On **release-X.Y**: update dependencies in ``pyproject.toml`` from dev
94+
to RC versions where applicable, then regenerate ``uv.lock``
95+
(``uv lock``) and commit it.
96+
5. Push tag ``vX.Y.ZrcN``. This triggers the ``release.yml`` workflow
97+
(build wheel → PyPI publish with manual approval).
98+
99+
.. rubric:: Checklist
100+
101+
.. list-table::
102+
:widths: 5 95
103+
:header-rows: 0
104+
105+
* - ☐
106+
- ``release-X.Y`` branch created and pushed.
107+
* - ☐
108+
- ``main`` bumped to next dev version; ``generate_api.py`` run.
109+
* - ☐
110+
- RC1 version set on release branch; ``generate_api.py`` run.
111+
* - ☐
112+
- Dependencies updated from dev to RC versions; ``uv.lock`` regenerated.
113+
* - ☐
114+
- Tag ``vX.Y.Zrc1`` pushed.
115+
* - ☐
116+
- RC1 published to PyPI (approve in GitHub environment).
117+
118+
119+
Release candidate stabilization
120+
-------------------------------
121+
122+
Bug fixes merge to ``main`` first, then are cherry-picked to
123+
``release-X.Y``. Cherry-pick relevant commits from ``main`` onto a feature
124+
branch and open a pull request targeting ``release-X.Y`` — never push
125+
directly to the release branch.
126+
127+
For each new RC (``rc2``, ``rc3``, …) bump the version in
128+
``newton/_version.py`` and run ``docs/generate_api.py``, then tag and push.
129+
Iterate until CI is green and QA signs off.
130+
131+
.. rubric:: Checklist
132+
133+
.. list-table::
134+
:widths: 5 95
135+
:header-rows: 0
136+
137+
* - ☐
138+
- All release-targeted fixes cherry-picked from ``main``.
139+
* - ☐
140+
- CI passing on release branch.
141+
* - ☐
142+
- QA sign-off obtained.
143+
* - ☐
144+
- No outstanding release-blocking issues.
145+
146+
147+
.. _final-release:
148+
149+
Final release
150+
-------------
151+
152+
1. Finalize ``CHANGELOG.md``: rename ``[Unreleased]`` →
153+
``[X.Y.Z] - YYYY-MM-DD``.
154+
2. Update documentation links to point to versioned URLs where appropriate.
155+
3. Verify all dependency pins in ``pyproject.toml`` use stable
156+
(non-pre-release) versions.
157+
4. Regenerate ``uv.lock`` (``uv lock``) and verify that no pre-release
158+
dependencies remain in the lock file.
159+
5. Bump ``newton/_version.py`` to ``X.Y.Z`` (remove the RC suffix) and run
160+
``docs/generate_api.py``.
161+
6. Commit and push tag ``vX.Y.Z``.
162+
7. Automated workflows trigger:
163+
164+
- ``release.yml``: builds wheel, publishes to PyPI (requires manual
165+
approval), creates a draft GitHub Release.
166+
- ``docs-release.yml``: deploys docs to ``/X.Y.Z/`` and ``/stable/``
167+
on gh-pages, updates ``switcher.json``.
168+
169+
8. Review and publish (un-draft) the GitHub Release.
170+
171+
.. rubric:: Checklist
172+
173+
.. list-table::
174+
:widths: 5 95
175+
:header-rows: 0
176+
177+
* - ☐
178+
- Changelog finalized with release date.
179+
* - ☐
180+
- All dependency pins in ``pyproject.toml`` use stable (non-pre-release)
181+
versions.
182+
* - ☐
183+
- ``uv.lock`` regenerated and verified free of pre-release dependencies.
184+
* - ☐
185+
- Version bumped to ``X.Y.Z``; ``generate_api.py`` run.
186+
* - ☐
187+
- Tag ``vX.Y.Z`` pushed.
188+
* - ☐
189+
- PyPI publish approved and verified: ``pip install newton==X.Y.Z``.
190+
* - ☐
191+
- GitHub Release un-drafted and published.
192+
* - ☐
193+
- Docs live at ``/X.Y.Z/`` and ``/stable/``: verify links and version
194+
switcher.
195+
196+
197+
Post-release
198+
------------
199+
200+
1. Compare ``CHANGELOG.md`` between ``release-X.Y`` and ``main``. The
201+
release branch has the finalized ``[X.Y.Z]`` section, while ``main``
202+
still has those entries under ``[Unreleased]``.
203+
2. On **main**: merge back the changelog from the release branch so that
204+
all entries included in the release are moved from ``[Unreleased]`` to
205+
the ``[X.Y.Z]`` section. (The ``[Unreleased]`` header already exists
206+
on ``main`` from the post-branch-creation bump.)
207+
3. Verify PyPI installation works in a clean environment.
208+
4. Verify published docs render correctly.
209+
210+
.. rubric:: Checklist
211+
212+
.. list-table::
213+
:widths: 5 95
214+
:header-rows: 0
215+
216+
* - ☐
217+
- ``CHANGELOG.md`` on ``main`` updated: released entries moved from
218+
``[Unreleased]`` to ``[X.Y.Z]`` section.
219+
* - ☐
220+
- PyPI install verified.
221+
* - ☐
222+
- Published docs verified.
223+
224+
225+
Patch releases
226+
--------------
227+
228+
Patch releases (``X.Y.Z+1``) continue cherry-picking fixes to the existing
229+
``release-X.Y`` branch. Follow the same :ref:`final-release` flow — bump
230+
version, update changelog, tag, and push. There is no need to create a new
231+
branch or bump ``main``.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Newton Physics
1919
guide/visualization
2020
guide/tutorials
2121
Development <guide/development>
22+
Release Process <guide/release>
2223

2324
.. toctree::
2425
:maxdepth: 1

0 commit comments

Comments
 (0)