Releasing Open Source
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 <[email protected]>
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 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 reddit, or the Go Nuts mailing list.
Related Articles:
- Go Package Management
- Go Testing Toolbox
- A Better Changelog by Jeff Forcier
- “Merge pull request” Considered Harmful by Nathaniel Talbott