ga4gh / ga4gh-server

Reference implementation of the APIs defined in ga4gh-schemas. RETIRED 2018-01-24
http://ga4gh.org
Apache License 2.0
96 stars 91 forks source link

One-button release #1546

Open dcolligan opened 7 years ago

dcolligan commented 7 years ago

Manual release steps are tedious and allow room for admin error. It would be better if we had one script we could run that would push a release.

kozbo commented 7 years ago

What do you think of a script that would handle changing the constraints files during the release?

david4096 commented 7 years ago

tl;dr the current release process should be documented properly.

The constraints file currently provides incorrect directions. What we did in the last release is just delete the constraints and set the version number for our internal dependencies in the requirements.txt, I think that's better.

Being able to release directly from a tag takes out one moving part.

I'm not sure if I know how to do a one-button release, we still need to supply the target version I think. The release notes are also written and committed by hand.

Let's say I've written the release notes, the one button release assumes that you have a git client set up and authorized to make tags.

Maybe it's a script that accepts a few parameters: the repository to release, the list of internal deps to manage, the target version, and a path to a file containing the release notes.

If this process works for any single repository, it should be possible to initiate dependent releases. Say the script succeeds for schemas, then we can set a script that waits until it is downloadable from pypi and then initiates the process for the client, then server. Since we have a few python repositories now I think we can do this.

Hope this makes sense. With the travis build changes, tagging a commit is enough to trigger a release, but making sure that commit makes sense is now the job of the script. Having an automated process doesn't preclude making manual releases either.

I think we can aspire towards automating of release notes as well. Now that all commits squash/merge it should be easier to grab commit messages since the previous release tag. The script could gather the top level commit messages as a template to the release manager when writing the release notes.

Another possibility is writing something for travis that will create the git tags if some flag is placed in the PR. That way, a release notes PR could be marked for creating some tag if it is merged. That would require hiding someone's github keys in Travis, or authorizing travis to perform the action.

I think having a release script that just makes a tagged commit and then also having the twine upload available is good. We can do this next release without any more automation though, just proper documentation. You can do a release without having to go to the command line now, which is nice, but you'll still have to use github's editor to delete the constraints.

dcolligan commented 7 years ago

I agree with David's TLDR, but there seems to be two different things we are addressing here: 1) how to release an individual package 2) how to release N ga4gh packages. The later is obviously a lot more difficult. I'll focus on the former in this comment.

I recently modified the documentation to specify a correct release procedure: http://ga4gh-reference-implementation.readthedocs.io/en/latest/development.html#release-process I will do so again to note the automated deployment, which automates steps (as specified in the link) 3, 4 and 5. Steps 1 and 2, on the other hand, are impossible to automate: a script can't know a) what tag we want to put on the release or b) what packages should be pinned to which versions or c) what the release notes should be. Furthermore, automating step 2 would require us to forego peer review (and CI) of a release PR, which probably isn't a good idea.

What we could possibly do, although I am not necessarily advocating this, is to have a test in the spirit of test_constraints.py which tests if the commit is a planned release commit and ensures that the relevant invariants are met (e.g. ga4gh dependencies are pinned, constraints file is empty, etc.), and fails if not. The tricky part is, how do we notify this test that the commit is indeed a planned release? We don't want to tag the commit before it passes CI. Any change that we could look for (e.g. the release notes file has changed) might have forgotten to be done, in which case the test doesn't really check what we want it to. We could set some kind of flag, but in that case why not remember to do the manual steps instead? Perhaps there is a good way to write this test, but I'm not sure what it would be. David mentions some magic value stored in a git commit message, but if at all possible I want to preserve a separation of concerns between the code and the SCM.

kozbo commented 7 years ago

Thanks for diving into the details @david4096 and @dcolligan.

There are certain steps that will need to be done manually. Once those are done we should be able to run a script, passing in a few parameters, and get the job done.

So what are the manual steps? As Danny pointed out

  1. Create the release notes (I think David's ideas about creating a script to pull all the top level commit messages and concatenating them is a good start. I still think it will need some editing. I think we could be better at writing descriptive commit messages.)
  2. Set the new versions in the requirements.txt file

Once those are done then we can run a release_now.py script passing the version to be released (and probably some other params TBD).

Setting up this structure in each repo will vastly simplify the release process and remove most of the error-prone manual steps.

david4096 commented 7 years ago

Yaks shall be shaved!

I was thinking adding a value into the travis.yml that says if it's flagged for a release instead of hiding something in a commit message, but let's keep it simple. @kozbo when you have done 1 and 2 by hand, three is to tag a commit and push it ( I think ).

dcolligan commented 7 years ago

One thing that we could do, potentially, if we wanted to push an artifact on every successful build would be to have our non-release commits push to the pypi testing site https://testpypi.python.org/pypi instead of the real thing. The advantage of doing this would be that we would have a publicly-accessible non-authoritative artifact built on every release. The downside would be that this would be another release step to automate; we would have to rewrite the .travis.yml (or find some other way of telling travis which configuration to use) on release commits.

david4096 commented 7 years ago

In the future, we won't tag alpha releases manually (I hope). We should be able to use handwritten tags for stable releases and then a sensible alpha-beta release cycle using travis deploy. This will make it easy to choose release candidates from beta builds that can be "retagged" as a release version. Right now you can run pluck a commit to choose as a release candidate anytime during a development cycle, but having seen the package move through the release machinery gives a higher level of confidence.

Until a PR happens at schemas master, our current scm version comes out to ga4gh-schemas-0.6.0a10.dev20+ng1ad7495 for schemas, for me pip install git+git://github.com/ga4gh/schemas . I believe we can use the setuptools_scm version to automatically create sensible versions between tagged releases. And upload those to pypi with "pre" tags. To get this right we'll also need to package the compiled protobuf at the schemas for the intermediate builds.