mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	bake: allow pattern matching for target names in --set
Although bake is for running multiple targets, --set required a single target name for overriding a property. This change allows matching multiple targets for overrides. Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
		@@ -511,7 +511,7 @@ Options:
 | 
				
			|||||||
|      --print             | Print the options without building
 | 
					|      --print             | Print the options without building
 | 
				
			||||||
|      --progress string   | Set type of progress output (auto, plain, tty). Use plain to show container output (default "auto")
 | 
					|      --progress string   | Set type of progress output (auto, plain, tty). Use plain to show container output (default "auto")
 | 
				
			||||||
|      --pull              | Always attempt to pull a newer version of the image
 | 
					|      --pull              | Always attempt to pull a newer version of the image
 | 
				
			||||||
|      --set stringArray   | Override target value (eg: target.key=value)
 | 
					|      --set stringArray   | Override target value (eg: targetpattern.key=value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `-f, --file FILE`
 | 
					#### `-f, --file FILE`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -554,14 +554,16 @@ Same as `build --progress`. Set type of progress output (auto, plain, tty). Use
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Same as `build --pull`.
 | 
					Same as `build --pull`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `--set target.key[.subkey]=value`
 | 
					#### `--set targetpattern.key[.subkey]=value`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Override target configurations from command line.
 | 
					Override target configurations from command line. The pattern matching syntax is defined in https://golang.org/pkg/path/#Match.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example:
 | 
					Example:
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
docker buildx bake --set target.args.mybuildarg=value
 | 
					docker buildx bake --set target.args.mybuildarg=value
 | 
				
			||||||
docker buildx bake --set target.platform=linux/arm64
 | 
					docker buildx bake --set target.platform=linux/arm64
 | 
				
			||||||
 | 
					docker buildx bake --set foo*.args.mybuildarg=value	# overrides build arg for all targets starting with 'foo'
 | 
				
			||||||
 | 
					docker buildx bake --set *.platform=linux/arm64		# overrides platform for all targets
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### File definition
 | 
					#### File definition
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										124
									
								
								bake/bake.go
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								bake/bake.go
									
									
									
									
									
								
							@@ -106,6 +106,26 @@ func mergeConfig(c1, c2 Config) Config {
 | 
				
			|||||||
	return c1
 | 
						return c1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c Config) expandTargets(pattern string) ([]string, error) {
 | 
				
			||||||
 | 
						if _, ok := c.Target[pattern]; ok {
 | 
				
			||||||
 | 
							return []string{pattern}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var names []string
 | 
				
			||||||
 | 
						for name := range c.Target {
 | 
				
			||||||
 | 
							ok, err := path.Match(pattern, name)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, errors.Wrapf(err, "could not match targets with '%s'", pattern)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								names = append(names, name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(names) == 0 {
 | 
				
			||||||
 | 
							return nil, errors.Errorf("could not find any target matching '%s'", pattern)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return names, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c Config) newOverrides(v []string) (map[string]Target, error) {
 | 
					func (c Config) newOverrides(v []string) (map[string]Target, error) {
 | 
				
			||||||
	m := map[string]Target{}
 | 
						m := map[string]Target{}
 | 
				
			||||||
	for _, v := range v {
 | 
						for _, v := range v {
 | 
				
			||||||
@@ -116,65 +136,69 @@ func (c Config) newOverrides(v []string) (map[string]Target, error) {
 | 
				
			|||||||
			return nil, errors.Errorf("invalid override key %s, expected target.name", parts[0])
 | 
								return nil, errors.Errorf("invalid override key %s, expected target.name", parts[0])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		name := keys[0]
 | 
							pattern := keys[0]
 | 
				
			||||||
		if len(parts) != 2 && keys[1] != "args" {
 | 
							if len(parts) != 2 && keys[1] != "args" {
 | 
				
			||||||
			return nil, errors.Errorf("invalid override %s, expected target.name=value", v)
 | 
								return nil, errors.Errorf("invalid override %s, expected target.name=value", v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		t := m[name]
 | 
							names, err := c.expandTargets(pattern)
 | 
				
			||||||
		if _, ok := c.Target[name]; !ok {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, errors.Errorf("unknown target %s", name)
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch keys[1] {
 | 
							for _, name := range names {
 | 
				
			||||||
		case "context":
 | 
								t := m[name]
 | 
				
			||||||
			t.Context = &parts[1]
 | 
					
 | 
				
			||||||
		case "dockerfile":
 | 
								switch keys[1] {
 | 
				
			||||||
			t.Dockerfile = &parts[1]
 | 
								case "context":
 | 
				
			||||||
		case "args":
 | 
									t.Context = &parts[1]
 | 
				
			||||||
			if len(keys) != 3 {
 | 
								case "dockerfile":
 | 
				
			||||||
				return nil, errors.Errorf("invalid key %s, args requires name", parts[0])
 | 
									t.Dockerfile = &parts[1]
 | 
				
			||||||
			}
 | 
								case "args":
 | 
				
			||||||
			if t.Args == nil {
 | 
									if len(keys) != 3 {
 | 
				
			||||||
				t.Args = map[string]string{}
 | 
										return nil, errors.Errorf("invalid key %s, args requires name", parts[0])
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if len(parts) < 2 {
 | 
					 | 
				
			||||||
				v, ok := os.LookupEnv(keys[2])
 | 
					 | 
				
			||||||
				if ok {
 | 
					 | 
				
			||||||
					t.Args[keys[2]] = v
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
									if t.Args == nil {
 | 
				
			||||||
				t.Args[keys[2]] = parts[1]
 | 
										t.Args = map[string]string{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if len(parts) < 2 {
 | 
				
			||||||
 | 
										v, ok := os.LookupEnv(keys[2])
 | 
				
			||||||
 | 
										if ok {
 | 
				
			||||||
 | 
											t.Args[keys[2]] = v
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										t.Args[keys[2]] = parts[1]
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case "labels":
 | 
				
			||||||
 | 
									if len(keys) != 3 {
 | 
				
			||||||
 | 
										return nil, errors.Errorf("invalid key %s, lanels requires name", parts[0])
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if t.Labels == nil {
 | 
				
			||||||
 | 
										t.Labels = map[string]string{}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									t.Labels[keys[2]] = parts[1]
 | 
				
			||||||
 | 
								case "tags":
 | 
				
			||||||
 | 
									t.Tags = append(t.Tags, parts[1])
 | 
				
			||||||
 | 
								case "cache-from":
 | 
				
			||||||
 | 
									t.CacheFrom = append(t.CacheFrom, parts[1])
 | 
				
			||||||
 | 
								case "cache-to":
 | 
				
			||||||
 | 
									t.CacheTo = append(t.CacheTo, parts[1])
 | 
				
			||||||
 | 
								case "target":
 | 
				
			||||||
 | 
									s := parts[1]
 | 
				
			||||||
 | 
									t.Target = &s
 | 
				
			||||||
 | 
								case "secrets":
 | 
				
			||||||
 | 
									t.Secrets = append(t.Secrets, parts[1])
 | 
				
			||||||
 | 
								case "ssh":
 | 
				
			||||||
 | 
									t.SSH = append(t.SSH, parts[1])
 | 
				
			||||||
 | 
								case "platform":
 | 
				
			||||||
 | 
									t.Platforms = append(t.Platforms, parts[1])
 | 
				
			||||||
 | 
								case "output":
 | 
				
			||||||
 | 
									t.Outputs = append(t.Outputs, parts[1])
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									return nil, errors.Errorf("unknown key: %s", keys[1])
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case "labels":
 | 
								m[name] = t
 | 
				
			||||||
			if len(keys) != 3 {
 | 
					 | 
				
			||||||
				return nil, errors.Errorf("invalid key %s, lanels requires name", parts[0])
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if t.Labels == nil {
 | 
					 | 
				
			||||||
				t.Labels = map[string]string{}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			t.Labels[keys[2]] = parts[1]
 | 
					 | 
				
			||||||
		case "tags":
 | 
					 | 
				
			||||||
			t.Tags = append(t.Tags, parts[1])
 | 
					 | 
				
			||||||
		case "cache-from":
 | 
					 | 
				
			||||||
			t.CacheFrom = append(t.CacheFrom, parts[1])
 | 
					 | 
				
			||||||
		case "cache-to":
 | 
					 | 
				
			||||||
			t.CacheTo = append(t.CacheTo, parts[1])
 | 
					 | 
				
			||||||
		case "target":
 | 
					 | 
				
			||||||
			s := parts[1]
 | 
					 | 
				
			||||||
			t.Target = &s
 | 
					 | 
				
			||||||
		case "secrets":
 | 
					 | 
				
			||||||
			t.Secrets = append(t.Secrets, parts[1])
 | 
					 | 
				
			||||||
		case "ssh":
 | 
					 | 
				
			||||||
			t.SSH = append(t.SSH, parts[1])
 | 
					 | 
				
			||||||
		case "platform":
 | 
					 | 
				
			||||||
			t.Platforms = append(t.Platforms, parts[1])
 | 
					 | 
				
			||||||
		case "output":
 | 
					 | 
				
			||||||
			t.Outputs = append(t.Outputs, parts[1])
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return nil, errors.Errorf("unknown key: %s", keys[1])
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m[name] = t
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return m, nil
 | 
						return m, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ target "webapp" {
 | 
				
			|||||||
	t.Run("InvalidTargetOverrides", func(t *testing.T) {
 | 
						t.Run("InvalidTargetOverrides", func(t *testing.T) {
 | 
				
			||||||
		_, err := ReadTargets(ctx, []string{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"})
 | 
							_, err := ReadTargets(ctx, []string{fp}, []string{"webapp"}, []string{"nosuchtarget.context=foo"})
 | 
				
			||||||
		require.NotNil(t, err)
 | 
							require.NotNil(t, err)
 | 
				
			||||||
		require.Equal(t, err.Error(), "unknown target nosuchtarget")
 | 
							require.Equal(t, err.Error(), "could not find any target matching 'nosuchtarget'")
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Run("ArgsOverrides", func(t *testing.T) {
 | 
						t.Run("ArgsOverrides", func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,7 +99,7 @@ func bakeCmd(dockerCli command.Cli) *cobra.Command {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file")
 | 
						flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file")
 | 
				
			||||||
	flags.BoolVar(&options.printOnly, "print", false, "Print the options without building")
 | 
						flags.BoolVar(&options.printOnly, "print", false, "Print the options without building")
 | 
				
			||||||
	flags.StringArrayVar(&options.overrides, "set", nil, "Override target value (eg: target.key=value)")
 | 
						flags.StringArrayVar(&options.overrides, "set", nil, "Override target value (eg: targetpattern.key=value)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	commonFlags(&options.commonOptions, flags)
 | 
						commonFlags(&options.commonOptions, flags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user