Skip to content

Commit 19bd077

Browse files
committed
bake: keep escaped interpolation in print output
Signed-off-by: CrazyMax <[email protected]>
1 parent 98c3abb commit 19bd077

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

bake/bake.go

+36
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package bake
33
import (
44
"context"
55
"encoding"
6+
"encoding/json"
67
"io"
78
"maps"
89
"os"
@@ -733,6 +734,41 @@ type Target struct {
733734
linked bool
734735
}
735736

737+
func (t *Target) MarshalJSON() ([]byte, error) {
738+
tgt := *t
739+
esc := func(s string) string {
740+
return strings.ReplaceAll(strings.ReplaceAll(s, "${", "$${"), "%{", "%%{")
741+
}
742+
743+
tgt.Annotations = slices.Clone(t.Annotations)
744+
for i, v := range tgt.Annotations {
745+
tgt.Annotations[i] = esc(v)
746+
}
747+
748+
if tgt.DockerfileInline != nil {
749+
escaped := esc(*tgt.DockerfileInline)
750+
tgt.DockerfileInline = &escaped
751+
}
752+
753+
tgt.Labels = make(map[string]*string, len(t.Labels))
754+
for k, v := range t.Labels {
755+
if v != nil {
756+
escaped := esc(*v)
757+
tgt.Labels[k] = &escaped
758+
}
759+
}
760+
761+
tgt.Args = make(map[string]*string, len(t.Args))
762+
for k, v := range t.Args {
763+
if v != nil {
764+
escaped := esc(*v)
765+
tgt.Args[k] = &escaped
766+
}
767+
}
768+
769+
return json.Marshal(tgt)
770+
}
771+
736772
var (
737773
_ hclparser.WithEvalContexts = &Target{}
738774
_ hclparser.WithGetName = &Target{}

tests/bake.go

+61
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
4040
testBakePrint,
4141
testBakePrintSensitive,
4242
testBakePrintOverrideEmpty,
43+
testBakePrintKeepEscaped,
4344
testBakeLocal,
4445
testBakeLocalMulti,
4546
testBakeRemote,
@@ -329,6 +330,66 @@ target "default" {
329330
}`, stdout.String())
330331
}
331332

333+
func testBakePrintKeepEscaped(t *testing.T, sb integration.Sandbox) {
334+
bakefile := []byte(`
335+
target "default" {
336+
dockerfile-inline = <<EOT
337+
ARG VERSION=latest
338+
FROM alpine:$${VERSION}
339+
EOT
340+
args = {
341+
VERSION = "3.21"
342+
}
343+
annotations = [
344+
"org.opencontainers.image.authors=$${user}"
345+
]
346+
labels = {
347+
foo = "hello %%{bar}"
348+
}
349+
}
350+
`)
351+
352+
dir := tmpdir(t, fstest.CreateFile("docker-bake.hcl", bakefile, 0600))
353+
cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--print"))
354+
stdout := bytes.Buffer{}
355+
stderr := bytes.Buffer{}
356+
cmd.Stdout = &stdout
357+
cmd.Stderr = &stderr
358+
require.NoError(t, cmd.Run(), stdout.String(), stderr.String())
359+
360+
require.JSONEq(t, `{
361+
"group": {
362+
"default": {
363+
"targets": [
364+
"default"
365+
]
366+
}
367+
},
368+
"target": {
369+
"default": {
370+
"annotations": [
371+
"org.opencontainers.image.authors=$${user}"
372+
],
373+
"context": ".",
374+
"dockerfile": "Dockerfile",
375+
"dockerfile-inline": "ARG VERSION=latest\nFROM alpine:$${VERSION}\n",
376+
"args": {
377+
"VERSION": "3.21"
378+
},
379+
"labels": {
380+
"foo": "hello %%{bar}"
381+
}
382+
}
383+
}
384+
}`, stdout.String())
385+
386+
// test build with definition from print output
387+
dir = tmpdir(t, fstest.CreateFile("docker-bake.json", stdout.Bytes(), 0600))
388+
cmd = buildxCmd(sb, withDir(dir), withArgs("bake"))
389+
out, err := cmd.CombinedOutput()
390+
require.NoError(t, err, string(out))
391+
}
392+
332393
func testBakeLocal(t *testing.T, sb integration.Sandbox) {
333394
dockerfile := []byte(`
334395
FROM scratch

0 commit comments

Comments
 (0)