Release Process
===============

1.  Set the new version number
------------------------------

See gitubuntu/version.py for the current version number.

  $ export LAST_RELEASE=$(cat gitubuntu/version.py | cut -d\' -f2)
  $ echo "${LAST_RELEASE}"

Git Ubuntu's version numbers follow the common MAJOR.MINOR.PATCH and
MAJOR.MINOR.PATCH-rcN patterns, where for this project these are
interpreted as follows:

  - MAJOR is updated for API breaking changes such as alterations in
    importer hash ABI stability.  As a special rule, MAJOR=0 indicates
    no stability guarantees.  Notably, changes in MAJOR version are not
    guaranteed to be forward or backward compatible with earlier MAJOR
    versions.

  - MINOR is incremented for feature-level changes that may alter how
    the git ubuntu frontends behave, including breaking changes in how
    git ubuntu subcommands and their parameters work.  The importer API,
    however, is intended to be backward compatible from one MINOR
    version to the next, with no breaking changes.

  - PATCH is incremented for bug fixes and routine feature additions
    that introduce no compatibility issues for either the backend
    importer or the frontend client.  In particular, new commands and
    parameters may be introduced, but existing ones will not be changed
    or removed.

  - rcN indicates a release candidate, using a sequential numbering for
    'N'.

Define the new version for the release:

  $ export VERSION="<MAJOR>.<MINOR>.<PATCH>"

Or, for a release candidate:

  $ export VERSION="<MAJOR>.<MINOR>.<PATCH>-rcN"

Set it in the git repo:

  $ echo "VERSION = '${VERSION}'" > gitubuntu/version.py
  $ git commit gitubuntu/version.py  -m "version: bump to ${VERSION}"
  $ git tag --annotate -m "${VERSION} Release" ${VERSION}

The annotated tag is necessary, because the snap build mechanisms
determine the version to set in the snap based on it.


2.  Draft release announcement
------------------------------

The release announcement generally summarizes the major changes in the
release, and (where possible) identifies the bug fixes included in it.
Some examples of past release announcements:

  - 0.2.1: https://lists.ubuntu.com/archives/ubuntu-server/2017-September/007594.html
  - 0.3.0: https://lists.ubuntu.com/archives/ubuntu-server/2017-October/007598.html
  - 0.4.0: https://lists.ubuntu.com/archives/ubuntu-server/2017-October/007605.html
  - 0.7.1: https://lists.ubuntu.com/archives/ubuntu-server/2018-March/007667.html

The git log can be referred to for changes worth mentioning:

  $ git log --stat ${LAST_RELEASE}..

If desired, a shortlog can be appended to the release announcement, to
itemize all changes:

  $  git shortlog ${LAST_RELEASE}...


3.  Testing
-----------

First check there are no unexpected test failures in trunk:

  $ python3 ./setup.py check
  $ python3 ./setup.py build
  $ pytest-3 .

Next, run the self-test against your locally installed snap environment:

  $ ./snap-wrappers/wrappers/git-ubuntu-self-test

Note that if your installed snap version is particularly old, or if the
new changes are particularly extensive or involve changes to the snap
build process itself, you may want to run a full snap build.  See
README.testing for details on how to do this.

Optionally, the full test suite can be directly executed, although since
it has some rather exacting dependencies, it may not be able to build
properly.

  $ python3 ./setup.py test

Next, push a copy of the branch up to launchpad under your own namespace
for Continuous Integration (CI) testing:

  $ git push ${LP_USERNAME} ${VERSION}-release

Go to the Launchpad page for the branch and create a merge proposal
targeted to lp:git-ubuntu, set 'main' as the Target branch and set
the Description to say "For CI build only".  Review type can be set to
'ci'.  This will ensure the regular CI runs on it, which exercises the
snap build mechanics, but let's the development team know it can be
ignored for review purposes.  This isn't the snap we'll actually be
using, but will produce one we can download and inspect.

A snap candidate (not yet uploaded to the store) can be installed
locally for testing like this:

  $ lxc exec ${CONTAINER} -- rm -vf /tmp/git-ubuntu_*-g*_amd64.snap
  $ lxc file push ./git-ubuntu_*-g*_amd64.snap ${CONTAINER}//tmp/
  $ lxc exec ${CONTAINER} -- bash
  $ sudo snap install --classic --dangerous /tmp/git-ubuntu_0+git.*_amd64.snap


4.  Release the new version
---------------------------

Once everything looks good, merge the change from your local release
branch to main:

  $ git checkout main
  $ git merge --ff-only ${VERSION}-release

Make sure everything looks ok.  The status should show no uncommitted
changes, etc.  Verify the log shows the correct tags and that HEAD
points to main, etc.  Doublecheck that git describe displays
${VERSION}:

  $ git status
  $ git log --oneline --decorate=short
  $ git describe

If all looks good, now push the annotated tag and code changes to origin:

  $ git push origin main ${VERSION}


5. Publish Snap
---------------

Channels used for delivering the snap package are defined as follows:

  - EDGE: Tracks the latest code in main to allow testing of
    potentially unstable work.  This is not recommended for general
    usage by end users.

  - BETA: Most of the time, this channel will track the same version as
    in STABLE, but also delivers release candidates and sometimes may
    provide early access to new features or bug fixes.  This channel is
    recommended particularly for advanced git-ubuntu users who wish to
    participate in testing activities.  It is also the channel used for
    the importer on the server.

  - STABLE: This channel tracks the current release used in the
    git-ubuntu service itself.  This is the recommended channel for
    all end users.

You will initially publish the package to EDGE only to verify it builds
properly.

First, trigger a rebuild of the snap in the server team's Jenkins
instance.  The git push from step #4 will get picked up by the nightly
builder, but if you don't wish to wait a day for the build, you can
manually trigger it on this page:

  https://jenkins.ubuntu.com/server/job/git-ubuntu-ci-nightly/

Make sure you're logged into Jenkins, then click "Build with parameters"
and accept the defaults.

As part of this job, the built snap will automatically be published to
the edge channel if it passes CI.

For anything but trivial releases, you should then `snap install` the
edge version of the package in a test environment to verify it.

Once you deem it good to go, use the Snapcraft website
(https://snapcraft.io/git-ubuntu/releases) to copy the snap to BETA, and
proceed with installing it in production (next step).  Solicit broader
testing, as appropriate, and then after a sufficient amount of testing
time (e.g. a week or so) copy the snap to STABLE.


6. Installation to Production
-----------------------------

See our internal process documentation for details on how to do this.


7. Announce Release
-------------------

Email the (gpg signed) announcement to:

  To: ubuntu-devel@lists.ubuntu.com
  Cc: ubuntu-distributed-devel@lists.ubuntu.com

Upload a copy of the announcement to https://launchpad.net/git-ubuntu/


8. Close bugs
-------------

Close all bugs fixed by this release. Here's an example that can be run
from `lp-shell` to close all bug tasks marked "Fix Committed". If you
use this, remember to change `VERSION` appropriately:

    VERSION = '1.0'
    tasks = list(lp.projects['git-ubuntu'].searchTasks(status='Fix Committed'))
    bugs = [lp.load(bug_link) for bug_link in set(task.bug_link for task in tasks)]
    for bug in bugs:
        bug.newMessage(
            subject=f'Fix released in git-ubuntu',
            content=f'Fix released in git-ubuntu version {VERSION}',
        )
    for task in tasks:
        task.status = 'Fix Released'
        task.lp_save()


9. Update Trello Card
---------------------

If a card hasn't been created in the daily-ubuntu-server board for the
release task already, add one at this point.  Add yourself as a member
of the card, and add labels 'git-ubuntu' and 'highlight'.  The latter
label flags it to be mentioned in the week's Ubuntu Server Developer Summary.


10. Discourse Blogging (Optional)
--------------------------------

If desired, follow up with one or more topics/posts to
discourse.ubuntu.com about the major new features included in the
release.  Discourse posts shouldn't be done just for ordinary bug
fixing, and shouldn't simply mirror the release announcement or usage
documentation.
