Skip to content

Instantly share code, notes, and snippets.

@sheldonhull
Last active April 20, 2023 17:51
Show Gist options
  • Save sheldonhull/84f45fc521274f144c01f3a02d494298 to your computer and use it in GitHub Desktop.
Save sheldonhull/84f45fc521274f144c01f3a02d494298 to your computer and use it in GitHub Desktop.
optimze dagger go sdk build speed
package main
import (
"os"
"os/exec"
"path/filepath"
"github.com/pterm/pterm"
)
// Build contains the mage task for ... building stuff ... duh.
type Build mg.Namespace
const (
// ArtifactDirectory is a directory containing artifacts for the project and shouldn't be committed to source.
ArtifactDirectory = ".artifacts"
// PermissionUserReadWriteExecute is the permissions for the artifact directory.
PermissionUserReadWriteExecute = 0o0700
// CacheDirectory is where the cache for the project is placed, ie artifacts that don't need to be rebuilt often.
CacheDirectory = ".cache"
)
var(
// TargetBuildDirectory is the directory where the build artifacts are placed and should be ignored by git.
TargetBuildDirectory = filepath.Join(ArtifactDirectory, "builds")
)
// MyApp builds the myapp service using Dagger.
//
// Development notes: This is a fully containerized build.
// Running go build locally was approx 3 seconds faster without further tuning, so I'm leaving the build method to use Dagger/BuildKit here to easily support containerized builds.
func (Build) MyApp() error {
ctx := context.Background()
pterm.DefaultHeader.Println("Building with Dagger")
if err := os.MkdirAll(filepath.Join(constants.TargetBuildDirectory, "myapp"), constants.PermissionUserReadWriteExecute); err != nil {
return err
}
// initialize Dagger client
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stdout))
if err != nil {
return err
}
defer client.Close()
// get reference to the local project
src := client.Host().Directory(".")
cachedBuild := client.CacheVolume("go-build-cache")
cachedMod := client.CacheVolume("go-mod-cache")
modcache := "/nonroot/.cache/go-mod-cache"
buildcache := "/nonroot/.cache/go-build-cache"
// get `golang` image
golang := client.Container().From("cgr.dev/chainguard/go:latest").
WithEnvVariable("CGO_ENABLED", "0").
WithEnvVariable("GOOS", runtime.GOOS).
WithEnvVariable("GOARCH", runtime.GOARCH).
WithEnvVariable("GOMODCACHE", modcache).
WithEnvVariable("GOCACHE", buildcache)
// mount cloned repository into `golang` image
golang = golang.WithMountedDirectory("/src", src).
WithWorkdir("/src").
WithMountedCache(modcache, cachedMod).
WithMountedCache(buildcache, cachedBuild)
// define the application build command
outputDirectory := filepath.Join(constants.TargetBuildDirectory, "myapp")
outputFile := filepath.Join(outputDirectory, "myapp-service")
golang = golang.WithExec([]string{"build", "-o", outputFile, "-ldflags", "-s -w", "-trimpath", "./myapp/main.go"})
// get reference to build output directory in container
output := golang.Directory(outputDirectory).File("myapp-service")
// write contents of container build/ directory to the host
_, err = output.Export(ctx, outputFile)
if err != nil {
return err
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment