BSK Release Guide

On this page

This guide describes how Basilisk maintainers prepare, validate, and publish major and patch releases. In this guide, a major Basilisk release means a scheduled 2.X.0 feature release, while a patch release means 2.X.Y for Y > 0.

The release workflows contain the ordering and branch decisions. Detailed commands and procedures are collected under Common Release Tasks so the same instructions can be used for both major and patch releases.

Release Model

The version in docs/source/bskVersion.txt, the release tag, and the commit being published must agree. Package versions use PEP 440 syntax without a leading v; Git tags add the leading v.

Basilisk release types

Release type

Source branch

Package version

Tag location

Destination

Major

develop through feature/v2_X_0

2.X.0

master

PyPI

Patch

patch/v2_X_x

2.X.Y

Patch branch

PyPI

Release candidate

Branch being validated

2.X.YrcN

Tested commit

TestPyPI

Pushing a version tag starts the Publish Wheels GitHub Actions workflow. Final tags publish to PyPI, while release-candidate and test* tags publish to TestPyPI.

Release Workflows

Major Release

Use this workflow for a scheduled 2.X.0 release. After publication, finish the workflow by starting the next beta cycle on develop.

Prepare

  1. Create feature/v2_X_0 from develop after all intended release content has been merged.

  2. Finalize the release notes and known issues for 2.X.0.

  3. If a release candidate is required, follow Validate a Release Candidate on the release branch.

  4. Set and verify the final version as 2.X.0.

Validate

  1. Run clean local validation.

  2. Push the release branch and open a PR to develop.

  3. Wait for the Pull Request workflow to pass before merging.

Publish

  1. Merge the release PR into develop.

  2. Merge develop into master.

  3. Create and push the final tag v2.X.0 from master.

  4. Wait for the Publish Wheels workflow to finish and verify the published artifacts.

  5. Create the GitHub Release.

Start the Next Beta Cycle

After the major release is published, prepare develop for the next major release:

  1. Create a beta_X_Y branch from develop for the next planned release.

  2. Set docs/source/bskVersion.txt to the next beta version, such as 2.X.0b0. Do not include a leading v.

  3. Keep the completed release notes under their literal version and date in docs/source/Support/bskReleaseNotes/2.X.rst. Create the next series page if needed and add it at the top of the bskReleaseNotes.rst index. At the top of the next series page, add a Version |release| section containing the active .. include:: ../bskReleaseNotesSnippets/_compiled_latest.rst directive. Move the bsk-release-current label to this section. Keep only one active release-note snippet include in the documentation so notes appear once.

  4. Keep completed known issues in docs/source/Support/bskKnownIssues/2.X.rst under their literal version and date. Create the next series page if needed and add it at the top of the bskKnownIssues.rst index. Add a new Version |release| section containing .. include:: ../bskKnownIssuesSnippets/_compiled_latest.rst. Move the bsk-known-issues-current label to this section, keeping exactly one active known-issue include.

  5. Open a PR from the beta branch to develop and wait for CI to pass before merging.

  6. After merging, manually run the Nightly Wheels workflow on develop using workflow_dispatch. Verify that the nightly package index on GitHub Pages contains the new beta version.

Patch Release

Use this workflow for 2.X.Y after v2.X.0 has been published. Only the latest 2.X.Y line is maintained on patch/v2_X_x; current development continues independently on develop.

Prepare

  1. For the first patch in the release line, create patch/v2_X_x from the v2.X.0 tag. For later patches, use the existing patch branch based on the latest v2.X.Y release.

  2. Cherry-pick the approved fixes from develop. Keep each cherry-pick focused and retain the original commit reference.

  3. Finalize the release notes and known issues for 2.X.Y.

  4. If a release candidate is required, follow Validate a Release Candidate on the patch branch.

  5. Set and verify the final version as 2.X.Y.

Validate

  1. Run clean local validation.

  2. Push patch/v2_X_x to origin.

  3. Manually run the Pull Request workflow on patch/v2_X_x and wait for all jobs to pass.

Publish

  1. Create and push the final tag v2.X.Y from patch/v2_X_x.

  2. Wait for the Publish Wheels workflow to finish and verify the published artifacts.

  3. Deploy the patch documentation.

  4. Create the GitHub Release.

Close Out

  1. Confirm that every patch fix also exists on develop. If a fix originated on the patch branch, forward-port it.

  2. Keep patch/v2_X_x available for subsequent patches in the same release line.

Common Release Tasks

Set and Verify the Version

The package version is stored in docs/source/bskVersion.txt and read by pyproject.toml during packaging. Update it manually and use PEP 440 syntax:

Version and tag examples

Build type

Package version

Git tag

Beta

2.X.0bN

No release tag

Release candidate

2.X.YrcN

v2.X.YrcN

Final

2.X.Y

v2.X.Y

Before tagging, confirm that the version file, intended tag, and checked-out commit all describe the same release. Commit every version change before creating its tag.

Finalize the Release Notes and Known Issues

Normal PRs contribute release-note snippets under docs/source/Support/bskReleaseNotesSnippets and known-issue snippets under docs/source/Support/bskKnownIssuesSnippets. Follow each folder’s README for when entries are required and how to format them. Maintainers gather, review, and place finalized content in the appropriate version-series RST files under bskReleaseNotes/ and bskKnownIssues/. Both collections use the same compiler; it does not assign entries to releases or delete snippets.

Known issues cover issues affecting tagged releases. An issue introduced and fixed by a commit within the same beta cycle does not need a known-issue entry if it never affected a tagged release. An issue discovered during beta development that also affects a tagged release still needs an entry. Document unresolved issues that will ship in the upcoming tagged release before tagging. Release-note requirements apply separately.

At release time:

  1. Compile the current snippets:

    make -C docs snippets
    
  2. Collect and edit the notes for the release. Put them in docs/source/Support/bskReleaseNotes/2.X.rst under a literal version and release date, newest first. For example, 2.12.1 belongs above 2.12.0 in 2.12.rst; 2.13.0 belongs in 2.13.rst. Create a series page and add it to the index when preparing the first release in that series.

  3. Before tagging, sort longer release-note and known-issue lists into topic subsections within the dated release section. Use the topics below in the same order, omitting empty categories. Small patch releases can remain simple bullet lists.

    • Compatibility and migration

    • Build, installation, and CI

    • Simulation framework and module development

    • Spacecraft dynamics and effectors

    • Environment, gravity, and ephemerides

    • Sensors and flight software

    • MuJoCo and stochastic integration

    • Visualization and data handling

    • Documentation, examples, and validation

    Use RST subsection headings underlined with ~ characters, as in the 2.12.0 and 2.11.0 release notes and known issues. If a topic is still long, add more specific subheadings underlined with ^, as in the 2.12.0 known issues for spacecraft dynamics. Place each entry once under its primary topic, keeping feature-specific examples, documentation, and tests with the feature. Put changes requiring users to adapt their code or setup under Compatibility and migration. Edit for clarity and combine related entries where appropriate, preserving migration instructions, RST references, issue numbers, and beta markers. Sorting and editing are maintainer tasks; PR snippets remain individual bullet entries.

  4. When finalizing the active development version, replace its _compiled_latest.rst include with the finalized bullet content. Leave the include present but commented if useful for the next development cycle. Retain existing section labels and anchors when finalizing a heading so bookmarks continue to work.

  5. In bskKnownIssues/2.X.rst, replace the active known-issue include with its reviewed content under a literal version and release date, newest first. Create a series page and add it to the bskKnownIssues.rst index if needed. Add a permanent label such as bsk-known-issues-2-13-0 to the finalized section. Retain existing version labels and heading anchors so bookmarks continue to work. Keep unresolved limitations and workarounds documented; archiving an entry does not imply it was resolved.

  6. Review the notes for duplicate, internal-only, unclear, or contradictory entries and verify that every RST reference resolves. Reconcile multiple pending descriptions of the same issue or workaround before archiving. Remove provisional entries for issues introduced and fixed entirely within the beta cycle if no tagged release was affected.

  7. After saving the reviewed content, delete only the consumed snippet files from each collection. Preserve each README.md, the compiler wrapper, samples, and other underscore-prefixed support files.

For a patch release, create dated 2.X.Y sections for the selected patch notes in bskReleaseNotes/2.X.rst and for the known issues in bskKnownIssues/2.X.rst, without disturbing newer develop release content.

On the maintenance branch, move bsk-known-issues-current to the newly finalized known-issue section and bsk-release-current to the new release-note section. Keep each current label in exactly one location and preserve permanent version labels on the older sections. This makes the legacy #version-release bookmarks open the latest patch. When forwarding patch history to develop, leave its current labels on the active beta sections.

Consume only snippets for the selected patch fixes; do not clear either collection wholesale when it also contains entries for newer work.

Full documentation builds reject nonempty snippet collections with no active include. After finalization, empty collections may have no include. Restore the active includes when starting the next development cycle, before publishing new snippets. Standalone compilation remains available while preparing a release, and single-page previews are exempt from this full-build check.

Each series page starts with a title followed by its release sections. Use this structure when adding a new series, replacing 2.X with its version series:

Version 2.X Release Notes
========================

.. _bsk-release-current:

Version |release|
-----------------

.. include:: ../bskReleaseNotesSnippets/_compiled_latest.rst

Use the matching structure for a known-issue series page:

Version 2.X Known Issues
=======================

.. _bsk-known-issues-current:

Version |release|
-----------------

.. include:: ../bskKnownIssuesSnippets/_compiled_latest.rst

Move each collection’s current-version label and active include when advancing to a new series. For another development patch in the same series, add the active section above the finalized releases in the same file. Keep Version 1.x and earlier as the last archive link in each index.

Run Clean Local Validation

Run the validation from the release branch or patch branch being tagged:

python conanfile.py --clean --opNav True --mujoco True
python run_all_test.py
make -C docs clean
make -C docs html SPHINXOPTS="-W --keep-going"

The build, test suite, and documentation build must complete without errors or warnings. See docs/source/Support/User/FAQ.rst for clean-build details and docs/source/Support/Developer/createHtmlDocumentation.rst for documentation prerequisites.

Validate a Release Candidate

Use a release candidate when the wheel pipeline or release payload should be tested through TestPyPI before production publication:

  1. Set bskVersion.txt to 2.X.YrcN and commit the change on the branch being validated.

  2. Run clean local validation and the appropriate GitHub Actions validation workflow.

  3. Tag the tested commit v2.X.YrcN and push the tag. Publish Wheels routes the artifacts to TestPyPI.

  4. Install and validate the TestPyPI artifacts. If changes are required, increment N and repeat with a new commit and tag.

  5. After the candidate passes, set bskVersion.txt to 2.X.Y, commit the final-version change, and repeat local and CI validation before creating the final tag.

Do not move or reuse a release-candidate tag after it has been pushed.

Create and Push a Release Tag

Create the tag on the exact validated commit: master for a major release or patch/v2_X_x for a patch release. Push only after confirming the final version and commit.

git status --short
git tag v2.X.Y
git push origin v2.X.Y

Tag pushes are publication triggers. Treat pushed tags as immutable; if a published version is wrong, correct the problem with a new version rather than moving or reusing the tag.

The Publish Wheels workflow builds all supported wheels and the source distribution. Do not continue until every job succeeds and the expected version is available from PyPI or TestPyPI.

Deploy Patch Documentation

Patch tags do not automatically deploy documentation because the patch branch is neither master nor develop. After publishing a patch:

  1. On the Basilisk Actions page, manually run Merge to master or develop using patch/v2_X_x. This deploys the patch documentation at the site root.

  2. The root deployment replaces the GitHub Pages contents. Run Merge to master or develop again using develop to restore the developer documentation under /develop.

  3. Verify both the root release documentation and the /develop documentation after the workflows finish.

Recover Failed Source-Distribution Validation

If all wheel build and packaging jobs succeeded but Test SDist failed because of an external dependency download, fix the validation environment on the release branch and keep the published tag unchanged. The Publish Wheels workflow has an optional recovery_run_id input for this case:

gh workflow run publish-wheels.yml --ref patch/v2_X_x \
  -f destination=pypi -f recovery_run_id=ORIGINAL_RUN_ID

Run this only after reviewing the original failure and the environment fix. The workflow verifies that the original run used the same final tag and commit, that all wheel checks succeeded, and that publication was skipped. It downloads the original, unexpired artifacts, verifies their package versions and platform pairs, and installs and imports the original source distribution with Conan retries and source backups configured. Publication runs only after these checks pass.

This recovery uses the original distributions without rebuilding or modifying them. It cannot repair a source-code defect in the tagged archive or recover a partially published release. A rerun of the original workflow still uses its old workflow definition; dispatch recovery from the branch containing the fix.

Create the GitHub Release

After package publication succeeds:

  1. Open the repository’s Releases page and select Draft a new release.

  2. Select the published v2.X.Y tag, regardless of which branch contains it.

  3. Set the title to Basilisk v2.X.Y.

  4. Add the release notes manually or use GitHub’s generated notes as a starting point. Remove unresolved RST-only markup such as :ref: roles.

  5. Publish the GitHub Release.

Forward-Port Patch Fixes

Never implement the same fix independently on both the patch branch and develop. Develop it once, then cherry-pick that commit to the other branch. Do not merge develop wholesale into patch/v2_X_x; maintenance branches must remain limited to approved fixes for their release line.

Release Safety Rules

  • Do not create a tag from an uncommitted or unvalidated version change.

  • Do not move or reuse a pushed release tag.

  • Do not merge develop wholesale into a maintenance branch.

  • Keep patch cherry-picks small, focused, and traceable to their original commits.

  • Verify package and documentation publication before announcing a release.