Stop overcomplicating go[lang] build and dependencies

PUBLISHED ON 2014-08-17

There has been no shortage of packages to help manage Go[lang] dependencies. But, I think a lot of them are more complex than what a company actually needs.

Update: This requires a gopath per project (gopath mangling). It is a quick and dirty solution. This was written before gopkg.in existed.

At the end of the day, managing golang packages fall into two camps.

  1. People writing a library to share with others. For these people, I can offer no help, it is a hard problem. (update: I suspect gopkg.in is the right answer)
  2. People writing an app for internal use or in any case where they will distribute a binary or run the code against their own hardware. They use libraries to help create their application, but don’t distribute libraries. For this case, I think a small shell script is really all you need.

If you are building a product, you should be vendoring your dependencies. Why would you make your application build dependent on internet connections and random repositories you don’t control?

Now, there are a lot of complex ways to handle thing by rewriting import statements, vendoring “alongside” your app, and various other tooling. But, there is a simpler way.

Check everything in, and use one gopath per project. Seriously, just check in all your dependencies along your companies code. Then at any point in the future, you can recreate the entire thing dependably. Single clone of a repo is all you need, then build, test, run! Now, this has one major downside:

  • Updating. You don’t want to (or can’t) check in version control directories (.hg, .git, .bzr, etc) to your repository. Deleting them manually is annoying, and has to be done everytime you do an update.

Solution, a few lines of script to update all your dependencies whenever you need it, and they get checked in so you can always dependably go back to old versions of the code base.

#!/bin/zsh

OURCOMPANY="acme"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export GOPATH=$DIR

read REPLY\?"This will delete everything under ./src except $OURCOMPANY stuff, and get it again using go get, are you sure (y/n)? "
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
        # do dangerous stuff
        echo "Deleting all non $OURCOMPANY code"
        ls -d src/* | grep -v github.com | xargs rm -rf
        ls -d src/github.com/* | grep -v $OURCOMPANY | xargs rm -rf

        echo "Getting deps"
        go get github.com/gorilla/mux
        # ... one go get line per dep

        echo "Clean up source history downloaded"
        find . -type d | grep -v $OURCOMPANY | grep \.hg$ | xargs rm -rf
        find . -type d | grep -v $OURCOMPANY | grep \.bzr$ | xargs rm -rf
        find . -type d | grep -v $OURCOMPANY | grep -v ^\./\.git$ | grep \.git$ | xargs rm -rf
        # might need to add svn if we ever use SVN repos
fi
comments powered by Disqus