diff --git a/commands/build.go b/commands/build.go index 99c00ab9..5bbec5b6 100644 --- a/commands/build.go +++ b/commands/build.go @@ -99,14 +99,25 @@ type buildOptions struct { func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error) { var err error + + buildArgs, err := listToMap(o.buildArgs, true) + if err != nil { + return nil, err + } + + labels, err := listToMap(o.labels, false) + if err != nil { + return nil, err + } + opts := controllerapi.BuildOptions{ Allow: o.allow, - BuildArgs: listToMap(o.buildArgs, true), + BuildArgs: buildArgs, CgroupParent: o.cgroupParent, ContextPath: o.contextPath, DockerfileName: o.dockerfileName, ExtraHosts: o.extraHosts, - Labels: listToMap(o.labels, false), + Labels: labels, NetworkMode: o.networkMode, NoCacheFilter: o.noCacheFilter, Platforms: o.platforms, @@ -782,24 +793,24 @@ func maybeJSONArray(v string) []string { return []string{v} } -func listToMap(values []string, defaultEnv bool) map[string]string { +func listToMap(values []string, defaultEnv bool) (map[string]string, error) { result := make(map[string]string, len(values)) for _, value := range values { - kv := strings.SplitN(value, "=", 2) - if len(kv) == 1 { - if defaultEnv { - v, ok := os.LookupEnv(kv[0]) - if ok { - result[kv[0]] = v - } - } else { - result[kv[0]] = "" + k, v, hasValue := strings.Cut(value, "=") + if k == "" { + return nil, errors.Errorf("invalid key-value pair %q: empty key", value) + } + if hasValue { + result[k] = v + } else if defaultEnv { + if envVal, ok := os.LookupEnv(k); ok { + result[k] = envVal } } else { - result[kv[0]] = kv[1] + result[k] = "" } } - return result + return result, nil } func dockerUlimitToControllerUlimit(u *dockeropts.UlimitOpt) *controllerapi.UlimitOpt { diff --git a/tests/build.go b/tests/build.go index 8c621b58..a5396512 100644 --- a/tests/build.go +++ b/tests/build.go @@ -42,6 +42,8 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildDetailsLink, testBuildProgress, testBuildAnnotations, + testBuildBuildArgNoKey, + testBuildLabelNoKey, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -358,3 +360,19 @@ func testBuildAnnotations(t *testing.T, sb integration.Sandbox) { require.NotNil(t, img.Desc) assert.Equal(t, "zzz", img.Desc.Annotations["example4"]) } + +func testBuildBuildArgNoKey(t *testing.T, sb integration.Sandbox) { + dir := createTestProject(t) + cmd := buildxCmd(sb, withArgs("build", "--build-arg", "=TEST_STRING", dir)) + out, err := cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.Equal(t, strings.TrimSpace(string(out)), `ERROR: invalid key-value pair "=TEST_STRING": empty key`) +} + +func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) { + dir := createTestProject(t) + cmd := buildxCmd(sb, withArgs("build", "--label", "=TEST_STRING", dir)) + out, err := cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.Equal(t, strings.TrimSpace(string(out)), `ERROR: invalid key-value pair "=TEST_STRING": empty key`) +}