mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 01:53:42 +08:00 
			
		
		
		
	Merge pull request #2900 from crazy-max/bake-list-flag
bake: replace --list-targets and --list-variables flags with --list flag
This commit is contained in:
		@@ -579,9 +579,9 @@ func (p *parser) validateVariables(vars map[string]*variable, ectx *hcl.EvalCont
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Variable struct {
 | 
			
		||||
	Name        string
 | 
			
		||||
	Description string
 | 
			
		||||
	Value       *string
 | 
			
		||||
	Name        string  `json:"name"`
 | 
			
		||||
	Description string  `json:"description,omitempty"`
 | 
			
		||||
	Value       *string `json:"value,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ParseMeta struct {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										161
									
								
								commands/bake.go
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								commands/bake.go
									
									
									
									
									
								
							@@ -25,7 +25,6 @@ import (
 | 
			
		||||
	"github.com/docker/buildx/controller/pb"
 | 
			
		||||
	"github.com/docker/buildx/localstate"
 | 
			
		||||
	"github.com/docker/buildx/util/buildflags"
 | 
			
		||||
	"github.com/docker/buildx/util/cobrautil"
 | 
			
		||||
	"github.com/docker/buildx/util/cobrautil/completion"
 | 
			
		||||
	"github.com/docker/buildx/util/confutil"
 | 
			
		||||
	"github.com/docker/buildx/util/desktop"
 | 
			
		||||
@@ -38,24 +37,30 @@ import (
 | 
			
		||||
	"github.com/moby/buildkit/util/progress/progressui"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/tonistiigi/go-csvvalue"
 | 
			
		||||
	"go.opentelemetry.io/otel/attribute"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type bakeOptions struct {
 | 
			
		||||
	files       []string
 | 
			
		||||
	overrides   []string
 | 
			
		||||
	printOnly   bool
 | 
			
		||||
	listTargets bool
 | 
			
		||||
	listVars    bool
 | 
			
		||||
	sbom        string
 | 
			
		||||
	provenance  string
 | 
			
		||||
	allow       []string
 | 
			
		||||
	files     []string
 | 
			
		||||
	overrides []string
 | 
			
		||||
 | 
			
		||||
	sbom       string
 | 
			
		||||
	provenance string
 | 
			
		||||
	allow      []string
 | 
			
		||||
 | 
			
		||||
	builder      string
 | 
			
		||||
	metadataFile string
 | 
			
		||||
	exportPush   bool
 | 
			
		||||
	exportLoad   bool
 | 
			
		||||
	callFunc     string
 | 
			
		||||
 | 
			
		||||
	print bool
 | 
			
		||||
	list  string
 | 
			
		||||
 | 
			
		||||
	// TODO: remove deprecated flags
 | 
			
		||||
	listTargets bool
 | 
			
		||||
	listVars    bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags) (err error) {
 | 
			
		||||
@@ -121,9 +126,13 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
 | 
			
		||||
	var nodes []builder.Node
 | 
			
		||||
	var progressConsoleDesc, progressTextDesc string
 | 
			
		||||
 | 
			
		||||
	if in.print && in.list != "" {
 | 
			
		||||
		return errors.New("--print and --list are mutually exclusive")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// instance only needed for reading remote bake files or building
 | 
			
		||||
	var driverType string
 | 
			
		||||
	if url != "" || !(in.printOnly || in.listTargets || in.listVars) {
 | 
			
		||||
	if url != "" || !(in.print || in.list != "") {
 | 
			
		||||
		b, err := builder.New(dockerCli,
 | 
			
		||||
			builder.WithName(in.builder),
 | 
			
		||||
			builder.WithContextPathHash(contextPathHash),
 | 
			
		||||
@@ -184,7 +193,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
 | 
			
		||||
		"BAKE_LOCAL_PLATFORM": platforms.Format(platforms.DefaultSpec()),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if in.listTargets || in.listVars {
 | 
			
		||||
	if in.list != "" {
 | 
			
		||||
		cfg, pm, err := bake.ParseFiles(files, defaults)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
@@ -192,10 +201,15 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
 | 
			
		||||
		if err = printer.Wait(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if in.listTargets {
 | 
			
		||||
			return printTargetList(dockerCli.Out(), cfg)
 | 
			
		||||
		} else if in.listVars {
 | 
			
		||||
			return printVars(dockerCli.Out(), pm.AllVariables)
 | 
			
		||||
		list, err := parseList(in.list)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		switch list.Type {
 | 
			
		||||
		case "targets":
 | 
			
		||||
			return printTargetList(dockerCli.Out(), list.Format, cfg)
 | 
			
		||||
		case "variables":
 | 
			
		||||
			return printVars(dockerCli.Out(), list.Format, pm.AllVariables)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -231,7 +245,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
 | 
			
		||||
		Target: tgts,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if in.printOnly {
 | 
			
		||||
	if in.print {
 | 
			
		||||
		if err = printer.Wait(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
@@ -427,6 +441,13 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
			
		||||
			if !cmd.Flags().Lookup("pull").Changed {
 | 
			
		||||
				cFlags.pull = nil
 | 
			
		||||
			}
 | 
			
		||||
			if options.list == "" {
 | 
			
		||||
				if options.listTargets {
 | 
			
		||||
					options.list = "targets"
 | 
			
		||||
				} else if options.listVars {
 | 
			
		||||
					options.list = "variables"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			options.builder = rootOpts.builder
 | 
			
		||||
			options.metadataFile = cFlags.metadataFile
 | 
			
		||||
			// Other common flags (noCache, pull and progress) are processed in runBake function.
 | 
			
		||||
@@ -439,7 +460,6 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
			
		||||
 | 
			
		||||
	flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file")
 | 
			
		||||
	flags.BoolVar(&options.exportLoad, "load", false, `Shorthand for "--set=*.output=type=docker"`)
 | 
			
		||||
	flags.BoolVar(&options.printOnly, "print", false, "Print the options without building")
 | 
			
		||||
	flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--set=*.output=type=registry"`)
 | 
			
		||||
	flags.StringVar(&options.sbom, "sbom", "", `Shorthand for "--set=*.attest=type=sbom"`)
 | 
			
		||||
	flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--set=*.attest=type=provenance"`)
 | 
			
		||||
@@ -450,13 +470,16 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
 | 
			
		||||
	flags.VarPF(callAlias(&options.callFunc, "check"), "check", "", `Shorthand for "--call=check"`)
 | 
			
		||||
	flags.Lookup("check").NoOptDefVal = "true"
 | 
			
		||||
 | 
			
		||||
	flags.BoolVar(&options.listTargets, "list-targets", false, "List available targets")
 | 
			
		||||
	cobrautil.MarkFlagsExperimental(flags, "list-targets")
 | 
			
		||||
	flags.MarkHidden("list-targets")
 | 
			
		||||
	flags.BoolVar(&options.print, "print", false, "Print the options without building")
 | 
			
		||||
	flags.StringVar(&options.list, "list", "", "List targets or variables")
 | 
			
		||||
 | 
			
		||||
	// TODO: remove deprecated flags
 | 
			
		||||
	flags.BoolVar(&options.listTargets, "list-targets", false, "List available targets")
 | 
			
		||||
	flags.MarkHidden("list-targets")
 | 
			
		||||
	flags.MarkDeprecated("list-targets", "list-targets is deprecated, use list=targets instead")
 | 
			
		||||
	flags.BoolVar(&options.listVars, "list-variables", false, "List defined variables")
 | 
			
		||||
	cobrautil.MarkFlagsExperimental(flags, "list-variables")
 | 
			
		||||
	flags.MarkHidden("list-variables")
 | 
			
		||||
	flags.MarkDeprecated("list-variables", "list-variables is deprecated, use list=variables instead")
 | 
			
		||||
 | 
			
		||||
	commonBuildFlags(&cFlags, flags)
 | 
			
		||||
 | 
			
		||||
@@ -557,10 +580,70 @@ func readBakeFiles(ctx context.Context, nodes []builder.Node, url string, names
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printVars(w io.Writer, vars []*hclparser.Variable) error {
 | 
			
		||||
type listEntry struct {
 | 
			
		||||
	Type   string
 | 
			
		||||
	Format string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseList(input string) (listEntry, error) {
 | 
			
		||||
	res := listEntry{}
 | 
			
		||||
 | 
			
		||||
	fields, err := csvvalue.Fields(input, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(fields) == 1 && fields[0] == input && !strings.HasPrefix(input, "type=") {
 | 
			
		||||
		res.Type = input
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if res.Type == "" {
 | 
			
		||||
		for _, field := range fields {
 | 
			
		||||
			key, value, ok := strings.Cut(field, "=")
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return res, errors.Errorf("invalid value %s", field)
 | 
			
		||||
			}
 | 
			
		||||
			key = strings.TrimSpace(strings.ToLower(key))
 | 
			
		||||
			switch key {
 | 
			
		||||
			case "type":
 | 
			
		||||
				res.Type = value
 | 
			
		||||
			case "format":
 | 
			
		||||
				res.Format = value
 | 
			
		||||
			default:
 | 
			
		||||
				return res, errors.Errorf("unexpected key '%s' in '%s'", key, field)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if res.Format == "" {
 | 
			
		||||
		res.Format = "table"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch res.Type {
 | 
			
		||||
	case "targets", "variables":
 | 
			
		||||
	default:
 | 
			
		||||
		return res, errors.Errorf("invalid list type %q", res.Type)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch res.Format {
 | 
			
		||||
	case "table", "json":
 | 
			
		||||
	default:
 | 
			
		||||
		return res, errors.Errorf("invalid list format %q", res.Format)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printVars(w io.Writer, format string, vars []*hclparser.Variable) error {
 | 
			
		||||
	slices.SortFunc(vars, func(a, b *hclparser.Variable) int {
 | 
			
		||||
		return cmp.Compare(a.Name, b.Name)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if format == "json" {
 | 
			
		||||
		enc := json.NewEncoder(w)
 | 
			
		||||
		enc.SetIndent("", "  ")
 | 
			
		||||
		return enc.Encode(vars)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
 | 
			
		||||
	defer tw.Flush()
 | 
			
		||||
 | 
			
		||||
@@ -578,12 +661,7 @@ func printVars(w io.Writer, vars []*hclparser.Variable) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printTargetList(w io.Writer, cfg *bake.Config) error {
 | 
			
		||||
	tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
 | 
			
		||||
	defer tw.Flush()
 | 
			
		||||
 | 
			
		||||
	tw.Write([]byte("TARGET\tDESCRIPTION\n"))
 | 
			
		||||
 | 
			
		||||
func printTargetList(w io.Writer, format string, cfg *bake.Config) error {
 | 
			
		||||
	type targetOrGroup struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		target *bake.Target
 | 
			
		||||
@@ -602,6 +680,20 @@ func printTargetList(w io.Writer, cfg *bake.Config) error {
 | 
			
		||||
		return cmp.Compare(a.name, b.name)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	var tw *tabwriter.Writer
 | 
			
		||||
	if format == "table" {
 | 
			
		||||
		tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
 | 
			
		||||
		defer tw.Flush()
 | 
			
		||||
		tw.Write([]byte("TARGET\tDESCRIPTION\n"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type targetList struct {
 | 
			
		||||
		Name        string `json:"name"`
 | 
			
		||||
		Description string `json:"description,omitempty"`
 | 
			
		||||
		Group       bool   `json:"group,omitempty"`
 | 
			
		||||
	}
 | 
			
		||||
	var targetsList []targetList
 | 
			
		||||
 | 
			
		||||
	for _, tgt := range list {
 | 
			
		||||
		if strings.HasPrefix(tgt.name, "_") {
 | 
			
		||||
			// convention for a private target
 | 
			
		||||
@@ -610,9 +702,9 @@ func printTargetList(w io.Writer, cfg *bake.Config) error {
 | 
			
		||||
		var descr string
 | 
			
		||||
		if tgt.target != nil {
 | 
			
		||||
			descr = tgt.target.Description
 | 
			
		||||
			targetsList = append(targetsList, targetList{Name: tgt.name, Description: descr})
 | 
			
		||||
		} else if tgt.group != nil {
 | 
			
		||||
			descr = tgt.group.Description
 | 
			
		||||
 | 
			
		||||
			if len(tgt.group.Targets) > 0 {
 | 
			
		||||
				slices.Sort(tgt.group.Targets)
 | 
			
		||||
				names := strings.Join(tgt.group.Targets, ", ")
 | 
			
		||||
@@ -622,8 +714,17 @@ func printTargetList(w io.Writer, cfg *bake.Config) error {
 | 
			
		||||
					descr = names
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			targetsList = append(targetsList, targetList{Name: tgt.name, Description: descr, Group: true})
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(tw, "%s\t%s\n", tgt.name, descr)
 | 
			
		||||
		if format == "table" {
 | 
			
		||||
			fmt.Fprintf(tw, "%s\t%s\n", tgt.name, descr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if format == "json" {
 | 
			
		||||
		enc := json.NewEncoder(w)
 | 
			
		||||
		enc.SetIndent("", "  ")
 | 
			
		||||
		return enc.Encode(targetsList)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ Build from a file
 | 
			
		||||
| [`--check`](#check)                 | `bool`        |         | Shorthand for `--call=check`                                                                        |
 | 
			
		||||
| `-D`, `--debug`                     | `bool`        |         | Enable debug logging                                                                                |
 | 
			
		||||
| [`-f`](#file), [`--file`](#file)    | `stringArray` |         | Build definition file                                                                               |
 | 
			
		||||
| `--list`                            | `string`      |         | List targets or variables                                                                           |
 | 
			
		||||
| `--load`                            | `bool`        |         | Shorthand for `--set=*.output=type=docker`                                                          |
 | 
			
		||||
| [`--metadata-file`](#metadata-file) | `string`      |         | Write build result metadata to a file                                                               |
 | 
			
		||||
| [`--no-cache`](#no-cache)           | `bool`        |         | Do not use cache when building the image                                                            |
 | 
			
		||||
 
 | 
			
		||||
@@ -1599,7 +1599,7 @@ target "abc" {
 | 
			
		||||
	out, err := bakeCmd(
 | 
			
		||||
		sb,
 | 
			
		||||
		withDir(dir),
 | 
			
		||||
		withArgs("--list-targets"),
 | 
			
		||||
		withArgs("--list=targets"),
 | 
			
		||||
	)
 | 
			
		||||
	require.NoError(t, err, out)
 | 
			
		||||
 | 
			
		||||
@@ -1628,7 +1628,7 @@ target "default" {
 | 
			
		||||
	out, err := bakeCmd(
 | 
			
		||||
		sb,
 | 
			
		||||
		withDir(dir),
 | 
			
		||||
		withArgs("--list-variables"),
 | 
			
		||||
		withArgs("--list=variables"),
 | 
			
		||||
	)
 | 
			
		||||
	require.NoError(t, err, out)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user