README
¶
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 thechicken & eggproblem. Onlygo buildrequired. - Easy upgrade, downgrade, addition, or removal of the needed binary's version, with no risk of dependency conflicts.
- NOTE: Tools are often not following semantic versioning, so
bingoallows to pin by the commit.
- NOTE: Tools are often not following semantic versioning, so
- Immutable binary names, which gives a reliable way for users and CIs to use the expected version of the binaries, with reinstall on-demand only if needed.
- Optional, automatic integration with Makefiles.
You can read full a story behind bingo in this blog post.
Requirements
- Go 1.14+
- Linux or MacOS (Want Windows support? Helps us out, should be trivial!)
- All tools that you wish to "pin" have to be built in Go (they don't need to use Go modules at all).
Installing
go get github.com/bwplotka/bingo && go mod tidy
or if you already installed bingo and want to pin it (inception!):
bingo get -u github.com/bwplotka/bingo
Usage
Installing Tools
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...]]
Once pinned, anyone can reliably install correct version of the tool by either doing:
go build -modfile .bingo/<tool>.mod -o=<where you want to build> <tool package>
or
bingo get <tool>
bingo allows to easily maintain a separate, nested Go Module for each binary. By default, it will keep it .bingo/<tool>.mod This allows to correctly pin the binary without polluting the main go module or other's tool module.
Using Installed Tools
Bingo get builds pinned tool in your GOBIN path. Binaries have a name following <provided-tool-name>-<version> pattern. While it's not the easiest for humans to read, it's essential to ensure your scripts use pinned version instead of some "unknown" latest version.
While bingo does not have run command, it provides useful helper variables for script or adhoc use:
NOTE: Below helper variables makes it super easy to install 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>
Examples
Let's show a few, real examples on popular goimports tool (which formats Go code including imports):
-
Pinning latest
goimports:bingo -u get golang.org/x/tools/cmd/goimportsThis will install (at the time of writing) binary:
${GOBIN}/goimports-v0.0.0-20200601175630-2caf76543d99 -
After running above, pinning (or downgrading/upgrading) version:
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.
-
Unpinning
goimportstotally from the project:bingo get goimports@nonePS:
go getallows that, did you know? I didn't (: -
Editing
.modfile manually. You can totally go to.bingo/goimports.modand edit the version manually. Just make sure tobingo get goimportsto install that version! -
Installing all tools:
bingo get -
Using
goimports${GOBIN}/goimports-v0.0.0-20200519204825-e64124511800 -
Using
goimportswhile not hard-coding version:
-
From shell:
source .bingo/variables.env ${GOIMPORTS} <args> -
From Makefile:
include .bingo/Variables.mk
run:
@$(GOIMPORTS) <args>
-
Bonus: Makefile mode! If you use
Makefile,bingogenerates a very simple helper with nice variables. After running anybingo getcommand, you will notice.bingo/Variables.mkfile. Feel free to include this in your Makefile (include .bingo/Variables.mkon the top of your Makefile).From now in your Makefile you can use, e.g.
$(GOIMPORTS)variable which reliably ensures a correct version is used and installed. -
Bonus number 2! Using immutable names might be hard to maintain for your other scripts so
bingoalso produces environment variables you can source to you shell. It's as easy as:source .bingo/variables.envFrom now on you can use, e.g.
$(GOIMPORTS)variable which holds currently pinned binary name of the goimports tool.
Production Usage
To see production example see:
Contributing
Any contributions are welcome! Just use GitHub Issues and Pull Requests as usual. We follow Thanos Go coding style guide.
See an extensive and up-to-date description of the bingo usage below:
Command Help
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. 'bingo' allows to easily maintain a separate, nested Go Module for each binary.
For detailed examples see: https://github.com/bwplotka/bingo
'bingo' supports following commands:
Commands:
get <flags> [<package or binary>[@version1 or none,version2,version3...]]
Similar to 'go get' you can pull, install and pin required 'main' (buildable Go) package as your tool in your project.
'bingo get <repo/org/tool>' will resolve given main package path, download it using 'go get -d', then will produce directory (controlled by -moddir flag) and put
separate, specially commented module called <tool>.mod. After that, it installs given package as '$GOBIN/<tool>-<Version>'.
Once installed at least once, 'get' allows to reference the tool via it's name (without Version) to install, downgrade, upgrade or remove.
Similar to 'go get' you can get binary with given Version: a git commit, git tag or Go Modules pseudo Version after @:
'bingo get <repo/org/tool>@<Version>' or 'bingo get <tool>@<Version>'
'get' without any argument will download and get ALL the tools in the moddir directory.
'get' also allows bulk pinning and install. Just specify multiple versions after '@':
'bingo get <tool>@<version1,version2,tag3>'
Similar to 'go get' you can use -u and -u=patch to control update logic and '@none' to remove binary.
Once pinned apart of 'bingo get', you can also use 'go build -modfile .bingo/<tool>.mod -o=<where you want to build> <tool package>' to install
correct Version of a tool.
Note that 'bingo' creates additional useful files inside -moddir:
* '<moddir>/Variables.mk': When included in your Makefile ('include <moddir>/Variables.mk'), you can refer to each binary
using '$(TOOL)' variable. It will also install correct Version if missing.
* '<moddir>/variables.env': When sourced ('source <moddir>/variables.env') you can refer to each binary using '$(TOOL)' variable.
It will NOT install correct Version if missing.
-go string
Path to the go command. (default "go")
-insecure
Use -insecure flag when using 'go get'
-moddir string
Directory where separate modules for each binary will be maintained. Feel free to commit this directory to your VCS to bond binary versions to your project code. If the directory does not exist bingo logs and assumes a fresh project. (default ".bingo")
-n string
The -n flag instructs to get binary and name it with given name instead of default, so the last element of package directory. Allowed characters [A-z0-9._-]. If -n is used and no package/binary is specified, bingo get will return error. If -n is used with existing binary name, copy of this binary will be done. Cannot be used with -r
-r string
The -r flag instructs to get existing binary and rename it with given name. Allowed characters [A-z0-9._-]. If -r is used and no package/binary is specified or non existing binary name is used, bingo will return error. Cannot be used with -n.
-u The -u flag instructs get to update modules providing dependencies of packages named on the command line to use newer minor or patch releases when available.
-upatch
The -upatch flag (not -u patch) also instructs get to update dependencies, but changes the default to select patch releases.
-v Print more'
list <flags> [<package or binary>]
List enumerates all or one binary that are/is currently pinned in this project. It will print exact path, Version and immutable output.
-moddir string
Directory where separate modules for each binary is maintained. If does not exists, bingo list will fail. (default ".bingo")
-v Print more'
Version
Prints bingo Version.
Error: Failed to parse flags: flag: help requested
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. 'bingo' allows to easily maintain a separate, nested Go Module for each binary.
For detailed examples see: https://github.com/bwplotka/bingo
'bingo' supports following commands:
Commands:
get <flags> [<package or binary>[@version1 or none,version2,version3...]]
Similar to 'go get' you can pull, install and pin required 'main' (buildable Go) package as your tool in your project.
'bingo get <repo/org/tool>' will resolve given main package path, download it using 'go get -d', then will produce directory (controlled by -moddir flag) and put
separate, specially commented module called <tool>.mod. After that, it installs given package as '$GOBIN/<tool>-<Version>'.
Once installed at least once, 'get' allows to reference the tool via it's name (without Version) to install, downgrade, upgrade or remove.
Similar to 'go get' you can get binary with given Version: a git commit, git tag or Go Modules pseudo Version after @:
'bingo get <repo/org/tool>@<Version>' or 'bingo get <tool>@<Version>'
'get' without any argument will download and get ALL the tools in the moddir directory.
'get' also allows bulk pinning and install. Just specify multiple versions after '@':
'bingo get <tool>@<version1,version2,tag3>'
Similar to 'go get' you can use -u and -u=patch to control update logic and '@none' to remove binary.
Once pinned apart of 'bingo get', you can also use 'go build -modfile .bingo/<tool>.mod -o=<where you want to build> <tool package>' to install
correct Version of a tool.
Note that 'bingo' creates additional useful files inside -moddir:
* '<moddir>/Variables.mk': When included in your Makefile ('include <moddir>/Variables.mk'), you can refer to each binary
using '$(TOOL)' variable. It will also install correct Version if missing.
* '<moddir>/variables.env': When sourced ('source <moddir>/variables.env') you can refer to each binary using '$(TOOL)' variable.
It will NOT install correct Version if missing.
-go string
Path to the go command. (default "go")
-insecure
Use -insecure flag when using 'go get'
-moddir string
Directory where separate modules for each binary will be maintained. Feel free to commit this directory to your VCS to bond binary versions to your project code. If the directory does not exist bingo logs and assumes a fresh project. (default ".bingo")
-n string
The -n flag instructs to get binary and name it with given name instead of default, so the last element of package directory. Allowed characters [A-z0-9._-]. If -n is used and no package/binary is specified, bingo get will return error. If -n is used with existing binary name, copy of this binary will be done. Cannot be used with -r
-r string
The -r flag instructs to get existing binary and rename it with given name. Allowed characters [A-z0-9._-]. If -r is used and no package/binary is specified or non existing binary name is used, bingo will return error. Cannot be used with -n.
-u The -u flag instructs get to update modules providing dependencies of packages named on the command line to use newer minor or patch releases when available.
-upatch
The -upatch flag (not -u patch) also instructs get to update dependencies, but changes the default to select patch releases.
-v Print more'
list <flags> [<package or binary>]
List enumerates all or one binary that are/is currently pinned in this project. It will print exact path, Version and immutable output.
-moddir string
Directory where separate modules for each binary is maintained. If does not exists, bingo list will fail. (default ".bingo")
-v Print more'
Version
Prints bingo Version.
Initial Author
@bwplotka inspired by Paul's research and with a bit of help from Duco (:
Documentation
¶
There is no documentation for this package.
