| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -9,6 +9,7 @@ import (
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"github.com/compose-spec/compose-go/loader"
 | 
					 | 
					 | 
					 | 
						"github.com/compose-spec/compose-go/loader"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						compose "github.com/compose-spec/compose-go/types"
 | 
					 | 
					 | 
					 | 
						compose "github.com/compose-spec/compose-go/types"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"github.com/pkg/errors"
 | 
					 | 
					 | 
					 | 
						"github.com/pkg/errors"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						"gopkg.in/yaml.v3"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					)
 | 
					 | 
					 | 
					 | 
					)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					func parseCompose(dt []byte) (*compose.Project, error) {
 | 
					 | 
					 | 
					 | 
					func parseCompose(dt []byte) (*compose.Project, error) {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -135,90 +136,86 @@ func flatten(in compose.MappingWithEquals) compose.Mapping {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return out
 | 
					 | 
					 | 
					 | 
						return out
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// composeExtTarget converts Compose build extension x-bake to bake Target
 | 
					 | 
					 | 
					 | 
					// xbake Compose build extension provides fields not (yet) available in
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension
 | 
					 | 
					 | 
					 | 
					// Compose build specification: https://github.com/compose-spec/compose-spec/blob/master/build.md
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					func (t *Target) composeExtTarget(exts map[string]interface{}) error {
 | 
					 | 
					 | 
					 | 
					type xbake struct {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if ext, ok := exts["x-bake"]; ok {
 | 
					 | 
					 | 
					 | 
						Tags          stringArray `yaml:"tags,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							for key, val := range ext.(map[string]interface{}) {
 | 
					 | 
					 | 
					 | 
						CacheFrom     stringArray `yaml:"cache-from,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								switch key {
 | 
					 | 
					 | 
					 | 
						CacheTo       stringArray `yaml:"cache-to,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "tags":
 | 
					 | 
					 | 
					 | 
						Secrets       stringArray `yaml:"secret,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
						SSH           stringArray `yaml:"ssh,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.Tags = append(t.Tags, res)
 | 
					 | 
					 | 
					 | 
						Platforms     stringArray `yaml:"platforms,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
						Outputs       stringArray `yaml:"output,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
						Pull          *bool       `yaml:"pull,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.Tags = append(t.Tags, res.(string))
 | 
					 | 
					 | 
					 | 
						NoCache       *bool       `yaml:"no-cache,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										}
 | 
					 | 
					 | 
					 | 
						NoCacheFilter stringArray `yaml:"no-cache-filter,omitempty"`
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									}
 | 
					 | 
					 | 
					 | 
						// don't forget to update documentation if you add a new field:
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "cache-from":
 | 
					 | 
					 | 
					 | 
						// docs/guides/bake/compose-file.md#extension-field-with-x-bake
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									t.CacheFrom = []string{} // Needed to override the main field
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.CacheFrom = append(t.CacheFrom, res)
 | 
					 | 
					 | 
					 | 
					type stringArray []string
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					func (sa *stringArray) UnmarshalYAML(unmarshal func(interface{}) error) error {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.CacheFrom = append(t.CacheFrom, res.(string))
 | 
					 | 
					 | 
					 | 
						var multi []string
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										}
 | 
					 | 
					 | 
					 | 
						err := unmarshal(&multi)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									}
 | 
					 | 
					 | 
					 | 
						if err != nil {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "cache-to":
 | 
					 | 
					 | 
					 | 
							var single string
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
							if err := unmarshal(&single); err != nil {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.CacheTo = append(t.CacheTo, res)
 | 
					 | 
					 | 
					 | 
								return err
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.CacheTo = append(t.CacheTo, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										}
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}
 | 
					 | 
					 | 
					 | 
							}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "secret":
 | 
					 | 
					 | 
					 | 
							*sa = strings.Fields(single)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.Secrets = append(t.Secrets, res)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} else {
 | 
					 | 
					 | 
					 | 
						} else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
							*sa = multi
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.Secrets = append(t.Secrets, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										}
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "ssh":
 | 
					 | 
					 | 
					 | 
						return nil
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.SSH = append(t.SSH, res)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.SSH = append(t.SSH, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// composeExtTarget converts Compose build extension x-bake to bake Target
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extension
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					func (t *Target) composeExtTarget(exts map[string]interface{}) error {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						var xb xbake
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ext, ok := exts["x-bake"]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if !ok || ext == nil {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							return nil
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "platforms":
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
						yb, _ := yaml.Marshal(ext)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.Platforms = append(t.Platforms, res)
 | 
					 | 
					 | 
					 | 
						if err := yaml.Unmarshal(yb, &xb); err != nil {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
							return err
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.Platforms = append(t.Platforms, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if len(xb.Tags) > 0 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							t.Tags = append(t.Tags, xb.Tags...)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "output":
 | 
					 | 
					 | 
					 | 
						if len(xb.CacheFrom) > 0 {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
							t.CacheFrom = xb.CacheFrom // override main field
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.Outputs = append(t.Outputs, res)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.Outputs = append(t.Outputs, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if len(xb.CacheTo) > 0 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							t.CacheTo = append(t.CacheTo, xb.CacheTo...)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "pull":
 | 
					 | 
					 | 
					 | 
						if len(xb.Secrets) > 0 {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, ok := val.(bool); ok {
 | 
					 | 
					 | 
					 | 
							t.Secrets = append(t.Secrets, xb.Secrets...)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.Pull = &res
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "no-cache":
 | 
					 | 
					 | 
					 | 
						if len(xb.SSH) > 0 {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, ok := val.(bool); ok {
 | 
					 | 
					 | 
					 | 
							t.SSH = append(t.SSH, xb.SSH...)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.NoCache = &res
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case "no-cache-filter":
 | 
					 | 
					 | 
					 | 
						if len(xb.Platforms) > 0 {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if res, k := val.(string); k {
 | 
					 | 
					 | 
					 | 
							t.Platforms = append(t.Platforms, xb.Platforms...)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										t.NoCacheFilter = append(t.NoCacheFilter, res)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										for _, res := range val.([]interface{}) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											t.NoCacheFilter = append(t.NoCacheFilter, res.(string))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if len(xb.Outputs) > 0 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							t.Outputs = append(t.Outputs, xb.Outputs...)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								default:
 | 
					 | 
					 | 
					 | 
						if xb.Pull != nil {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									return fmt.Errorf("compose file invalid: unkwown %s field for x-bake", key)
 | 
					 | 
					 | 
					 | 
							t.Pull = xb.Pull
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if xb.NoCache != nil {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							t.NoCache = xb.NoCache
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if len(xb.NoCacheFilter) > 0 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							t.NoCacheFilter = append(t.NoCacheFilter, xb.NoCacheFilter...)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						}
 | 
					 | 
					 | 
					 | 
						}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return nil
 | 
					 | 
					 | 
					 | 
						return nil
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |