Merge pull request #3152 from crazy-max/history-export-finalize

history: make sure build record is finalized before exporting
This commit is contained in:
Tõnis Tiigi
2025-05-13 14:20:04 -07:00
committed by GitHub
6 changed files with 209 additions and 20 deletions
+27 -5
View File
@@ -20,10 +20,11 @@ import (
)
type exportOptions struct {
builder string
refs []string
output string
all bool
builder string
refs []string
output string
all bool
finalize bool
}
func runExport(ctx context.Context, dockerCli command.Cli, opts exportOptions) error {
@@ -62,6 +63,26 @@ func runExport(ctx context.Context, dockerCli command.Cli, opts exportOptions) e
return errors.Errorf("no record found for ref %q", ref)
}
if opts.finalize {
var finalized bool
for _, rec := range recs {
if rec.Trace == nil {
finalized = true
if err := finalizeRecord(ctx, rec.Ref, nodes); err != nil {
return err
}
}
}
if finalized {
recs, err = queryRecords(ctx, ref, nodes, &queryOptions{
CompletedOnly: true,
})
if err != nil {
return err
}
}
}
if ref == "" {
slices.SortFunc(recs, func(a, b historyRecord) int {
return b.CreatedAt.AsTime().Compare(a.CreatedAt.AsTime())
@@ -154,7 +175,8 @@ func exportCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
flags := cmd.Flags()
flags.StringVarP(&options.output, "output", "o", "", "Output file path")
flags.BoolVar(&options.all, "all", false, "Export all records for the builder")
flags.BoolVar(&options.all, "all", false, "Export all build records for the builder")
flags.BoolVar(&options.finalize, "finalize", false, "Ensure build records are finalized before exporting")
return cmd
}
+1 -9
View File
@@ -17,7 +17,6 @@ import (
"github.com/docker/buildx/util/otelutil"
"github.com/docker/buildx/util/otelutil/jaeger"
"github.com/docker/cli/cli/command"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/browser"
@@ -57,14 +56,7 @@ func loadTrace(ctx context.Context, ref string, nodes []builder.Node) (string, [
// build is complete but no trace yet. try to finalize the trace
time.Sleep(1 * time.Second) // give some extra time for last parts of trace to be written
c, err := rec.node.Driver.Client(ctx)
if err != nil {
return "", nil, err
}
_, err = c.ControlClient().UpdateBuildHistory(ctx, &controlapi.UpdateBuildHistoryRequest{
Ref: rec.Ref,
Finalize: true,
})
err := finalizeRecord(ctx, rec.Ref, []builder.Node{*rec.node})
if err != nil {
return "", nil, err
}
+22
View File
@@ -247,6 +247,28 @@ func queryRecords(ctx context.Context, ref string, nodes []builder.Node, opts *q
return out, nil
}
func finalizeRecord(ctx context.Context, ref string, nodes []builder.Node) error {
eg, ctx := errgroup.WithContext(ctx)
for _, node := range nodes {
node := node
eg.Go(func() error {
if node.Driver == nil {
return nil
}
c, err := node.Driver.Client(ctx)
if err != nil {
return err
}
_, err = c.ControlClient().UpdateBuildHistory(ctx, &controlapi.UpdateBuildHistoryRequest{
Ref: ref,
Finalize: true,
})
return err
})
}
return eg.Wait()
}
func formatDuration(d time.Duration) string {
if d < time.Minute {
return fmt.Sprintf("%.1fs", d.Seconds())