Skip to content

Commit 10b547f

Browse files
committed
tests: run package tests in LLB graph
Move spec/package test execution out of the frontend's manual container-run path and into the normal LLB graph. The previous test runner solved the package build, then used the BuildKit API to run test containers and inspect filesystem state from outside the graph. That made the build less lazy, introduced extra solve behavior, and broke clients such as `docker buildx dap build` that expect the frontend solve to remain debuggable as a normal graph. This change represents test execution as BuildKit operations instead. The frontend binary is mounted into test containers and invoked through internal subcommands for filesystem checks. Each assertion is emitted as a separate exec op so failures can retain useful source mapping. Running tests this way keeps the test work attached to the build graph, lets BuildKit schedule and cache it normally, and avoids forcing package outputs to be materialized just so the frontend can run tests manually. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
1 parent 27c3d66 commit 10b547f

48 files changed

Lines changed: 3287 additions & 2998 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmd/frontend/git_credential_helper.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bufio"
55
"bytes"
6+
"context"
67
"encoding/base64"
78
"flag"
89
"fmt"
@@ -11,9 +12,18 @@ import (
1112
"path/filepath"
1213
"slices"
1314
"strings"
15+
16+
"github.com/project-dalec/dalec/internal/commands"
17+
"github.com/project-dalec/dalec/internal/plugins"
1418
)
1519

20+
func init() {
21+
commands.RegisterPlugin(credHelperSubcmd, plugins.CmdHandlerFunc(credentialHelperCmd))
22+
}
23+
1624
const (
25+
credHelperSubcmd = "credential-helper"
26+
1727
keyProtocol = "protocol"
1828
keyHost = "host"
1929
keyPath = "path"
@@ -72,7 +82,7 @@ type credConfig struct {
7282
kind string
7383
}
7484

75-
func gomodMain(args []string) {
85+
func credentialHelperCmd(ctx context.Context, args []string) {
7686
var cfg credConfig
7787
fs := flag.NewFlagSet(credHelperSubcmd, flag.ExitOnError)
7888
fs.Func("kind", "the kind of secret to retrieve (token or header)", readKind(&cfg.kind))

cmd/frontend/main.go

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
package main
22

33
import (
4+
"context"
45
_ "embed"
56
"flag"
67
"fmt"
78
"os"
9+
"path/filepath"
810

11+
"github.com/containerd/plugin"
912
"github.com/moby/buildkit/frontend/gateway/grpcclient"
1013
"github.com/moby/buildkit/util/appcontext"
1114
"github.com/moby/buildkit/util/bklog"
1215
"github.com/project-dalec/dalec/frontend"
1316
"github.com/project-dalec/dalec/internal/frontendapi"
14-
"github.com/project-dalec/dalec/internal/testrunner"
17+
"github.com/project-dalec/dalec/internal/plugins"
1518
"github.com/sirupsen/logrus"
1619
"google.golang.org/grpc/grpclog"
20+
21+
_ "github.com/project-dalec/dalec/internal/commands"
1722
)
1823

1924
const (
2025
Package = "github.com/project-dalec/dalec/cmd/frontend"
21-
22-
credHelperSubcmd = "credential-helper"
2326
)
2427

2528
func init() {
@@ -28,43 +31,62 @@ func init() {
2831
}
2932

3033
func main() {
31-
fs := flag.CommandLine
32-
fs.Usage = func() {
33-
fmt.Fprintf(os.Stderr, `usage: %s [subcommand [args...]]`, os.Args[0])
34-
}
34+
flags := flag.NewFlagSet(filepath.Base(os.Args[0]), flag.ExitOnError)
3535

36-
if err := fs.Parse(os.Args); err != nil {
36+
if err := flags.Parse(os.Args[1:]); err != nil {
3737
bklog.L.WithError(err).Fatal("error parsing frontend args")
3838
os.Exit(70) // 70 is EX_SOFTWARE, meaning internal software error occurred
39+
}
3940

41+
ctx := appcontext.Context()
42+
if flags.NArg() == 0 {
43+
dalecMain(ctx)
44+
return
4045
}
4146

42-
subCmd := fs.Arg(1)
43-
44-
// NOTE: for subcommands we take args[2:]
45-
// skip args[0] (the executable) and args[1] (the subcommand)
46-
47-
// each "sub-main" function handles its own exit
48-
switch subCmd {
49-
case credHelperSubcmd:
50-
args := flag.Args()[2:]
51-
gomodMain(args)
52-
case testrunner.StepRunnerCmdName:
53-
args := flag.Args()[2:]
54-
testrunner.StepCmd(args)
55-
case testrunner.CheckFilesCmdName:
56-
args := flag.Args()[2:]
57-
testrunner.CheckFilesCmd(args)
58-
case frontend.TestErrorCmdName:
59-
args := flag.Args()[2:]
60-
frontend.TestErrorCmd(args)
61-
default:
62-
dalecMain()
47+
h, err := lookupCmd(ctx, flags.Arg(0))
48+
if err != nil {
49+
bklog.L.WithError(err).Fatal("error handling command")
50+
os.Exit(70) // 70 is EX_SOFTWARE, meaning internal software error occurred
51+
}
52+
53+
if h == nil {
54+
fmt.Fprintln(os.Stderr, "unknown subcommand:", flags.Arg(1))
55+
fmt.Fprintln(os.Stderr, "full args:", flag.Args())
56+
fmt.Fprintln(os.Stderr, "If you see this message this is probably a bug in dalec.")
57+
os.Exit(64) // 64 is EX_USAGE, meaning command line usage error
6358
}
59+
60+
h.HandleCmd(ctx, flags.Args()[1:])
6461
}
6562

66-
func dalecMain() {
67-
ctx := appcontext.Context()
63+
func lookupCmd(ctx context.Context, cmd string) (plugins.CmdHandler, error) {
64+
set := plugin.NewPluginSet()
65+
filter := func(r *plugins.Registration) bool {
66+
return r.Type != plugins.TypeCmd || r.ID != cmd
67+
}
68+
69+
for _, r := range plugins.Graph(filter) {
70+
cfg := plugin.NewContext(ctx, set, nil)
71+
72+
p := r.Init(cfg)
73+
74+
v, err := p.Instance()
75+
if plugin.IsSkipPlugin(err) {
76+
continue
77+
}
78+
79+
if err != nil {
80+
return nil, err
81+
}
82+
83+
return v.(plugins.CmdHandler), nil
84+
}
85+
86+
return nil, nil
87+
}
88+
89+
func dalecMain(ctx context.Context) {
6890
mux, err := frontendapi.NewBuildRouter(ctx)
6991
if err != nil {
7092
bklog.L.WithError(err).Fatal("error creating frontend router")

frontend/build.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func LoadSpec(ctx context.Context, client *dockerui.Client, platform *ocispecs.P
5454
o(&cfg)
5555
}
5656

57-
src, err := client.ReadEntrypoint(ctx, "Dockerfile")
57+
src, err := client.ReadEntrypoint(ctx, "dalec")
5858
if err != nil {
5959
return nil, fmt.Errorf("could not read spec file: %w", err)
6060
}
@@ -218,26 +218,26 @@ func (c *clientWithPlatform) BuildOpts() gwclient.BuildOpts {
218218
return opts
219219
}
220220

221-
func GetCurrentFrontend(client gwclient.Client) (llb.State, error) {
221+
func GetCurrentFrontend(client gwclient.Client) llb.State {
222+
return *getCurrentFrontend(client)
223+
}
224+
225+
func getCurrentFrontend(client gwclient.Client) *llb.State {
222226
f, err := client.(frontendClient).CurrentFrontend()
223227
if err != nil {
224-
return llb.Scratch(), err
228+
panic(err)
225229
}
226230

227231
if f == nil {
228-
return llb.Scratch(), fmt.Errorf("nil frontend state returned")
232+
panic("nil frontend state returned -- this should never happen")
229233
}
230234

231-
return *f, nil
235+
return f
232236
}
233237

234238
func withCredHelper(c gwclient.Client) func() (llb.RunOption, error) {
235239
return func() (llb.RunOption, error) {
236-
f, err := GetCurrentFrontend(c)
237-
if err != nil {
238-
return nil, err
239-
}
240-
240+
f := GetCurrentFrontend(c)
241241
return dalec.RunOptFunc(func(ei *llb.ExecInfo) {
242242
llb.AddMount("/usr/local/bin/frontend", f, llb.SourcePath("/frontend")).SetRunOption(ei)
243243
}), nil

frontend/request.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func MaybeSign(ctx context.Context, client gwclient.Client, st llb.State, spec *
203203
Warnf(ctx, client, st, "Spec signing config overwritten by config at path %q in build-context %q", cfgPath, configCtxName)
204204
}
205205

206-
cfg, err := getSigningConfigFromContext(ctx, client, cfgPath, configCtxName, sOpt)
206+
cfg, err := getSigningConfigFromContext(ctx, client, cfgPath, configCtxName, sOpt, opts...)
207207
if err != nil {
208208
return dalec.ErrorState(llb.Scratch(), err)
209209
}

0 commit comments

Comments
 (0)