Dague
Build Go projects, better. Based on dagger
.
Why?
dague
is a docker
cli plugin. It acts as a opinionated Go toolchain only relying on Docker as dependency.
You don't need to have the right version of Go or any other dependencies, if you have Docker you have everything.
Installation
-
Download the binary corresponding to your platform from the
latest
release.binaries are available for linux, mac and windows, for amd64 and arm64
-
Rename the binary to
docker-dague
and make it executablechmod +x docker-dague
-
On Mac, authorize the binary (as not signed):
xattr -d com.apple.quarantine docker-dague
-
Copy it to the docker directory for CLI plugins:
mkdir -p ~/.docker/cli-plugins install docker-dague ~/.docker/cli-plugins/
Usage
Configuration is made using a .dague.yml
file. This file is mandatory.
Build Targets
If you want to build a binary from main/path
to .dist/
this is the minimal file you need:
go:
build:
targets:
local-build:
path: ./main/path
With that, you can run docker dague go:build local-build
and it will build your binary and put it under ./dist/
.
The build is performed inside containers, so you don't have to worry about the needed dependencies, tools, versions, etc.
If you want to configure the output directory, set the out
key.
Default tools
By default dague
comes with handy go tools already configured like:
-
go:fmt
: runsgoimports
and a formatter (gofmt
by default, but configurable) to re-format the code -
go:lint
: runsgolangci-lint
andgovulncheck
-
go:doc
: generate Go documentation in markdown inside README.me files -
go:test
: run go unit tests with handy defaults (-race -cover -shuffle=on
) -
go:mod
: rungo mod tidy
and updatego.mod
andgo.sum
files
Some subcommands exist, you can see them using the --help
flag.
Arbitrary Task Inside Container
It's also possible to define any script that will be run from the inside of the build container. The exec task can also define files to export to the host.
go:
exec:
info:
cmds: |
uname -a > info.txt
go version >> info.txt
export:
pattern: info.txt
path: .
Then you can run:
❯ docker dague go:exec info
# ...
❯ cat info.txt
Linux buildkitsandbox 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022 aarch64 Linux
go version go1.19.4 linux/arm64
In comparison, this is the output of go version
directly on my host:
❯ go version
go version go1.19.4 darwin/arm64
Arbitrary Tasks on Host
You can also define any arbitrary task to be run on the host:
tasks:
install:
deps:
- go:build local
cmds: |
mkdir -p ~/.docker/cli-plugins
install dist/docker-dague ~/.docker/cli-plugins/docker-dague
The command docker dague task install
will first run go:build local
then run the shell script to install the binary.
The shell script is run using a Go shell implementation so is portable across platforms.
Base Image Configuration
The base image for go tools can be configured:
- the image to use
- apt or apk packages to install
- go packages to install
- mount directories
- environment variables
- caches
For instance, if you want to use gofumpt
instead of gofmt
, follow this configuration:
go:
image:
goPackages:
- mvdan.cc/gofumpt@latest
fmt:
formatter: gofumpt
With that, docker dague go:fmt
(or more specifically docker dague go:fmt:write
) will now use the specified gofumpt
formatter instead of the default gofmt
.
go:
image:
caches:
- target: /cache/go
env:
GOCACHE: /cache/go
GOLANGCI_LINT_CACHE: /cache/go
With that, a cache will be mounted and two environment variables are set to reflect it.
Reference
To know more about the possibilities and available configuration, please refer to the configuration reference file.
dague
import "github.com/eunomie/dague"
Index
- func ApkInstall(packages ...string) []string
- func AptInstall(cont *dagger.Container, packages ...string) *dagger.Container
- func Exec(ctx context.Context, src *dagger.Container, args []string) error
- func ExportFilePattern(ctx context.Context, cont *dagger.Container, pattern, path string) error
- func GoInstall(packages ...string) []string
- func RunInDagger(ctx context.Context, do func(*dagger.Client) error) error
func ApkInstall
func ApkInstall(packages ...string) []string
ApkInstall runs the apk add command with the specified packaged, to install packages on alpine based systems. Example:
c.Container().From("alpine").WithExec(ApkInstall("build-base"))
func AptInstall
func AptInstall(cont *dagger.Container, packages ...string) *dagger.Container
AptInstall runs apt-get to install the specified packages. It updates first, install, then clean and remove apt-get lists. Example:
dague.AptInstall(c.Container().From("debian"), "gcc", "git")
func Exec
func Exec(ctx context.Context, src *dagger.Container, args []string) error
Exec runs the specified command and check the error and exit code. Example:
err := dague.Exec(ctx, c.Container().From("golang"), []string{"go", "build"})
func ExportFilePattern
func ExportFilePattern(ctx context.Context, cont *dagger.Container, pattern, path string) error
func GoInstall
func GoInstall(packages ...string) []string
GoInstall installs the specified go packages. Example:
c.Container().From("golang").WithExec(GoInstall("golang.org/x/vuln/cmd/govulncheck@latest"))
func RunInDagger
func RunInDagger(ctx context.Context, do func(*dagger.Client) error) error
RunInDagger initialize the dagger client and close it. In between it runs the specified function. Example:
dague.RunInDagger(ctx, func(c *dagger.Client) error {
c.Container().From("alpine")
})
Generated by gomarkdoc