Mir release protocol

Hi all,

I wanted to discuss our plan wrt Mir releases, now that we’ve moved to GitHub and have more control of our CI system.

NB: this is work in progress, so expect changes.

Goals

I’d like our release process to be non-intrusive and automated as much as possible.

Artefacts

There’s a handful of things that need to be available after a Mir release:

Nice to haves

Some additional things that we could do:

  • Fedora packages in the Mir COPR and/or Fedora archives

Code

We’re hosting our code on GitHub now, and using Travis for CI. Ideally, a release tagged on master would result in all the artefacts mentioned above being available automatically after a while.

Our master branch should see all the incoming code, and should receive the releases merged back when done. A release in process should not prevent code landing on the master branch.

So I propose a the process as follows:

  1. we branch a release candidate into release/$MAJOR.$MINOR
    git checkout -b release/0.29 master
    1.1. Update the version [CMakeLists.txt]
    1.2. Update the changelog [debian/changelog]
  2. we push to MirServer/mir and create a Pull Request for the release branch
    git push --set-upstream origin release/0.29
  3. CI picks this up and does everything in its power to prepare and test staging artefacts (Mir Team RC PPA, snap store candidate channel)
  4. we cherry-pick fixes from master, or commit directly to release/0.29
  5. see 2.
  6. when happy (see: the test plan), we tag the version and push
    git commit --message "0.29 Release"
    git tag --sign v0.29.0 release/0.29
    git push origin v0.29.0
  7. see 2
  8. when the Pull Request is approved, see 2., but this time things are published to the stable channel and copied to the release PPA, and to Ubuntu as well.

Builders

I’d like to use Launchpad infrastructure as much as possible for Ubuntu packages and snaps, see [1] however.

Open questions

[1] It takes longer for a PPA to build across all architectures than Travis allows us to run jobs for. This means that we might need to split build and autotest/publish steps between the CI and merge stages. So extensive testing and publication to stable would actually happen on merging of the release/0.29 branch to master. That follows, however, what we plan to do with non-release merges into master, so maybe that’s fine?

If there’s anything I’m missing, please reply!

Tips

git config --global push.followTags true will make --follow-tags the default.

One thing that jumps out is the repeated debchange dance, which could possibly be automated, if we said git tags are the authoritative place for our version numbers. One problem with that is that information “disappears” in tarballs, other than the tarball name. So we can’t have, say, CMakeLists.txt depend on git describe. But maybe, when building a tarball, we can encode the version from git into debian/changelog and CMakeLists.txt automatically.

Another option I thought of would be to avoid tags for release candidates, and have the CI system manage that itself, based on the release/* branch name being merged. We can verify this comes from the MirServer/mir repo, so this should be perfectly safe. We could then add the ~rc* suffix automatically, until we encountered a v0.29 tag, at which point we’d build final packages and copy them into the release PPA and the stable snap channels.

I like the ideas of the CI system managing the "debchange dance", because I think it is an artefact of using debian-based builders, not part of the underlying process of making a Mir release.

That is it fits with the model:

  1. Branch a release candidate
  2. Builders “do stuff”
  3. test
  4. If needs fixing; then fix; goto 2; fi
  5. Approve release candidate
  6. Builders “do stuff”

If we add Fedora, snapcraft, etc builders that central process should remain unchanged.

I’ve now modified the plan to that effect, and filed a Pull request for release/0.29. Will report how it goes.

Mir v0.29.0 packages for Ubuntu are now published in the release PPA. The process above has some teething trouble, but seems to work overall.

We’ve hit some snags with runaway version numbers, but most of that was because of rewriting the history, which we shouldn’t do anyway.

The most recent concern is that which regards when do we actually publish the release. My thinking was that tagging is too early, because that’s the time when we build the final packages, so some testing of those is in order still.

The next available “event” was when the release/* branch gets merged into master, and that’s what I thought would be a good time to consider the release. At that time master has everything the release is, along with the release tag, so it felt like the right time. @alan_g correctly pointed out, however, that this might mean delays unrelated to the release itself. So the jury’s still out on when this happens.

Another thing that we didn’t consider were conflicts when merging release/* into master. To resolve them, we have to do a merge on top of the release branch (because there’s no way to resolve conflicts when merging to master when using bors), but those would not be part of the release, or even potentially the series. Pushing that to release/* would end up starting the next patch release candidate. In that case we need a separate PR into master, and bors realizes the release/* branch got merged as well.

Unfortunately that means that the release tag is not a parent of the merge, and that’s what our scripts are looking at to determine whether this is a release merge. We’ll need to look through the git merge-base to find release tags, if we continue with merging being the release trigger.

I’m not sure if you’ve read this already, but Rust’s release process seems relevant:

https://forge.rust-lang.org/release-process.html

Basically, the release artifacts (source tarballs, RPMs, MSIs, etc) are produced by pushing to a blessed branch called “stable,” and are uploaded to a folder called dev. The release is only actually considered Official a couple days after that, when the release artifacts are copied from dev to prod, Git tags are created, blogposts are made, etc. The release candidates (called “beta”, but the actual role in the release process seems the same) are done the same way, except the branch is different.

What’s nice about this way is that, since the Git tag is only created after a human has verified that the release artifacts were built correctly, you can have it do this:

  • release artifacts are built when the stable branch is pushed to, but are not published
  • the release is actually published when the v0.x tag is created

We’ve had some further thoughts about this process.

  1. We re-affirm that git should be the primary source of version information
    1.1. Currently version information in CMakeLists.txt is used for generating headers.
    1.2.The release tarball is detached from git but needs version information (c.f. 1.1).
    1.3. Therefore, version information needs to be automatically incorporated into the release tarball.
  2. We are using multiple distribution formats
    2.1 Therefore, we should to separate changelog information from the debian/changelog file.
    2.1.1. Some of this should be automatically generated from the merge commits; but,
    2.1.2. We will still need to manually document ABI changes.