Semantic Version Support
Versioning packages in Go is a problem. Let me illustrate this with three examples.
- I was recently looking at Kubernetes, its dependencies, and the dependencies of its dependencies. There are numerous cases where the same dependency is imported, the version specified is different, and the version is a commit id. Can you decipher what should be going on?
- I was looking at a project importing Kubernetes. The version specified was a commit id. Since Kubernetes releases versions I was wondering what version was being used. After a little searching I found it was a commit between two versions. When projects have stable releases when is it a good idea to use a commit between releases?
- What if you found an application using the version
f9885acc8cd1403afcd09570c89a009e8bd1dc19of OpenSSL. Would you think it was a good idea to use that application? Would you know what vulnerabilities had been fixed? This is theoretical since no one does that. That commit id happens to be vulnerable to Heartbleed. With versions it’s pretty easy to see if a release is after the fixed version. When using commit ids it’s not.
Semantic Versioning (SemVer) is a nice way to version packages and applications. Not only is it widely used it has a versioned spec making it easy to write support for.
Glide now supports SemVer and you can use constraints. For example, for a version you can specify
1.2.x (which is
>= 1.2.0, < 1.3.0),
^1.2.3 (which is
>= 1.2.3, < 2.0.0), and a host of other options. Glide will try to pick the latest release to meet the constraint. The SemVer handling is through the
github.com/Masterminds/semver package. In the documentation you can see the supported syntax and even use it in your own applications.
Of course, you can still specify a branch, tag, or commit id. Those have a higher priority than attempting to figure out the right semantic version.
Automatic Dependency Flattening
Go works best when there is only one import location for a package in a build. This is best seen in the
$GOPATH which is one location. With
vendor/ directory support there’s an opportunity for packages to import packages that import packages and the dependencies are in the corresponding
Different packages can import different versions and objects created in one package location are going to have an issue working with the same package in another import location. To illustrate this I’ve put an example online that you can clone and fail to run.
And it’s worth noting that each separate import location is included in the resulting build binary. This can easily lead to binary bloat.
Glide now flattens dependencies to a top level
vendor/ folder unless the dependency has chosen to self manage the dependencies. In addition to Glide managed projects, this also works with Godep, GPM, and gb managed projects when flattening. You can import packages managed by different tools.
Building Practical Solutions
We’re attempting to build Glide to be a practical tool solving real problems. Given the fragmentation of package management in Go that means working with packages managed with multiple tools. Using the new vendor support in Go means we learn practical ways to work with these packages and try to come up with useful solutions.
If you want to contribute to this or you have some insight please drop by the issue queues or find us in IRC (
#masterminds room on Freenode). We’re happy to talk and welcomes pull requests and feedback.