Skip to content

Commit

Permalink
fix builkit progressui integration
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
  • Loading branch information
ndeloof committed May 5, 2023
1 parent 5fdcaa0 commit 7434610
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 42 deletions.
15 changes: 13 additions & 2 deletions pkg/compose/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package compose
import (
"context"
"fmt"
"os"
"path/filepath"

"github.com/compose-spec/compose-go/types"
Expand Down Expand Up @@ -60,6 +61,17 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
if err != nil {
return nil, err
}

// Progress needs its own context that lives longer than the
// build one otherwise it won't read all the messages from
// build and will lock
progressCtx, cancel := context.WithCancel(context.Background())
defer cancel()
w, err := xprogress.NewPrinter(progressCtx, s.stdout(), os.Stdout, options.Progress)
if err != nil {
return nil, err
}

builtIDs := make([]string, len(project.Services))
err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
Expand Down Expand Up @@ -101,9 +113,8 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
return err
}
buildOptions.BuildArgs = mergeArgs(buildOptions.BuildArgs, flatten(args))
opts := map[string]build.Options{service.Name: buildOptions}

ids, err := s.doBuildBuildkit(ctx, opts, options.Progress)
ids, err := s.doBuildBuildkit(ctx, service.Name, buildOptions, w)
if err != nil {
return err
}
Expand Down
64 changes: 24 additions & 40 deletions pkg/compose/build_buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,22 @@ import (
"context"
"crypto/sha1"
"fmt"
"os"
"path/filepath"

_ "github.com/docker/buildx/driver/docker" //nolint:blank-imports
_ "github.com/docker/buildx/driver/docker-container" //nolint:blank-imports
_ "github.com/docker/buildx/driver/kubernetes" //nolint:blank-imports
_ "github.com/docker/buildx/driver/remote" //nolint:blank-imports
buildx "github.com/docker/buildx/util/progress"
"github.com/moby/buildkit/client"

"github.com/docker/buildx/build"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/util/dockerutil"
xprogress "github.com/docker/buildx/util/progress"
"github.com/docker/compose/v2/pkg/progress"
)

func (s *composeService) doBuildBuildkit(ctx context.Context, opts map[string]build.Options, mode string) (map[string]string, error) {
func (s *composeService) doBuildBuildkit(ctx context.Context, service string, opts build.Options, p *buildx.Printer) (map[string]string, error) {
b, err := builder.New(s.dockerCli)
if err != nil {
return nil, err
Expand All @@ -49,22 +48,9 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, opts map[string]bu

var response map[string]*client.SolveResponse
if s.dryRun {
response = s.dryRunBuildResponse(ctx, opts)
response = s.dryRunBuildResponse(ctx, service, opts)
} else {
// Progress needs its own context that lives longer than the
// build one otherwise it won't read all the messages from
// build and will lock
progressCtx, cancel := context.WithCancel(context.Background())
defer cancel()
w, err := xprogress.NewPrinter(progressCtx, s.stdout(), os.Stdout, mode)
if err != nil {
return nil, err
}
response, err = build.Build(ctx, nodes, opts, dockerutil.NewClient(s.dockerCli), filepath.Dir(s.configFile().Filename), w)
errW := w.Wait()
if err == nil {
err = errW
}
response, err = build.Build(ctx, nodes, map[string]build.Options{service: opts}, dockerutil.NewClient(s.dockerCli), filepath.Dir(s.configFile().Filename), buildx.WithPrefix(p, "", true))
if err != nil {
return nil, WrapCategorisedComposeError(err, BuildFailure)
}
Expand All @@ -85,29 +71,27 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, opts map[string]bu
return imagesBuilt, err
}

func (s composeService) dryRunBuildResponse(ctx context.Context, options map[string]build.Options) map[string]*client.SolveResponse {
func (s composeService) dryRunBuildResponse(ctx context.Context, name string, options build.Options) map[string]*client.SolveResponse {
w := progress.ContextWriter(ctx)
buildResponse := map[string]*client.SolveResponse{}
for name, option := range options {
dryRunUUID := fmt.Sprintf("dryRun-%x", sha1.Sum([]byte(name)))
w.Event(progress.Event{
ID: " ",
Status: progress.Done,
Text: fmt.Sprintf("build service %s", name),
})
w.Event(progress.Event{
ID: "==>",
Status: progress.Done,
Text: fmt.Sprintf("==> writing image %s", dryRunUUID),
})
w.Event(progress.Event{
ID: "==> ==>",
Status: progress.Done,
Text: fmt.Sprintf(`naming to %s`, option.Tags[0]),
})
buildResponse[name] = &client.SolveResponse{ExporterResponse: map[string]string{
"containerimage.digest": dryRunUUID,
}}
}
dryRunUUID := fmt.Sprintf("dryRun-%x", sha1.Sum([]byte(name)))
w.Event(progress.Event{
ID: " ",
Status: progress.Done,
Text: fmt.Sprintf("build service %s", name),
})
w.Event(progress.Event{
ID: "==>",
Status: progress.Done,
Text: fmt.Sprintf("==> writing image %s", dryRunUUID),
})
w.Event(progress.Event{
ID: "==> ==>",
Status: progress.Done,
Text: fmt.Sprintf(`naming to %s`, options.Tags[0]),
})
buildResponse[name] = &client.SolveResponse{ExporterResponse: map[string]string{
"containerimage.digest": dryRunUUID,
}}
return buildResponse
}

0 comments on commit 7434610

Please sign in to comment.