Skip to content

Commit 5245d50

Browse files
committed
tests: history finalize on multi-node
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
1 parent c4e9dfc commit 5245d50

File tree

1 file changed

+97
-85
lines changed

1 file changed

+97
-85
lines changed

tests/history.go

Lines changed: 97 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
var historyTests = []func(t *testing.T, sb integration.Sandbox){
2020
testHistoryExport,
2121
testHistoryExportFinalize,
22+
testHistoryExportFinalizeMultiNodeRef,
23+
testHistoryExportFinalizeMultiNodeAll,
2224
testHistoryInspect,
2325
testHistoryLs,
2426
testHistoryRm,
@@ -29,21 +31,55 @@ var historyTests = []func(t *testing.T, sb integration.Sandbox){
2931
func testHistoryExport(t *testing.T, sb integration.Sandbox) {
3032
ref := buildTestProject(t, sb)
3133
require.NotEmpty(t, ref.Ref)
34+
requireHistoryRef(t, sb, ref.Ref)
3235

3336
outFile := path.Join(t.TempDir(), "export.dockerbuild")
3437
cmd := buildxCmd(sb, withArgs("history", "export", ref.Ref, "--output", outFile))
35-
out, err := cmd.Output()
38+
out, err := cmd.CombinedOutput()
3639
require.NoError(t, err, string(out))
3740
require.FileExists(t, outFile)
3841
}
3942

4043
func testHistoryExportFinalize(t *testing.T, sb integration.Sandbox) {
4144
ref := buildTestProject(t, sb)
4245
require.NotEmpty(t, ref.Ref)
46+
requireHistoryRef(t, sb, ref.Ref)
4347

4448
outFile := path.Join(t.TempDir(), "export.dockerbuild")
4549
cmd := buildxCmd(sb, withArgs("history", "export", ref.Ref, "--finalize", "--output", outFile))
46-
out, err := cmd.Output()
50+
out, err := cmd.CombinedOutput()
51+
require.NoError(t, err, string(out))
52+
require.FileExists(t, outFile)
53+
}
54+
55+
func testHistoryExportFinalizeMultiNodeRef(t *testing.T, sb integration.Sandbox) {
56+
if !isRemoteMultiNodeWorker(sb) {
57+
t.Skip("only testing with remote multi-node worker")
58+
}
59+
60+
ref := buildTestProject(t, sb, withArgs("--platform=linux/amd64,linux/arm64", "--output=type=cacheonly"))
61+
require.NotEmpty(t, ref.Ref)
62+
requireHistoryRef(t, sb, ref.Ref)
63+
64+
outFile := path.Join(t.TempDir(), "export.dockerbuild")
65+
cmd := buildxCmd(sb, withArgs("history", "export", ref.Ref, "--finalize", "--output", outFile))
66+
out, err := cmd.CombinedOutput()
67+
require.NoError(t, err, string(out))
68+
require.FileExists(t, outFile)
69+
}
70+
71+
func testHistoryExportFinalizeMultiNodeAll(t *testing.T, sb integration.Sandbox) {
72+
if !isRemoteMultiNodeWorker(sb) {
73+
t.Skip("only testing with remote multi-node worker")
74+
}
75+
76+
ref := buildTestProject(t, sb, withArgs("--platform=linux/amd64,linux/arm64", "--output=type=cacheonly"))
77+
require.NotEmpty(t, ref.Ref)
78+
requireHistoryRef(t, sb, ref.Ref)
79+
80+
outFile := path.Join(t.TempDir(), "export.dockerbuild")
81+
cmd := buildxCmd(sb, withArgs("history", "export", "--finalize", "--all", "--output", outFile))
82+
out, err := cmd.CombinedOutput()
4783
require.NoError(t, err, string(out))
4884
require.FileExists(t, outFile)
4985
}
@@ -53,7 +89,7 @@ func testHistoryInspect(t *testing.T, sb integration.Sandbox) {
5389
require.NotEmpty(t, ref.Ref)
5490

5591
cmd := buildxCmd(sb, withArgs("history", "inspect", ref.Ref, "--format=json"))
56-
out, err := cmd.Output()
92+
out, err := cmd.CombinedOutput()
5793
require.NoError(t, err, string(out))
5894

5995
type recT struct {
@@ -77,31 +113,10 @@ func testHistoryInspect(t *testing.T, sb integration.Sandbox) {
77113
}
78114

79115
func testHistoryLs(t *testing.T, sb integration.Sandbox) {
80-
if isRemoteMultiNodeWorker(sb) {
81-
// FIXME: "history ls" fails on multi nodes
82-
t.Skip("fails with multi nodes")
83-
}
84-
85116
ref := buildTestProject(t, sb)
86117
require.NotEmpty(t, ref.Ref)
87118

88-
cmd := buildxCmd(sb, withArgs("history", "ls", "--filter=ref="+ref.Ref, "--format=json"))
89-
out, err := cmd.Output()
90-
require.NoError(t, err, string(out))
91-
92-
type recT struct {
93-
Ref string `json:"ref"`
94-
Name string `json:"name"`
95-
Status string `json:"status"`
96-
CreatedAt *time.Time `json:"created_at"`
97-
CompletedAt *time.Time `json:"completed_at"`
98-
TotalSteps int32 `json:"total_steps"`
99-
CompletedSteps int32 `json:"completed_steps"`
100-
CachedSteps int32 `json:"cached_steps"`
101-
}
102-
var rec recT
103-
err = json.Unmarshal(out, &rec)
104-
require.NoError(t, err)
119+
rec := requireHistoryRecord(t, sb, ref.String())
105120
require.Equal(t, ref.String(), rec.Ref)
106121
require.NotEmpty(t, rec.Name)
107122
}
@@ -146,15 +161,10 @@ func testHistoryLsStoppedBuilder(t *testing.T, sb integration.Sandbox) {
146161
}
147162

148163
func testHistoryBuildName(t *testing.T, sb integration.Sandbox) {
149-
if isRemoteMultiNodeWorker(sb) {
150-
// FIXME: "history ls" fails on multi nodes
151-
t.Skip("fails with multi nodes")
152-
}
153-
154164
t.Run("override", func(t *testing.T) {
155165
dir := createTestProject(t)
156166
out, err := buildCmd(sb, withArgs("--build-arg=BUILDKIT_BUILD_NAME=foobar", "--metadata-file", filepath.Join(dir, "md.json"), dir))
157-
require.NoError(t, err, string(out))
167+
require.NoError(t, err, out)
158168

159169
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
160170
require.NoError(t, err)
@@ -169,23 +179,7 @@ func testHistoryBuildName(t *testing.T, sb integration.Sandbox) {
169179
refParts := strings.Split(md.BuildRef, "/")
170180
require.Len(t, refParts, 3)
171181

172-
cmd := buildxCmd(sb, withArgs("history", "ls", "--filter=ref="+refParts[2], "--format=json"))
173-
bout, err := cmd.Output()
174-
require.NoError(t, err, string(bout))
175-
176-
type recT struct {
177-
Ref string `json:"ref"`
178-
Name string `json:"name"`
179-
Status string `json:"status"`
180-
CreatedAt *time.Time `json:"created_at"`
181-
CompletedAt *time.Time `json:"completed_at"`
182-
TotalSteps int32 `json:"total_steps"`
183-
CompletedSteps int32 `json:"completed_steps"`
184-
CachedSteps int32 `json:"cached_steps"`
185-
}
186-
var rec recT
187-
err = json.Unmarshal(bout, &rec)
188-
require.NoError(t, err)
182+
rec := requireHistoryRecord(t, sb, md.BuildRef)
189183
require.Equal(t, md.BuildRef, rec.Ref)
190184
require.Equal(t, "foobar", rec.Name)
191185
})
@@ -230,23 +224,7 @@ COPY foo /foo
230224
refParts := strings.Split(md.BuildRef, "/")
231225
require.Len(t, refParts, 3)
232226

233-
cmd := buildxCmd(sb, withArgs("history", "ls", "--filter=ref="+refParts[2], "--format=json"))
234-
bout, err := cmd.Output()
235-
require.NoError(t, err, string(bout))
236-
237-
type recT struct {
238-
Ref string `json:"ref"`
239-
Name string `json:"name"`
240-
Status string `json:"status"`
241-
CreatedAt *time.Time `json:"created_at"`
242-
CompletedAt *time.Time `json:"completed_at"`
243-
TotalSteps int32 `json:"total_steps"`
244-
CompletedSteps int32 `json:"completed_steps"`
245-
CachedSteps int32 `json:"cached_steps"`
246-
}
247-
var rec recT
248-
err = json.Unmarshal(bout, &rec)
249-
require.NoError(t, err)
227+
rec := requireHistoryRecord(t, sb, md.BuildRef)
250228
require.Equal(t, md.BuildRef, rec.Ref)
251229
require.Equal(t, addr+"#main", rec.Name)
252230
})
@@ -296,23 +274,7 @@ EOT
296274
refParts := strings.Split(md.Default.BuildRef, "/")
297275
require.Len(t, refParts, 3)
298276

299-
cmd := buildxCmd(sb, withArgs("history", "ls", "--filter=ref="+refParts[2], "--format=json"))
300-
bout, err := cmd.Output()
301-
require.NoError(t, err, string(bout))
302-
303-
type recT struct {
304-
Ref string `json:"ref"`
305-
Name string `json:"name"`
306-
Status string `json:"status"`
307-
CreatedAt *time.Time `json:"created_at"`
308-
CompletedAt *time.Time `json:"completed_at"`
309-
TotalSteps int32 `json:"total_steps"`
310-
CompletedSteps int32 `json:"completed_steps"`
311-
CachedSteps int32 `json:"cached_steps"`
312-
}
313-
var rec recT
314-
err = json.Unmarshal(bout, &rec)
315-
require.NoError(t, err)
277+
rec := requireHistoryRecord(t, sb, md.Default.BuildRef)
316278
require.Equal(t, md.Default.BuildRef, rec.Ref)
317279
require.Equal(t, addr, rec.Name)
318280
})
@@ -328,10 +290,11 @@ func (b buildRef) String() string {
328290
return b.Builder + "/" + b.Node + "/" + b.Ref
329291
}
330292

331-
func buildTestProject(t *testing.T, sb integration.Sandbox) buildRef {
293+
func buildTestProject(t *testing.T, sb integration.Sandbox, opts ...cmdOpt) buildRef {
332294
dir := createTestProject(t)
333-
out, err := buildCmd(sb, withArgs("--metadata-file", filepath.Join(dir, "md.json"), dir))
334-
require.NoError(t, err, string(out))
295+
opts = append(opts, withArgs("--metadata-file", filepath.Join(dir, "md.json"), dir))
296+
out, err := buildCmd(sb, opts...)
297+
require.NoError(t, err, out)
335298

336299
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
337300
require.NoError(t, err)
@@ -352,3 +315,52 @@ func buildTestProject(t *testing.T, sb integration.Sandbox) buildRef {
352315
Ref: refParts[2],
353316
}
354317
}
318+
319+
func requireHistoryRef(t *testing.T, sb integration.Sandbox, ref string) {
320+
cmd := buildxCmd(sb, withArgs("history", "ls", "--format={{.Ref}}"))
321+
out, err := cmd.CombinedOutput()
322+
require.NoError(t, err, string(out))
323+
var matches int
324+
for line := range strings.SplitSeq(strings.TrimSpace(string(out)), "\n") {
325+
if strings.TrimSpace(line) == ref {
326+
matches++
327+
}
328+
}
329+
require.GreaterOrEqual(t, matches, 1)
330+
}
331+
332+
type historyLsRecord struct {
333+
Ref string `json:"ref"`
334+
Name string `json:"name"`
335+
Status string `json:"status"`
336+
CreatedAt *time.Time `json:"created_at"`
337+
CompletedAt *time.Time `json:"completed_at"`
338+
TotalSteps int32 `json:"total_steps"`
339+
CompletedSteps int32 `json:"completed_steps"`
340+
CachedSteps int32 `json:"cached_steps"`
341+
}
342+
343+
func requireHistoryRecord(t *testing.T, sb integration.Sandbox, ref string, opts ...cmdOpt) historyLsRecord {
344+
cmd := buildxCmd(sb, append(opts, withArgs("history", "ls", "--format=json"))...)
345+
out, err := cmd.CombinedOutput()
346+
require.NoError(t, err, string(out))
347+
348+
for line := range strings.SplitSeq(strings.TrimSpace(string(out)), "\n") {
349+
line = strings.TrimSpace(line)
350+
if line == "" {
351+
continue
352+
}
353+
if !strings.HasPrefix(line, "{") {
354+
continue
355+
}
356+
var rec historyLsRecord
357+
err := json.Unmarshal([]byte(line), &rec)
358+
require.NoError(t, err)
359+
if rec.Ref == ref {
360+
return rec
361+
}
362+
}
363+
364+
require.Failf(t, "history record not found", "ref %q was not found in history ls output:\n%s", ref, string(out))
365+
return historyLsRecord{}
366+
}

0 commit comments

Comments
 (0)