mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	These commands allow working with build records of completed and running builds. Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
		
			
				
	
	
		
			152 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package history
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"io"
 | 
						|
 | 
						|
	"github.com/docker/buildx/builder"
 | 
						|
	"github.com/docker/buildx/util/cobrautil/completion"
 | 
						|
	"github.com/docker/cli/cli/command"
 | 
						|
	"github.com/hashicorp/go-multierror"
 | 
						|
	controlapi "github.com/moby/buildkit/api/services/control"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"github.com/spf13/cobra"
 | 
						|
	"golang.org/x/sync/errgroup"
 | 
						|
)
 | 
						|
 | 
						|
type rmOptions struct {
 | 
						|
	builder string
 | 
						|
	refs    []string
 | 
						|
	all     bool
 | 
						|
}
 | 
						|
 | 
						|
func runRm(ctx context.Context, dockerCli command.Cli, opts rmOptions) error {
 | 
						|
	b, err := builder.New(dockerCli, builder.WithName(opts.builder))
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	nodes, err := b.LoadNodes(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	for _, node := range nodes {
 | 
						|
		if node.Err != nil {
 | 
						|
			return node.Err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	errs := make([][]error, len(opts.refs))
 | 
						|
	for i := range errs {
 | 
						|
		errs[i] = make([]error, len(nodes))
 | 
						|
	}
 | 
						|
 | 
						|
	eg, ctx := errgroup.WithContext(ctx)
 | 
						|
	for i, 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
 | 
						|
			}
 | 
						|
 | 
						|
			refs := opts.refs
 | 
						|
 | 
						|
			if opts.all {
 | 
						|
				serv, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
 | 
						|
					EarlyExit: true,
 | 
						|
				})
 | 
						|
				if err != nil {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
				defer serv.CloseSend()
 | 
						|
 | 
						|
				for {
 | 
						|
					resp, err := serv.Recv()
 | 
						|
					if err != nil {
 | 
						|
						if errors.Is(err, io.EOF) {
 | 
						|
							break
 | 
						|
						}
 | 
						|
						return err
 | 
						|
					}
 | 
						|
					if resp.Type == controlapi.BuildHistoryEventType_COMPLETE {
 | 
						|
						refs = append(refs, resp.Record.Ref)
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			for j, ref := range refs {
 | 
						|
				_, err = c.ControlClient().UpdateBuildHistory(ctx, &controlapi.UpdateBuildHistoryRequest{
 | 
						|
					Ref:    ref,
 | 
						|
					Delete: true,
 | 
						|
				})
 | 
						|
				if opts.all {
 | 
						|
					if err != nil {
 | 
						|
						return err
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					errs[j][i] = err
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return nil
 | 
						|
		})
 | 
						|
	}
 | 
						|
 | 
						|
	if err := eg.Wait(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	var out []error
 | 
						|
loop0:
 | 
						|
	for _, nodeErrs := range errs {
 | 
						|
		var nodeErr error
 | 
						|
		for _, err1 := range nodeErrs {
 | 
						|
			if err1 == nil {
 | 
						|
				continue loop0
 | 
						|
			}
 | 
						|
			if nodeErr == nil {
 | 
						|
				nodeErr = err1
 | 
						|
			} else {
 | 
						|
				nodeErr = multierror.Append(nodeErr, err1)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		out = append(out, nodeErr)
 | 
						|
	}
 | 
						|
	if len(out) == 0 {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	if len(out) == 1 {
 | 
						|
		return out[0]
 | 
						|
	}
 | 
						|
	return multierror.Append(out[0], out[1:]...)
 | 
						|
}
 | 
						|
 | 
						|
func rmCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command {
 | 
						|
	var options rmOptions
 | 
						|
 | 
						|
	cmd := &cobra.Command{
 | 
						|
		Use:   "rm [OPTIONS] [REF...]",
 | 
						|
		Short: "Remove build records",
 | 
						|
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
						|
			if len(args) == 0 && !options.all {
 | 
						|
				return errors.New("rm requires at least one argument")
 | 
						|
			}
 | 
						|
			if len(args) > 0 && options.all {
 | 
						|
				return errors.New("rm requires either --all or at least one argument")
 | 
						|
			}
 | 
						|
			options.refs = args
 | 
						|
			options.builder = *rootOpts.Builder
 | 
						|
			return runRm(cmd.Context(), dockerCli, options)
 | 
						|
		},
 | 
						|
		ValidArgsFunction: completion.Disable,
 | 
						|
	}
 | 
						|
 | 
						|
	flags := cmd.Flags()
 | 
						|
	flags.BoolVar(&options.all, "all", false, "Remove all build records")
 | 
						|
 | 
						|
	return cmd
 | 
						|
}
 |