# How to cut a Toga release

The release infrastructure for Toga is semi-automated, using GitHub Actions to formally publish releases.

This guide assumes that you have an `upstream` remote configured on your local clone of the Toga repository, pointing at the official repository. If all you have is a checkout of a personal fork of the Toga repository, you can configure that checkout by running:

```console
$ git remote add upstream https://github.com/beeware/toga.git
```

The procedure for cutting a new release is as follows:

1. Check the contents of the upstream repository's main branch:

      ```console
      $ git fetch upstream
      $ git checkout --detach upstream/main
      ```

      Check that the HEAD of release now matches upstream/main.

2. Ensure that the release notes are up to date. Run:

      ```console
      $ tox -e towncrier -- --draft
      ```

      to review the release notes that will be included, and then:

      ```console
      $ tox -e towncrier
      ```

      to generate the updated release notes.

3. Build the documentation to ensure that the new release notes don't include any spelling errors or markup problems:

      ```console
      $ tox -e docs-lint,docs
      ```

4. Tag the release, and push the branch and tag upstream:

      ```console
      $ git tag v1.2.3
      $ git push upstream HEAD:main
      $ git push upstream v1.2.3
      ```

5. Pushing the tag will start a workflow to create a draft release on GitHub. You can [follow the progress of the workflow on GitHub](https://github.com/beeware/toga/actions?query=workflow%3A%22Create+Release%22); once the workflow completes, there should be a new [draft release](https://github.com/beeware/toga/releases), and entries on the TestPyPI server for [toga-core](https://test.pypi.org/project/toga-core/), [toga-cocoa](https://test.pypi.org/project/toga-cocoa/), etc. Confirm that this action successfully completes. If it fails,  there's a couple of possible causes:

      a. The final upload to TestPyPI failed. TestPyPI doesn't have the same service monitoring as PyPI-proper, so it sometimes has problems. However, it's not critical to the release process.

      b. Something else fails in the build process. If the problem can be fixed without a code change to the Toga repository (e.g., a transient problem with build machines not being available), you can re-run the action that failed through the GitHub Actions GUI. If the fix requires a code change, delete the old tag, make the code change, and re-tag the release.

6. Create a clean virtual environment, install the new release from Test PyPI, and perform any pre-release testing that may be appropriate:

      ```console
      $ python3 -m venv testvenv
      $ . ./testvenv/bin/activate (testvenv)
      $ pip install --extra-index-url https://test.pypi.org/simple/ toga==1.2.3 (testvenv)
      $ toga-demo (testvenv) $ #... any other manual checks you want to perform ...
      ```

7. Log into Read the Docs, visit the [Versions tab](https://readthedocs.org/projects/toga/versions/), and activate the new version. Ensure that the build completes; if there's a problem, you may need to correct the build configuration, roll back and re-tag the release.

8. Edit the GitHub release to add release notes. You can use the text generated by Towncrier. If necessary, check the pre-release checkbox.

9. Double check everything, then click Publish. This will trigger a [publication workflow on GitHub](https://github.com/beeware/toga/actions?query=workflow%3A%22Upload+Python+Package%22).

10. Wait for the packages to appear on PyPI ([toga-core](https://pypi.org/project/toga-core/), [toga-cocoa](https://pypi.org/project/toga-cocoa/), etc.).

Congratulations, you've just published a release!

Once the release has successfully appeared on PyPI or TestPyPI, it cannot be changed. If you spot a problem after that point, you'll need to restart with a new version number.
