# A guide to making a DIPY release

A guide for developers who are doing a DIPY release

## Automated release preparation

Most of the manual steps below are automated by the `spin prepare-release` command. Run it from the root of the DIPY repository:

    spin prepare-release

The command walks you through each step interactively. If it is interrupted you can resume from any step with `--from-step N`:

    spin prepare-release --from-step 6

You can also override the auto-detected previous tag or skip the version prompt:

    spin prepare-release --last-tag 1.11.0 --new-version 1.12.0

Available steps (`--from-step` values):

     1. fetch-tag        – detect the previous release tag
     2. mailmap          – auto-detect duplicate authors, propose .mailmap entries, show full shortlog
     3. version          – choose the new version number
     4. author           – regenerate the AUTHOR file
     5. copyright        – update copyright years in LICENSE and doc/conf.py
     6. release-notes    – generate doc/release_notes/releaseX.Y.Z.rst
     7. changelog        – prepend entry in Changelog
     8. api-changes      – review and update doc/api_changes.rst
     9. index            – add announcement line to doc/index.rst
    10. old-news         – rotate oldest announcements from index.rst → doc/old_news.rst
    11. highlights       – move previous highlights from index.rst → doc/old_highlights.rst
    12. stateoftheart    – add new release to doc/stateoftheart.rst toctree
    13. toolchain        – add new version row to doc/devel/toolchain.rst
    14. version-switcher – promote new version to stable in doc/_static/version_switcher.json
    15. developers       – review and update doc/developers.rst contributor list
    16. pyproject        – set version in pyproject.toml
    17. deprecations     – confirm deprecated code has been removed
    18. doctest          – run Cython / extension module doctests
    19. tests            – run the full test suite
    20. docs             – build HTML documentation (without examples)
    21. tutorials        – build and review individual tutorials with ``spin docs <name>``
    22. website          – deploy docs to docs.dipy.org and verify version switcher

Before running the script, make sure to:

- Review the open list of dipy issues. Close or label outstanding issues, and check whether any should delay the release.

- Verify that no builds are failing on DIPY Github Actions. The `PRE` build is allowed to fail for PR merges but must not fail at release time.

- Check the `README` in the root directory and verify all links are still valid.

### Notes on individual steps

Step 2 – mailmap

  The script parses `git log` to detect duplicate authors automatically (same email / different name, or same normalised name / different email). Each new candidate entry is shown and you are asked `yes / no / edit`. Accepted entries are appended to `.mailmap` and a diff is shown. A full `git shortlog -nse <last_tag>..HEAD` is printed afterwards for a final manual review before you continue.

Step 6 – release-notes

  Release notes are generated with `tools/github_stats.py`:

      python3 tools/github_stats.py <last_tag> > doc/release_notes/release<version>.rst

  You will be paused to add a header and highlights section above the auto-generated contributor/PR/issue lists before continuing.

Step 7 – changelog

  A skeleton entry is prepended to `Changelog`. You are paused to fill in the highlights (derived from the release notes) before continuing.

Step 11 – doctest

  Runs `./tools/doctest_extmods.py dipy`. No output means all doctests passed; the exit code is always printed so you can tell the command actually ran. Requires the package to be built in-place (`spin build` or `pip install --no-build-isolation -e .`).

Step 12 – tests

  Runs `pytest -svv --doctest-modules dipy` from the repo root.

Step 13 – docs

  Runs `make clean && make html` inside `doc/`. Review the generated output for broken tutorials, figures, or API pages before confirming.

  During development you can use `spin docs` for faster, selective builds:

      spin docs                      # full build with examples
      spin docs --no-plot            # skip example execution
      spin docs reconst_csa          # build only one tutorial
      spin docs reconst_csa --no-plot  # RST only, no execution

  Tutorial names are matched as regex substrings against the example file path; multiple names are joined with `|` (union).

## Release checklist (manual reference)

The steps below are the manual equivalent of what `spin prepare-release` does, kept here for reference.

- Detect the previous tag:

      git tag | sort -V | tail -1

- Review contributors and update `.mailmap`:

      git shortlog -nse <last_tag>..HEAD

- Generate release notes:

      python3 tools/github_stats.py <last_tag> > doc/release_notes/release<version>.rst

  Edit the file to add a header and highlights section.

- Prepend an entry to `Changelog` with the new version and highlights.

- Add the new announcement line to `doc/index.rst`.

- Regenerate the `AUTHOR` file from git history:

      git log --format=’%aN’ | sort -u > AUTHOR

- Check copyright years in `LICENSE` and `doc/conf.py`.

- Set the version in `pyproject.toml`.

- Confirm all deprecated functions past their removal cycle have been removed.

- Run Cython / extension module doctests:

      ./tools/doctest_extmods.py dipy

- Run the full test suite:

      pytest -svv --doctest-modules dipy

- Build the HTML documentation:

      cd doc && make clean && make html && cd ..

- Build and test the DIPY wheels via DIPY Github Actions. Wheels are built automatically on CI when a release tag is pushed.

## Doing the release

Once `spin prepare-release` completes successfully:

1. Stage and commit all changes:

       git commit -m "REL: set version to <version>"

2. Open a Pull Request, get it reviewed and merged.

3. After the merge, create an annotated tag on the merge commit:

       git tag -am ‘Public release <version>’ <version>

4. Build the source distribution:

       git clean -dfx
       python -m build

5. Upload to PyPI:

       pip install twine
       twine upload dist/*

6. Push the tag to trigger wheel builds on CI:

       git push upstream <version>

7. Create a maintenance branch and bump the development version:

       git checkout -b maint/<version>
       # set version to <major>.<minor+1>.0.dev0 in pyproject.toml on master
       git checkout master
       git merge -s ours maint/<version>

8. Announce to the mailing lists.

## Other stuff that needs doing for the release

- Build and upload the HTML docs to the GitHub Pages website:

      make upload

- Announce to the mailing lists.