diff --git a/go/README.md b/go/README.md index dc2f747..655de44 100644 --- a/go/README.md +++ b/go/README.md @@ -13,3 +13,26 @@ Run: ``` dagger check -l ``` + +## Environment variables + +Pass `--env-vars` to set environment variables (in `KEY=VALUE` format) in the +Go container, e.g. for `GOEXPERIMENT` flags. As a toolchain, set it via a +customization in `dagger.json`: + +```json +{ + "toolchains": [ + { + "name": "go", + "source": "github.com/papercomputeco/daggerverse/go@main", + "customizations": [ + { + "argument": "envVars", + "default": "GOEXPERIMENT=jsonv2" + } + ] + } + ] +} +``` diff --git a/go/main.go b/go/main.go index c199314..510e2a5 100644 --- a/go/main.go +++ b/go/main.go @@ -5,29 +5,54 @@ import ( "dagger/go/internal/dagger" "errors" "fmt" + "strings" ) type Go struct { // +private Source *dagger.Directory + + // EnvVars is an optional list of environment variables to set in the + // Go container. Each entry must be in "KEY=VALUE" format. + // This is useful for build-time variables like GOEXPERIMENT. + // + // +private + EnvVars []string } func New( // +defaultPath="/" source *dagger.Directory, + + // Optional environment variables to set in the Go container. + // Each entry must be in "KEY=VALUE" format (e.g. "GOEXPERIMENT=jsonv2"). + // +optional + envVars []string, ) *Go { return &Go{ - Source: source, + Source: source, + EnvVars: envVars, } } -func (g *Go) goContainer() *dagger.Container { - return dag.Container(). +func (g *Go) goContainer() (*dagger.Container, error) { + ctr := dag.Container(). From("golang:1.26-bookworm"). WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod")). WithMountedCache("/root/.cache/go-build", dag.CacheVolume("go-build")). WithWorkdir("/src"). WithDirectory("/src", g.Source) + + // Apply caller-provided environment variables. + for _, env := range g.EnvVars { + parts := strings.SplitN(env, "=", 2) + if len(parts) != 2 || parts[0] == "" { + return nil, fmt.Errorf("invalid env var %q: must be in KEY=VALUE format", env) + } + ctr = ctr.WithEnvVariable(parts[0], parts[1]) + } + + return ctr, nil } // CheckGoModTidy runs "go mod tidy" and fails if it produces any changes to @@ -35,7 +60,12 @@ func (g *Go) goContainer() *dagger.Container { // // +check func (g *Go) CheckGoModTidy(ctx context.Context) (string, error) { - out, err := g.goContainer(). + ctr, err := g.goContainer() + if err != nil { + return "", fmt.Errorf("could not create go container: %w", err) + } + + out, err := ctr. WithExec([]string{"cp", "go.mod", "go.mod.HEAD"}). WithExec([]string{"cp", "go.sum", "go.sum.HEAD"}). WithExec([]string{"go", "mod", "tidy"}). @@ -62,7 +92,12 @@ func (g *Go) CheckGoModTidy(ctx context.Context) (string, error) { // // +check func (g *Go) CheckGoVet(ctx context.Context) (string, error) { - return g.goContainer(). + ctr, err := g.goContainer() + if err != nil { + return "", fmt.Errorf("could not create go container: %w", err) + } + + return ctr. WithExec([]string{"go", "vet", "./..."}). Stdout(ctx) }