Bingo
Like `go get` but for Go tools! CI Automating versioning of Go binaries in a nested, isolated Go modules.
Install / Use
/learn @bwplotka/BingoREADME
bingo
go get like, simple CLI that allows automated versioning of Go package level binaries (e.g required as dev tools by your project!) built on top of Go Modules, allowing reproducible dev environments.
Features
From our experience all repositories and projects require some tools and binaries to be present on the machine to be able to perform various development operations like building, formatting, releasing or static analysis. For smooth development all such tools should be pinned to a certain version and bounded to the code commits there were meant to be used against.
Go modules does not aim to solve this problem, and even if they will do at some point it will not be on the package level, which makes it impossible to e.g pin minor version X.Y.0 of package module1/cmd/abc and version X.Z.0 of module1/cmd/def.
At the end bingo, has following features:
- It allows maintaining separate, hidden, nested Go modules for Go buildable packages you need without obfuscating your own module or worrying with tool's cross dependencies!
- Package level versioning, which allows versioning different (or the same!) package multiple times from a single module in different versions.
- Works also for non-Go projects. It only requires the tools to be written in Go.
- No need to install
bingoin order to use pinned tools. This avoids the "chicken & egg" problem. You only needgo build. - Easy upgrade, downgrade, addition, and removal of the needed binary's version, with no risk of dependency conflicts.
- NOTE: Tools are often not following semantic versioning, so
bingoallow one to pin by commit ID.
- NOTE: Tools are often not following semantic versioning, so
- Immutable binary names. This creates a reliable way for users and CIs to use expected version of the binaries, reinstalling on-demand only if needed.
- Works with all buildable Go projects, including pre Go modules and complex projects with complex directives like
replace,retractorexcludestatements. (e.g Prometheus) - Optional, automatic integration with Makefiles.
You can read full a story behind bingo in this blog post.
Requirements
- Go 1.24+
- Linux or MacOS (Want Windows support? Helps us out)
- All tools that you wish to "pin" have to be built in Go (they don't need to use Go modules at all).
Installing
In your repository (does not need to be a Go project)
go install github.com/bwplotka/bingo@latest
For go version before 1.17 use
go get github.com/bwplotka/bingoinstead.
Recommended: Ideally you want to pin bingo tool to the single version too (inception!). Do it via:
bingo get -l github.com/bwplotka/bingo
Usage
go get but for binaries!
The key idea is that you can manage your tools similar to your Go dependencies via go get:
bingo get [<package or binary>[@version1 or none,version2,version3...]]
For example:
bingo get github.com/fatih/faillintbingo get github.com/fatih/faillint@latestbingo get github.com/fatih/faillint@v1.5.0bingo get github.com/fatih/faillint@v1.1.0,v1.5.0
After this, make sure to commit .bingo directory in git repository, so the tools will stay versioned! Once pinned, anyone can install correct version of the tool with correct dependencies by either doing:
bingo get <tool>
For example bingo get faillint
... or without bingo:
go build -mod=mod -modfile .bingo/<tool>.mod -o=$GOBIN/<tool>-<version>
For example go build -mod=mod -modfile .bingo/faillint.mod -o=$GOBIN/faillint-v1.5.0
bingo allow one to easily maintain a separate, nested Go Module for each binary. By default, it will keep it .bingo/<tool>.mod This allow one to correctly pin the binary without polluting the main go module or other's tool module.
Using Installed Tools
bingo get builds pinned tool or tools in your $GOBIN path. Binaries have a name following <provided-tool-name>-<version> pattern. So after installation you can do:
- From shell:
${GOBIN}/<tool>-<version> <args>
For example: ${GOBIN}/faillint-v1.5.0
While it's not the easiest for humans to read or type, it's essential to ensure your scripts use pinned version instead of some non-deterministic "latest version".
NOTE: If you use
-loption, bingo creates symlink to <tool> . Use it with care as it's easy to have side effects by having another binary with same name e.g on CI.
bingo does not have run command (for a reason), it provides useful helper variables for script or adhoc use:
NOTE: Below helpers makes it super easy to install or use pinned binaries without even installing
bingo(it will use justgo build!) 💖
- From shell:
source .bingo/variables.env
${<PROVIDED_TOOL_NAME>} <args>
- From Makefile:
include .bingo/Variables.mk
run:
$(<PROVIDED_TOOL_NAME>) <args>
Real life examples!
Let's show a few, real, sometimes novel examples showcasing bingo capabilities:
-
golangci-lintis all-in-one lint framework. It's important to pin it on CI so CI runs are reproducible no matter what new linters are added, removed or changed in new release. Let's pin it tov1.35.2and use path recommended by golangci-lint install docs:github.com/golangci/golangci-lint/cmd/golangci-lint(funny enough they discouragego getexactly because of the lack of pinning featuresbingohave!)bingo get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.35.2This will pin to that commit and install
${GOBIN}/golangci-lint-v1.35.2 -
It's very common in Go world to use
goimports, populargofmtreplacement which formats Go code including imports. However, not many know that it's breaking compatibility a lot between versions (there are no releases). If you want to assert certain formatting of the Go code in the CI etc your only option is to pingoimportsversion. You can do it viabingo get:bingo get golang.org/x/tools/cmd/goimports@latestThis will install (at the time of writing) latest binary:
${GOBIN}/goimports-v0.0.0-20210112230658-8b4aab62c064 -
You rather like older formatting? No issue, let's downgrade. Since
goimportswas already installed you can reference it by justgoimports. Let's pick the commit we want e.ge64124511800702a4d8d79e04cf6f1af32e7bef2:bingo get goimports@e64124511800702a4d8d79e04cf6f1af32e7bef2This will pin to that commit and install
${GOBIN}/goimports-v0.0.0-20200519204825-e64124511800 -
Installing (and pinning) multiple versions:
bingo get goimports@e64124511800702a4d8d79e04cf6f1af32e7bef2,v0.0.0-20200601175630-2caf76543d99,af9456bb636557bdc2b14301a9d48500fdecc053This will pin and install three versions of goimports. Very useful to compatibility testing.
-
Updating to the current latest:
bingo get goimports@latestThis will find the latest module version, pin and install it.
-
Listing binaries you have pinned:
bingo list -
Unpinning
goimportstotally from the project:bingo get goimports@nonePS:
go getalso allows@nonesuffix! Did you know? I didn't (:* -
Installing all tools:
bingo get -
Bonus: Have you ever dreamed to pin command from bigger project like...
thanos? I was. Can you even install it using Go tooling? Let's try:go get github.com/thanos-io/thanos/cmd/thanos@v0.17.2 # Output: go: cannot use path@version syntax in GOPATH modeUps you cannot use this in non-Go project at all... (: Let's create setup go mod and retry:
go mod init _ # Output: go: creating new go.mod: module go get github.com/thanos-io/thanos/cmd/thanos@v0.17.2 # go get github.com/thanos-io/thanos/cmd/thanos@v0.17.2 # go: downloading github.com/thanos-io/thanos v0.17.2 # go: found github.com/thanos-io/thanos/cmd/thanos in github.com/thanos-io/thanos v0.17.2 # go get: github.com/thanos-io/thanos@v0.17.2 requires # github.com/cortexproject/cortex@v1.5.1-0.20201111110551-ba512881b076 requires # github.com/thanos-io/thanos@v0.13.1-0.20201030101306-47f9a225cc52 requires # github.com/cortexproject/cortex@v1.4.1-0.20201030080541-83ad6df2abea requires # github.com/thanos-io/thanos@v0.13.1-0.20201019130456-f41940581d9a requires # github.com/cortexproject/cortex@v1.3.1-0.20200923145333-8587ea61fe17 requires # github.com/thanos-io/thanos@v0.13.1-0.20200807203500-9b578afb4763 requires # github.com/cortexproject/cortex@v1.2.1-0.20200805064754-d8edc95e2c91 requires # github.com/thanos-io/thanos@v0.13.1-0.20200731083140-69b87607decf requires # github.com/cortexproject/cortex@v0.6.1-0.20200228110116-92ab6cbe0995 requires # github.com/prometheus/alertmanager@v0.19.0 requires # github.com/prometheus/prometheus@v0.0.0-20190818123050-43acd0e2e93f requires # k8s.io/client-go@v12.0.0
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
346.8kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).

