From 8e42fbd8b724e88684333e353caecf7a721c3a01 Mon Sep 17 00:00:00 2001 From: Jacob Gillespie Date: Fri, 27 Jan 2023 17:45:49 +0000 Subject: [PATCH] Add the ability to specify `--build-platform` --- pkg/buildx/buildx.go | 14 +++++++++++--- pkg/cmd/bake/bake.go | 15 ++++++++++++--- pkg/cmd/build/build.go | 11 ++++++++++- pkg/helpers/buildplatform.go | 22 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 pkg/helpers/buildplatform.go diff --git a/pkg/buildx/buildx.go b/pkg/buildx/buildx.go index 2f9becdd..7650dce9 100644 --- a/pkg/buildx/buildx.go +++ b/pkg/buildx/buildx.go @@ -43,7 +43,7 @@ import ( const DefaultTargetName = "default" -func BuildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]build.Options, progressMode, contextPathHash, metadataFile string, project string, token string, allowNoOutput bool) (imageID string, err error) { +func BuildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]build.Options, progressMode, contextPathHash, metadataFile string, project string, token string, allowNoOutput bool, buildPlatform string) (imageID string, err error) { var buildErr error ctx2, cancel := context.WithCancel(context.TODO()) @@ -74,7 +74,7 @@ func BuildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu } }() - dis, err := GetDrivers(ctx, dockerCli, contextPathHash, b.Msg.BuildId, token) + dis, err := GetDrivers(ctx, dockerCli, contextPathHash, b.Msg.BuildId, token, buildPlatform) if err != nil { return "", err } @@ -112,7 +112,7 @@ func BuildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu return resp[DefaultTargetName].ExporterResponse["containerimage.digest"], err } -func GetDrivers(ctx context.Context, dockerCli command.Cli, contextPathHash string, buildID string, token string) ([]build.DriverInfo, error) { +func GetDrivers(ctx context.Context, dockerCli command.Cli, contextPathHash string, buildID string, token string, buildPlatform string) ([]build.DriverInfo, error) { imageopt, err := storeutil.GetImageConfig(dockerCli, nil) if err != nil { return nil, err @@ -151,6 +151,14 @@ func GetDrivers(ctx context.Context, dockerCli command.Cli, contextPathHash stri }, } + if buildPlatform == "linux/amd64" { + return []build.DriverInfo{amdDriverInfo}, nil + } + + if buildPlatform == "linux/arm64" { + return []build.DriverInfo{armDriverInfo}, nil + } + if strings.HasPrefix(runtime.GOARCH, "arm") { return []build.DriverInfo{armDriverInfo, amdDriverInfo}, nil } diff --git a/pkg/cmd/bake/bake.go b/pkg/cmd/bake/bake.go index ac6f6d51..f006f926 100644 --- a/pkg/cmd/bake/bake.go +++ b/pkg/cmd/bake/bake.go @@ -13,6 +13,7 @@ import ( "github.com/depot/cli/pkg/buildx" "github.com/depot/cli/pkg/config" dockerclient "github.com/depot/cli/pkg/docker" + "github.com/depot/cli/pkg/helpers" "github.com/depot/cli/pkg/project" cliv1beta1 "github.com/depot/cli/pkg/proto/depot/cli/v1beta1" "github.com/docker/buildx/bake" @@ -27,8 +28,9 @@ import ( ) type bakeOptions struct { - project string - token string + project string + token string + buildPlatform string files []string overrides []string @@ -129,7 +131,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error } }() - dis, err := buildx.GetDrivers(ctx, dockerCli, contextPathHash, b.Msg.BuildId, in.token) + dis, err := buildx.GetDrivers(ctx, dockerCli, contextPathHash, b.Msg.BuildId, in.token, in.buildPlatform) if err != nil { return err } @@ -238,6 +240,12 @@ func NewCmdBake() *cobra.Command { return fmt.Errorf("missing API token, please run `depot login`") } + buildPlatform, err := helpers.NormalizePlatform(options.buildPlatform) + if err != nil { + return err + } + options.buildPlatform = buildPlatform + dockerCli, err := dockerclient.NewDockerCLI() if err != nil { fmt.Fprintln(os.Stderr, err) @@ -253,6 +261,7 @@ func NewCmdBake() *cobra.Command { // Depot options flags.StringVar(&options.project, "project", "", "Depot project ID") flags.StringVar(&options.token, "token", "", "Depot API token") + flags.StringVar(&options.buildPlatform, "build-platform", "dynamic", `Run builds on this platform ("dynamic", "linux/amd64", "linux/arm64")`) // docker buildx bake options flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file") diff --git a/pkg/cmd/build/build.go b/pkg/cmd/build/build.go index 6bc41cda..963aa6d0 100644 --- a/pkg/cmd/build/build.go +++ b/pkg/cmd/build/build.go @@ -9,6 +9,7 @@ import ( _ "github.com/depot/cli/pkg/buildxdriver" "github.com/depot/cli/pkg/config" "github.com/depot/cli/pkg/docker" + "github.com/depot/cli/pkg/helpers" "github.com/depot/cli/pkg/project" "github.com/docker/buildx/build" "github.com/docker/buildx/util/buildflags" @@ -32,6 +33,7 @@ type buildOptions struct { project string token string allowNoOutput bool + buildPlatform string contextPath string dockerfileName string @@ -232,7 +234,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) { contextPathHash = in.contextPath } - imageID, err := buildx.BuildTargets(ctx, dockerCli, map[string]build.Options{buildx.DefaultTargetName: opts}, in.progress, contextPathHash, in.metadataFile, in.project, in.token, in.allowNoOutput) + imageID, err := buildx.BuildTargets(ctx, dockerCli, map[string]build.Options{buildx.DefaultTargetName: opts}, in.progress, contextPathHash, in.metadataFile, in.project, in.token, in.allowNoOutput, in.buildPlatform) err = buildx.WrapBuildError(err, false) if err != nil { return err @@ -287,6 +289,12 @@ func NewCmdBuild() *cobra.Command { return errors.Errorf("load and no-load may not be both set") } + buildPlatform, err := helpers.NormalizePlatform(options.buildPlatform) + if err != nil { + return err + } + options.buildPlatform = buildPlatform + options.contextPath = args[0] return runBuild(dockerCli, options) }, @@ -302,6 +310,7 @@ func NewCmdBuild() *cobra.Command { // Depot options flags.StringVar(&options.project, "project", "", "Depot project ID") flags.StringVar(&options.token, "token", "", "Depot API token") + flags.StringVar(&options.buildPlatform, "build-platform", "dynamic", `Run builds on this platform ("dynamic", "linux/amd64", "linux/arm64")`) allowNoOutput := false if v := os.Getenv("DEPOT_SUPPRESS_NO_OUTPUT_WARNING"); v != "" { diff --git a/pkg/helpers/buildplatform.go b/pkg/helpers/buildplatform.go new file mode 100644 index 00000000..03cd8742 --- /dev/null +++ b/pkg/helpers/buildplatform.go @@ -0,0 +1,22 @@ +package helpers + +import ( + "fmt" + "os" +) + +func NormalizePlatform(buildPlatform string) (string, error) { + if buildPlatform == "" { + buildPlatform = os.Getenv("DEPOT_BUILD_PLATFORM") + } + + if buildPlatform == "" { + buildPlatform = "dynamic" + } + + if buildPlatform != "linux/amd64" && buildPlatform != "linux/arm64" && buildPlatform != "dynamic" { + return "", fmt.Errorf("invalid build platform: %s (must be one of: dynamic, linux/amd64, linux/arm64)", buildPlatform) + } + + return buildPlatform, nil +}