Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ require (
github.com/hashicorp/go-cty-funcs v0.0.0-20250818135842-6aab67130928
github.com/hashicorp/hcl/v2 v2.24.0
github.com/in-toto/in-toto-golang v0.11.0
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/moby/buildkit v0.33.0
github.com/moby/moby/api v1.55.0
github.com/moby/moby/client v0.5.0
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,6 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.33.0 h1:zBbt1FiMcTB/oFg1iCNcKa83k5Rn8MGcVjXFIcfYhuQ=
Expand Down
45 changes: 28 additions & 17 deletions util/progress/printer.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package progress

import (
"bytes"
"context"
"io"
"os"
"slices"
"sync"

"github.com/docker/buildx/util/logutil"
"github.com/mitchellh/hashstructure/v2"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/opencontainers/go-digest"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"google.golang.org/protobuf/proto"
)

type printerState int
Expand Down Expand Up @@ -295,28 +298,36 @@ func WithOnClose(onclose func()) PrinterOpt {
}

func dedupWarnings(inp []client.VertexWarning) []client.VertexWarning {
m := make(map[uint64]client.VertexWarning)
res := make([]client.VertexWarning, 0, len(inp))
for _, w := range inp {
wcp := w
wcp.Vertex = ""
if wcp.SourceInfo != nil {
wcp.SourceInfo.Definition = nil
if !slices.ContainsFunc(res, func(prev client.VertexWarning) bool {
return equalWarnings(prev, w)
}) {
res = append(res, w)
}
h, err := hashstructure.Hash(wcp, hashstructure.FormatV2, nil)
if err != nil {
continue
}
if _, ok := m[h]; !ok {
m[h] = w
}
}
res := make([]client.VertexWarning, 0, len(m))
for _, w := range m {
res = append(res, w)
}
return res
}

// equalWarnings ignores the vertex and source definition, which can differ
// between otherwise identical warnings from separate builds.
func equalWarnings(a, b client.VertexWarning) bool {
if a.Level != b.Level || a.URL != b.URL || !bytes.Equal(a.Short, b.Short) ||
!slices.EqualFunc(a.Detail, b.Detail, bytes.Equal) {
return false
}
if (a.SourceInfo == nil) != (b.SourceInfo == nil) {
return false
}
if a.SourceInfo != nil && (a.SourceInfo.Filename != b.SourceInfo.Filename ||
a.SourceInfo.Language != b.SourceInfo.Language || !bytes.Equal(a.SourceInfo.Data, b.SourceInfo.Data)) {
return false
}
return slices.EqualFunc(a.Range, b.Range, func(a, b *pb.Range) bool {
return proto.Equal(a, b)
})
}

type interruptRequest struct {
desiredState printerState
done chan<- struct{}
Expand Down
69 changes: 69 additions & 0 deletions util/progress/printer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package progress

import (
"testing"

"github.com/moby/buildkit/client"
"github.com/moby/buildkit/solver/pb"
"github.com/stretchr/testify/require"
)

func TestDedupWarnings(t *testing.T) {
newWarning := func() client.VertexWarning {
return client.VertexWarning{
Vertex: "first",
Level: 1,
Short: []byte("warning"),
Detail: [][]byte{[]byte("detail"), []byte("more detail")},
URL: "https://example.com",
SourceInfo: &pb.SourceInfo{
Filename: "Dockerfile",
Language: "dockerfile",
Data: []byte("FROM scratch"),
Definition: &pb.Definition{Def: [][]byte{[]byte("definition")}},
},
Range: []*pb.Range{{Start: &pb.Position{Line: 1}, End: &pb.Position{Line: 2}}},
}
}

t.Run("duplicates preserve first warning and inputs", func(t *testing.T) {
first, second := newWarning(), newWarning()
second.Vertex = "second"
second.SourceInfo.Definition = &pb.Definition{Def: [][]byte{[]byte("other definition")}}
got := dedupWarnings([]client.VertexWarning{first, second, first})
require.Len(t, got, 1)
require.Equal(t, first, got[0])
require.Equal(t, [][]byte{[]byte("definition")}, first.SourceInfo.Definition.Def)
require.Equal(t, [][]byte{[]byte("other definition")}, second.SourceInfo.Definition.Def)
})

for _, tc := range []struct {
name string
change func(*client.VertexWarning)
}{
{"level", func(w *client.VertexWarning) { w.Level++ }},
{"short", func(w *client.VertexWarning) { w.Short[0]++ }},
{"detail", func(w *client.VertexWarning) { w.Detail[0][0]++ }},
{"detail order", func(w *client.VertexWarning) { w.Detail[0], w.Detail[1] = w.Detail[1], w.Detail[0] }},
{"url", func(w *client.VertexWarning) { w.URL += "/other" }},
{"filename", func(w *client.VertexWarning) { w.SourceInfo.Filename += ".other" }},
{"language", func(w *client.VertexWarning) { w.SourceInfo.Language = "other" }},
{"source data", func(w *client.VertexWarning) { w.SourceInfo.Data[0]++ }},
{"missing source", func(w *client.VertexWarning) { w.SourceInfo = nil }},
{"range start", func(w *client.VertexWarning) { w.Range[0].Start.Line++ }},
{"range end", func(w *client.VertexWarning) { w.Range[0].End.Character++ }},
{"missing range", func(w *client.VertexWarning) { w.Range = nil }},
} {
t.Run(tc.name, func(t *testing.T) {
first, second := newWarning(), newWarning()
tc.change(&second)
require.Equal(t, []client.VertexWarning{first, second}, dedupWarnings([]client.VertexWarning{first, second, first}))
})
}

t.Run("empty values", func(t *testing.T) {
require.Empty(t, dedupWarnings(nil))
require.Len(t, dedupWarnings([]client.VertexWarning{{}, {Short: []byte{}, Detail: [][]byte{}, Range: []*pb.Range{}}}), 1)
require.Len(t, dedupWarnings([]client.VertexWarning{{}, {SourceInfo: &pb.SourceInfo{}}}), 2)
})
}
21 changes: 0 additions & 21 deletions vendor/github.com/mitchellh/hashstructure/v2/LICENSE

This file was deleted.

76 changes: 0 additions & 76 deletions vendor/github.com/mitchellh/hashstructure/v2/README.md

This file was deleted.

22 changes: 0 additions & 22 deletions vendor/github.com/mitchellh/hashstructure/v2/errors.go

This file was deleted.

Loading
Loading