Skip to content

Commit 14d407b

Browse files
committed
verifier: do not run invalid platforms check when there are no results
When `--call=lint` or `--call=outline` were used, the intention wasn't to run this check because the result doesn't have a platform. When those checks are run, there is no exporter platforms key. We would check `Request` from the request operations, but this wasn't a reliable way to determine whether the result was from a lint because it is possible for subrequests to have different frontend attributes than the primary request and the primary request would sometimes not have the `requestid` attribute set. Instead of detecting a subrequest with that method, the check has been updated to exit if there are no references and if there is no exporter key. Signed-off-by: Jonathan A. Sternberg <[email protected]>
1 parent 2f7007e commit 14d407b

File tree

3 files changed

+70
-7
lines changed

3 files changed

+70
-7
lines changed

client/client_test.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){
218218
testOCIIndexMediatype,
219219
testLayerLimitOnMounts,
220220
testFrontendVerifyPlatforms,
221+
testFrontendLintSkipVerifyPlatforms,
221222
testRunValidExitCodes,
222223
testFileOpSymlink,
223224
}
@@ -10414,6 +10415,52 @@ func testFrontendVerifyPlatforms(t *testing.T, sb integration.Sandbox) {
1041410415
require.Contains(t, string(warnings[0].Short), "do not match result platforms linux/amd64,linux/arm64")
1041510416
}
1041610417

10418+
func testFrontendLintSkipVerifyPlatforms(t *testing.T, sb integration.Sandbox) {
10419+
c, err := New(sb.Context(), sb.Address())
10420+
require.NoError(t, err)
10421+
defer c.Close()
10422+
10423+
frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
10424+
dockerfile := `
10425+
FROM scratch
10426+
COPY foo /foo
10427+
`
10428+
st := llb.Scratch().File(
10429+
llb.Mkfile("Dockerfile", 0600, []byte(dockerfile)).
10430+
Mkfile("foo", 0600, []byte("data")))
10431+
10432+
def, err := st.Marshal(sb.Context())
10433+
if err != nil {
10434+
return nil, err
10435+
}
10436+
10437+
return c.Solve(ctx, gateway.SolveRequest{
10438+
FrontendInputs: map[string]*pb.Definition{
10439+
"context": def.ToPB(),
10440+
"dockerfile": def.ToPB(),
10441+
},
10442+
FrontendOpt: map[string]string{
10443+
"requestid": "frontend.lint",
10444+
"frontend.caps": "moby.buildkit.frontend.subrequests",
10445+
},
10446+
})
10447+
}
10448+
10449+
wc := newWarningsCapture()
10450+
_, err = c.Build(sb.Context(), SolveOpt{
10451+
FrontendAttrs: map[string]string{
10452+
"platform": "linux/amd64,linux/arm64",
10453+
},
10454+
}, "", frontend, wc.status)
10455+
require.NoError(t, err)
10456+
warnings := wc.wait()
10457+
10458+
for _, w := range warnings {
10459+
t.Logf("warning: %s", string(w.Short))
10460+
}
10461+
require.Len(t, warnings, 0)
10462+
}
10463+
1041710464
type warningsCapture struct {
1041810465
status chan *SolveStatus
1041910466
statusDone chan struct{}
@@ -10876,7 +10923,8 @@ func testClientCustomGRPCOpts(t *testing.T, sb integration.Sandbox) {
1087610923
reply interface{},
1087710924
cc *grpc.ClientConn,
1087810925
invoker grpc.UnaryInvoker,
10879-
opts ...grpc.CallOption) error {
10926+
opts ...grpc.CallOption,
10927+
) error {
1088010928
interceptedMethods = append(interceptedMethods, method)
1088110929
return invoker(ctx, method, req, reply, cc, opts...)
1088210930
}

exporter/verifier/platforms.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ func CheckInvalidPlatforms[T comparable](ctx context.Context, res *result.Result
1919
return nil, err
2020
}
2121

22-
if req.Request != "" {
23-
return nil, nil
24-
}
25-
26-
if _, ok := res.Metadata[exptypes.ExporterPlatformsKey]; len(res.Refs) > 0 && !ok {
27-
return nil, errors.Errorf("build result contains multiple refs without platforms mapping")
22+
if _, ok := res.Metadata[exptypes.ExporterPlatformsKey]; !ok {
23+
if len(res.Refs) > 0 {
24+
return nil, errors.Errorf("build result contains multiple refs without platforms mapping")
25+
} else if res.IsEmpty() {
26+
// No results and no exporter key. Don't run this check.
27+
return nil, nil
28+
}
2829
}
2930

3031
isMap := len(res.Refs) > 0

solver/result/result.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ func (r *Result[T]) EachRef(fn func(T) error) (err error) {
110110
return err
111111
}
112112

113+
// IsEmpty returns true if this result does not refer to
114+
// any references.
115+
func (r *Result[T]) IsEmpty() bool {
116+
r.mu.Lock()
117+
defer r.mu.Unlock()
118+
119+
if len(r.Refs) > 0 {
120+
return false
121+
}
122+
123+
var zero T
124+
return r.Ref == zero
125+
}
126+
113127
// EachRef iterates over references in both a and b.
114128
// a and b are assumed to be of the same size and map their references
115129
// to the same set of keys

0 commit comments

Comments
 (0)