Releasing Open Source

Being a good open source citizen for the benefit of humans and tooling.

First published on 31 Aug 2013, last revised 13 Nov 2013.

Gophers with a friendly fox

There a few simple things we can all do to improve the Go ecosystem. Before you unleash your next open source project and [ANN] it on Go Nuts, consider this.

See What's Out There

Before getting started, do a search on GoDoc or ask around.

There are already a few packages for working with databases: codex, gorp, goSQL, hood, jet, kdb, meddler, sqlx, Vivom, and xorm.

We probably have enough options, but I bet any one of these packages could be improved upon. Why not pick one and contribute?

If later you decide to start fresh, or take a wildly different approach, you'll have met a fellow gopher, and probably learned something too.

Write A Readme

Make a good first impression with a README that describes the purpose of your project, how to install it, and how to use it.

You might even consider writing it first. Go itself began with the spec:

$ hg log -r4
changeset:   4:4e9a5b095532
user:        Robert Griesemer <gri@golang.org>
date:        Sun Mar 02 20:47:34 2008 -0800
summary:     Go spec starting point.

If you're writing a reusable library, also be sure to document the APIs. GoDoc makes it easy for others to read your API documentation. Add a GoDoc badge to your README (see the Tools link on the GoDoc page for your package).

Encourage Contributions

In addition to a README.md, provide instructions for those who have a question, an issue, or code to contribute. Put this in a file named CONTRIBUTING.md. If you're using GitHub, it will link to your CONTRIBUTING file from the New Issue form:

Please review the guidelines for contributing to this repository.

Choose A License

Go is under a BSD (3-clause) License. I don't need the third clause for personal projects, so I just use the BSD 2-clause License (Simplified BSD). Choose whatever license suits your needs.

There is a LICENSE file in the root of my Development folder with the Copyright set, so I can just copy the file and I'm good to go. I'm investigating project generators to make this process even smoother.

Tag Your Releases

40-character SHAs aren't the best for conversation.

What version did you have when you ran into this bug?

Oh, I think it was commit df126e5386a3ed95a945f99cd910a2b82dc422c6.

Right now go get has no concept of releases, but the DVCS way to indicate releases is through tags. Tools like Johnny Deps and Rx already make use of tags to checkout specific releases. When I looked at using one of these tools, I found that 3 of 4 dependencies had no tags (sad panda). Then I realized I hadn't tagged my project yet either!

Whether or not you use these tools, it's still a good habit to add tags in your DVCS of choice.

Git

See Pro Git for details.

git tag v1.0.0         # Tag the current revision
git tag v0.1.0 b13a082 # Tag a past revision
git tag                # List tags
git push origin --tags # Share tags (pushes tags only)

Mercurial

See Mercurial: The Definitive Guide for details.

hg tag v1.0.0          # Tag the current revision
hg tag -r 13 v0.1.0    # Tag a past revision
hg tags                # List tags
hg push                # Share tags (.hgtags already committed)

Bazaar

See Bazaar Wiki for details. Yes, these instructions are exactly the same as Mercurial.

bzr tag v1.0.0         # Tag the current revision
bzr tag -r 13 v0.1.0   # Tag a past revision
bzr tags               # List tags
bzr push               # Share tags (stores tags with branch)

Versions

Go uses semantic versioning and so should we. Go went through many changes until it stabilized as v1.0.0.

"Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable." - SemVer

This year Go v1.1.0 was released, a backwards compatible update. Then v1.1.2 was a patch release, and breaking changes await a v2.0.0 release in the distant future. So we're all on the same page, please read and follow Semantic Versioning 2.0.0.

If you are strongly against versions, please still tag your releases. Might I suggest using the international date format (ISO 8601), as in r2013-08-31?

Futureproof

We can prepare today for the tools we are building tomorrow.

There are APIs to list tags for GitHub and BitBucket. If we stick to a consistent tagging format, tools can parse them into their constituent parts. Then versions can be compared very simply, eg. >= 3.2.0, whereas a tool could only determine if 11586e3 > b1e3a97 with the full DVCS history.

If you're in the camp that wants a SAT solver like Bundler, tagging our releases is the first step in that direction. If you never want to hear of SAT again, having been traumatized by Maven (so I hear), tagged releases are still incredibly helpful for us today.

Write a Changelog

Dominik Honnef is writing a wonderful series entitled "What's happening in Go tip". Reading a high-level summary of changes is so much nicer than parsing dozens of commit messages.

This is the benefit of providing a changelog for your project, even if it's just in point form. Here's an example:

# Changelog

## v0.2.1 / 2013-07-06

* Add --debug flag to help track down [#6] Tests run twice

## v0.2.0 / 2013-05-16

* Rename to Looper
* Packages are the unit of compilation in Go. Use a package-level
  granularity for testing.
* Don't log Stat errors (can be caused by atomic saves in editors)
...

Please take note:

  • Entries are in reverse chronological order, putting the most relevant information first.
  • The first "word" for second-level headings matches the tag we used previously.
  • A standard file name makes it easier for humans to locate. CHANGELOG.md was the most favoured in the survey that accompanied this article, so I am renaming my Changelogs.
  • Though not shown here, it's fairly common to have an "Unreleased" section at the top, building up a list of changes that will become the next release.

Markdown is a well known format that displays nicely on GitHub and BitBucket. There was an overwhelming preference for Markdown in the survey results.

Tools exist to generate changelogs, though I have yet to try any. What I find more interesting are tools to parse changelogs. Apps like Gemnasium will present the relevant subset of a changelog. Consistent use of tags, subheadings and file names make this kind of tooling fairly straightforward.

Green Master

With go get, anyone could pull your master branch at any time. When writing a reusable library, it's critical to keep master stable.

Rather than developing directly on master, use a feature branch, and only merge when ready for release. Before merging, review your own code, or ask your peers to take a look. If you're using GitHub, a great way to do this is with a pull request from the feature branch to master.

Write unit tests to help ensure that your code continues to behave according to your expectations. Besides running your tests locally, consider setting up Continuous Integration. Some CI services will integrate with pull requests, helping you keep master green.

Release Often

After the 14-month marathon that was Go 1.1, Go has moved to a 6 month release cycle.

"One of the benefits of time based releases is that they encourage evolutionary change, instead of revolutionary change. Instead of radical breaks every year or two years, smaller changes are made every month." - Jeremy Evans

An interesting observation that I would like to explore.

Finî

I hope this is a good starting place for practices that are beneficial today, while also paving the way for better tooling.

When this article was first published, I included a survey, to help establish some conventions for tagging and naming of changelogs. With only 92 respondents, it may not be conclusive, but I'm already updating my projects based on the results.

Hopefully some tools will appear that can rely on these conventions, and I'm currently investigating a badge to help encourage adoption.

Comment on Go+, reddit, or the Go Nuts mailing list.

Related Articles:

get updates

Nathan Youngman

Rubyist and Go enthusiast.