Monday, October 20, 2014

Scaling down continuous deployment

Before I started working on Mockito 1.10 release I set a goal for myself. I decided that the next release, and every subsequent release will be completely automatic and will happen on ‘git push’ without even any ‘release’ button pressing. Getting the release out of the door, without investing into automation, would be tons easier. However, I din’t want to take this shortcut _again_. I wanted to consume the lessons learned from the past: shameful 2-year release cadence, totally _not_ reflecting my attitude and experience in continuous delivery and software automation. I wanted the 1.10 version to start the new era in Mockito ecosystem. Now I need to scale this down a bit :)

Driven by the ‘completely automated release’ use case I’ve set up Travis CI, Bintray, GitHub and the master tool: Gradle to let the magic happen. At the time, I was already thinking that releasing on every push might be too eager. However, I couldn’t come up with convincing use cases and it was getting hard to decide on the ‘right’ release trigger. So I’ve applied my favorite approach: get stuff DONE and then watch REAL use cases and feedback showing up.

We learned pretty quickly that certain category of project events don’t make sense as release triggers. Consider all kinds of non-code changes that occur surprisingly often: updates to, adding TODOs, minor changes to the automation machinery. We worked around this problem by including a “[ci skip]” incantation in commit messages. Travis CI does not trigger the build for changes annotated with “[ci skip]”. This approach helps a bit but removes the validation of the changes completely because the build does not run at all. Not to mention that it's easy to forget to include the magic string in the commit message which would lead to an awkward release. So, I’ve improved the automation by crafting a Gradle task that compares binaries between the current build and the previous release. The release is skipped if binaries are the same (the comparison method is simplistic).

The second category of events that I started observing is pretty interesting. Consider internal code refactorings, changes that do not affect any public API nor the software behavior. Those changes still update the code, so the byte code is different and the jars are different. Should such changes trigger a new publication of a library? What would be the content of the release notes?

I’m undecided on this matter yet but I’ll make the call soon. Interesting use cases are already showing up. For one of the recent PRs I’d love to get some refactorings done first, before the eager contributor picks up the main implementation. It feels that in this case, it’s more effective if I prepare a landing for a new feature, instead of continuing the pull request code-review cycle. This will push our current continuous delivery model to address the internal refactorings and find the right place for them in the process.

Thursday, October 9, 2014

maven central vs bintray

When I started developing continuous deployment pipeline for Mockito I was (naively) thinking that I could happily publish to Bintray and forget about Maven Central.

Not quite :)

The reason I started looking at Bintray in the first place was that I was hoping for simpler publication process. Specifically, I wanted to be able to publish a new version from a CI box I don't own (for example: Travis CI box). It's not quite that easy with Nexus OSS publication model. Maven Central fancies PGP signatures for the publications. To generate signatures, the gpg tooling is needed and the key ring with a private key. To perform the release from a box I don't own I need to provision the key and possibly gpg tooling, too. It's doable but kind of... hard. At least it seems hard enough to look at alternate solutions for publishing to Central (hey Bintray!).

There was one more gotcha with publishing directly to Nexus OSS. I would probably need to use Gradle's signing plugin for the pgp stuff. This plugin needs love - it does not yet work with Gradle's new beautiful publication DSL. The option of using old publication plugin was not appealing to me at all.

Setting up automated publication was a breeze with gradle-bintray-plugin. I became complacent. Everything was neatly set up: every git push triggered a completely automated release, an update to the release notes, a new real version published etc. A couple of days passed and the keywords "when", "Mockito", "Central" started dominating the community air. I was curious why users needed the jars in Central when they were available in Bintray's jCenter. There were a couple of good arguments and here's my favorite.

Happiness :) A lot of people still use Maven. I'm perfectly OK with this because they all will use Gradle eventually. It won't be long, Gradle is unstoppable. Maven projects use Central Repository by default so naturally, it's nicer if Mockito is available without any extra configuration. I'm happy that I don't have to maintain the documentation how to set up maven builds to consume Mockito dependency (yes, users were asking us about this). It's just nice when stuff works out of the box.

I really want to forget about Central but it turns out the world around me does not forget and pushes back. I continuously publish to Bintray and I enjoy very much the automation level it offers. I can sync to Central from Bintray (a step that I haven't yet automated). I don't have to mess around with PGP any more because I can hook up the key to "Mockito" organisation in Bintray UI and that's it. The whole Maven Central PGP requirement was questioned already by Bintray.

Thank you Bintray for making automation challenges simpler! Continuous deployment of Mockito wouldn't be there without you. I'd be still figuring out how to PGP from Travis CI and biting my nails with Gradle's old publication model (the new model is such a beauty!). In meantime Mockito users would wait another 2 years for the next release. Thank you Central for serving the jars to all Maven users (btw. jCenter can do this, too ;).

Next week I'm at JDD Conference in Krakow talking about continuous delivery. After that, I'm keen on getting out a nice blog post on how to cut down 2-year release cadence to 2 hours.