****************************
Package Release Instructions
****************************

This document outlines the steps for releasing a versioned Jdaviz package to
PyPI. Currently, these do not cover submitting package updates to other
distribution outlets, such as ``astroconda`` or ``conda-forge``.

This process currently requires you (the release manager) to have sufficient GitHub
permissions to tag, push, and create a GitHub release on Jdaviz repository.

It is recommended that you lock the ``main`` branch after the "feature freeze"
for the release and only unlock it when release is out on PyPI. Any urgent
pull request that needs to go in after the freeze needs your blessing.
A lock can be as simple as bumping the "reviews required" protection rule
for the ``main`` branch to a very high number; Any rule that will prevent
co-maintainers from merging pull requests without your blessing would do.

If you deem it necessary, you may choose to release a Release Candidate (RC)
first before the actual release. In that case, instead of "vX.Y.Z", it would
be "vX.YrcN" (also see `PEP 440 <https://www.python.org/dev/peps/pep-0440/>`_).

.. note::
    These instructions are adapted from the Astropy package template releasing
    instructions. Replace "vX.Y.Z" with the actual version tag of the release you
    are about to make.

Choose your adventure:

* :ref:`release-long`
* :ref:`release-short`


.. _release-long:

The long way
============

This way is recommended if you are new to the process or wish to manually run
some automated steps locally. It takes longer but has a smaller risk factor.
It also gives you a chance to test things out on a machine that is different
from the one used for deployment on GitHub Actions.

It is recommended for you to have a clean checkout of the Jdaviz repository
(not the fork), especially if you also do a lot of development work.
You can create a clean checkout as follows (requires
`SSH setup <https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh>`_)::

    mkdir jdaviz_for_release
    cd jdaviz_for_release
    git clone git@github.com:spacetelescope/jdaviz.git .
    git fetch origin --tags

#. Ensure `CI on Actions for main <https://github.com/spacetelescope/jdaviz/actions/workflows/ci_workflows.yml?query=branch%3Amain>`_
   and `RTD build for latest <https://readthedocs.org/projects/jdaviz/builds/>`_
   are passing.

#. Update the ``CHANGES.rst`` file to make sure that all the user-facing changes are listed,
   and update the release date from ``unreleased`` to current date in the ``yyyy-mm-dd`` format.
   Remove any empty subsections. Do not forget to commit your changes::

     git add CHANGES.rst
     git commit -m "Preparing release vX.Y.Z"

#. Remove any untracked files. (WARNING: This will
   permanently remove any files that have not been previously committed, so
   make sure that you don't need to keep any of these files.)
   This step is not needed if you have a fresh code checkout, but does not hurt either::

     git clean -xdf

#. Tag the version you are about to release and sign it (optional but it is a good practice).
   Signing requires
   `GPG setup <https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/adding-a-new-gpg-key-to-your-github-account>`_::

     git tag -s "vX.Y.Z" -m "Tagging version vX.Y.Z"

#. Generate the package distribution files by first making sure the
   following packages are installed and up-to-date::

     pip install build twine -U

#. Creating the source distribution and its wheel with::

     python -m build --sdist --wheel .

#. Do a preliminary check of the generated files::

     python -m twine check --strict dist/*

#. Fix any errors or warnings reported. Skip this step if not applicable.

#. Run unit tests using package you are about to release. It is recommended that you
   do this in a fresh Python environment. The following example uses ``conda``,
   so if you use a non-``conda`` Python environment manager, replace the ``conda``
   commands accordingly::

     conda create -n testenv python=3.9
     conda activate testenv
     pip install pytest pytest-astropy pytest-tornasync dist/*.whl
     cd ..
     python -c "import jdaviz; jdaviz.test(remote_data=True)"
     cd jdaviz_for_release

#. Fix any test failures. Skip this step if not applicable.

#. Depending on the severity of the fixes above, you might need to submit the
   fixes as separate PRs and abandon the release. If that is the case, stop here,
   delete the ``vX.Y.Z`` tag, and start again from above when those fixes are in
   the ``main`` branch. If there are no fixes (yay) or if you can justify pushing
   the fixes as part of this release (not recommended), continue on.

#. Remove files generated by above steps::

     git clean -xdf

#. Make sure code checkout state is clean and history is correct. If not, fix accordingly::

     git status
     git log

#. The release is basically done locally, but now you have to set it up for the
   *next* release cycle. Add a new section to the top of ``CHANGES.rst`` as follows,
   replacing ``A.B`` with the next non-bugfix version::

     A.B (unreleased)
     ================

     New Features
     ------------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     API Changes
     -----------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     Bug Fixes
     ---------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     Other Changes and Additions
     ---------------------------

#. Commit your changes of the, uh, change log::

     git add CHANGES.rst
     git commit -m "Back to development: A.B.dev"

#. Push out the updated code and tag. If applicable, change ``origin`` to point to
   the remote that points to the repository being released::

     git push origin main
     git push origin vX.Y.Z

#. Go to `Releases on GitHub <https://github.com/spacetelescope/jdaviz/releases>`_
   and `create a new GitHub release <https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository>`_
   off the new ``vX.Y.Z`` tag.

#. Check `Release on Actions <https://github.com/spacetelescope/jdaviz/actions/workflows/publish.yml>`_
   to make sure that the new GitHub release triggered PyPI upload successfully.
   Also check that `files on PyPI <https://pypi.org/project/jdaviz/#files>`_ contain
   both the source tarball and the wheel for that release.

#. Check `RTD builds <https://readthedocs.org/projects/jdaviz/builds/>`_ to make sure
   that documentation built successfully for both ``latest`` and the new ``vX.Y.Z`` tag.

#. Check `Zenodo page for Jdaviz <https://zenodo.org/badge/latestdoi/185452341>`_.
   It should have picked up the GitHub Release automatically.

#. Follow procedures for :ref:`release-milestones`.

Congratulations, you have just released a new version of Jdaviz!


.. _release-short:

The short way
=============

This way is for when you are in a rush, is very familiar with the process already,
and is deploying on a proven automated process. It is faster but also has a higher
risk factor. If you choose this way wrongly, you will end up doing hotfix releases
anyway, which will not save you any time in the end. Only go this way if you know
what you are doing.

You can do a release from your fork directly without a clean code check-out.

#. Ensure `CI on Actions for main <https://github.com/spacetelescope/jdaviz/actions/workflows/ci_workflows.yml?query=branch%3Amain>`_
   and `RTD build for latest <https://readthedocs.org/projects/jdaviz/builds/>`_
   are passing.

#. Create a new branch on your fork and make sure you have updated tags too::

     git fetch upstream main
     git fetch upstream --tags
     git checkout upstream/main -b release-vX.Y.Z

#. Update the ``CHANGES.rst`` file to make sure that all the user-facing changes are listed,
   and update the release date from ``unreleased`` to current date in the ``yyyy-mm-dd`` format.
   Remove any empty subsections. Do not forget to commit your changes::

     git add CHANGES.rst
     git commit -m "Preparing release vX.Y.Z"

#. Push the ``release-vX.Y.Z`` branch out and create a new pull request with it.
   Make sure the CI passes, then merge. If review is required for merge to happen,
   ask for a review, though you can override that requirement if you have admin access.

#. If any of the CI fails, especially the job that says "Release", abandon this way.
   Stop here; do not continue! Otherwise, go to the next step.

#. Go to `Releases on GitHub <https://github.com/spacetelescope/jdaviz/releases>`_
   and `create a new GitHub release <https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository>`_
   by giving it a new ``vX.Y.Z`` tag (do not choose any existing tags).

#. Check `Release on Actions <https://github.com/spacetelescope/jdaviz/actions/workflows/publish.yml>`_
   to make sure that the new GitHub release triggered PyPI upload successfully.
   Also check that `files on PyPI <https://pypi.org/project/jdaviz/#files>`_ contain
   both the source tarball and the wheel for that release.

#. Check `RTD builds <https://readthedocs.org/projects/jdaviz/builds/>`_ to make sure
   that documentation built successfully for both ``latest`` and the new ``vX.Y.Z`` tag.

#. Check `Zenodo page for Jdaviz <https://zenodo.org/badge/latestdoi/185452341>`_.
   It should have picked up the GitHub Release automatically.

#. The release is basically done, but now you have to set it up for the
   *next* release cycle. Update ``CHANGES.rst`` directly in the ``main`` branch
   using your admin power. If you do not have sufficient access to do that,
   you will have to update it via a pull request from your fork.
   Add a new section to the top of ``CHANGES.rst`` as follows, replacing ``A.B``
   with the next non-bugfix version::

     A.B (unreleased)
     ================

     New Features
     ------------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     API Changes
     -----------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     Bug Fixes
     ---------

     Cubeviz
     ^^^^^^^

     Imviz
     ^^^^^

     Mosviz
     ^^^^^^

     Specviz
     ^^^^^^^

     Other Changes and Additions
     ---------------------------

#. Commit your changes of the, uh, change log with a message, "Back to development: A.B.dev"

#. Follow procedures for :ref:`release-milestones`.

#. For your own sanity unrelated to the release, grab the new tag for your fork::

     git fetch upstream --tags

Congratulations, you have just released a new version of Jdaviz!

.. _release-milestones:

Milestones bookkeeping
======================

#. Go to `Milestones <https://github.com/spacetelescope/jdaviz/milestones>`_.

#. Create a new milestone for the next release.

#. For the milestone of this release, if there are any open issues or pull requests
   still milestoned to it, move their milestones to the next release.

#. Make sure the milestone of this release ends up with "0 open" and then close it.

#. Remind the other devs of the open pull requests with milestone moved that they
   will need to move their change log entries to the new release section that you
   have created in ``CHANGES.rst`` during the release process.
