Recently I’ve been maintaining a Github repository to serve as a generic template for my Golang projects, and its been working rather well for me.
The repository is here: Self-contained Go Project
The basic idea is that using this template, you can setup a Go project with
vendored dependencies not just for the main project but also for every tool
used in building and linting it (with the exception of
git and a
working Golang install).
go get <my project> cd $GOPATH/src/<my project> make
does a production build.
How to Use It
Out of the box (i.e.
git clone https://github.com/wrouesnel/self-contained-go-project.git)
on a Linux machine it should be all setup to go. I’ve made some effort to try
and remove Linux specific things from it, but since I don’t run Mac OS or
Windows for Go development it’s probably not working too well there.
Essentially, it’ll build multi-platform, CGO-less binaries for any
package you place in a folder underneath the
cmd directory. Running
will build all current commands for your current platform and symlink them into
the root folder, while running
make release will build all binaries and then
create tarballs with the name and version in the
It also includes bevy of other CI-friendly commands - namely
make style which
goimports formatting and
make lint which runs
gometalinter against the entire project.
Just looking at the commands, the main thing accomplished is a lot of use of
make. It’s practically used for ergonomics more then utility to some level
make is a familiar “build whatever this is” command in the Unix world.
make is used correctly - build dependencies are expressed
and managed in a form it understands so it only rebuilds as necessary.
But there is more important element, and that is not just that there is a
Makefile but that the repository for the project, through
not just the code but also the linting and checking tools needed to build it,
and a mechanism to update them all.
tools directory we have a secondary
Makefile which is called from
the top-level and is reposible for managing the tools. By running
here we can
go get a new version of
gometalinter, extract the list of tools
it runs, then automatically have them updated and installed inside the source
directory and made available to the top level
Makefile to use to run CI tasks.
This combines to make project management extremely ergonomic in my opinion,
and avoids dragging a heavier tool like
Docker into the mix (which often means
some uncontrolled external dependencies).
Basically: you check in everything your project needs to be built and run and tested into the one Git repository, because storage is cheap but your time is not and external dependencies can’t be trusted to always exist.
It’s not the be all and end all - in build tooling there never is one, but I’m thusfar really happy with how this basic structure has turned out as I’ve evolved it and it’s proven relatively easy to extend when I need to (i.e. adding more testing levels, building web assets as well with npm and including them in the go-binary etc.)