From 8b6f23d18bc0487d6740a35f0797300c2ae20e91 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 19 Feb 2026 23:23:38 +0100 Subject: [PATCH 1/2] cli/compose/loader: remove some wrapper utilities Signed-off-by: Sebastiaan van Stijn --- cli/compose/loader/merge.go | 50 ++++++++++--------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/cli/compose/loader/merge.go b/cli/compose/loader/merge.go index 28e42838b61b..532d08a6c8e6 100644 --- a/cli/compose/loader/merge.go +++ b/cli/compose/loader/merge.go @@ -28,26 +28,22 @@ func (s *specials) Transformer(t reflect.Type) func(dst, src reflect.Value) erro func merge(configs []*types.Config) (*types.Config, error) { base := configs[0] for _, override := range configs[1:] { - var err error - base.Services, err = mergeServices(base.Services, override.Services) - if err != nil { - return base, fmt.Errorf("cannot merge services from %s: %w", override.Filename, err) + if services, err := mergeServices(base.Services, override.Services); err != nil { + return nil, fmt.Errorf("cannot merge services from %s: %w", override.Filename, err) + } else { + base.Services = services } - base.Volumes, err = mergeVolumes(base.Volumes, override.Volumes) - if err != nil { - return base, fmt.Errorf("cannot merge volumes from %s: %w", override.Filename, err) + if err := mergo.Map(&base.Volumes, &override.Volumes, mergo.WithOverride); err != nil { + return nil, fmt.Errorf("cannot merge volumes from %s: %w", override.Filename, err) } - base.Networks, err = mergeNetworks(base.Networks, override.Networks) - if err != nil { - return base, fmt.Errorf("cannot merge networks from %s: %w", override.Filename, err) + if err := mergo.Map(&base.Networks, &override.Networks, mergo.WithOverride); err != nil { + return nil, fmt.Errorf("cannot merge networks from %s: %w", override.Filename, err) } - base.Secrets, err = mergeSecrets(base.Secrets, override.Secrets) - if err != nil { - return base, fmt.Errorf("cannot merge secrets from %s: %w", override.Filename, err) + if err := mergo.Map(&base.Secrets, &override.Secrets, mergo.WithOverride); err != nil { + return nil, fmt.Errorf("cannot merge secrets from %s: %w", override.Filename, err) } - base.Configs, err = mergeConfigs(base.Configs, override.Configs) - if err != nil { - return base, fmt.Errorf("cannot merge configs from %s: %w", override.Filename, err) + if err := mergo.Map(&base.Configs, &override.Configs, mergo.WithOverride); err != nil { + return nil, fmt.Errorf("cannot merge configs from %s: %w", override.Filename, err) } } return base, nil @@ -78,7 +74,7 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig, for _, overrideService := range override { if baseService, ok := baseServices[overrideService.Name]; ok { if err := mergo.Merge(&baseService, &overrideService, mergeOpts...); err != nil { - return base, fmt.Errorf("cannot merge service %s: %w", overrideService.Name, err) + return nil, fmt.Errorf("cannot merge service %s: %w", overrideService.Name, err) } baseServices[overrideService.Name] = baseService continue @@ -284,23 +280,3 @@ func mergeUint64(dst, src reflect.Value) error { } return nil } - -func mergeVolumes(base, override map[string]types.VolumeConfig) (map[string]types.VolumeConfig, error) { - err := mergo.Map(&base, &override, mergo.WithOverride) - return base, err -} - -func mergeNetworks(base, override map[string]types.NetworkConfig) (map[string]types.NetworkConfig, error) { - err := mergo.Map(&base, &override, mergo.WithOverride) - return base, err -} - -func mergeSecrets(base, override map[string]types.SecretConfig) (map[string]types.SecretConfig, error) { - err := mergo.Map(&base, &override, mergo.WithOverride) - return base, err -} - -func mergeConfigs(base, override map[string]types.ConfigObjConfig) (map[string]types.ConfigObjConfig, error) { - err := mergo.Map(&base, &override, mergo.WithOverride) - return base, err -} From 13c993f1014f437ced9ab1872d5f594c6694debd Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 20 Feb 2026 00:10:22 +0100 Subject: [PATCH 2/2] cli/compose/loader: merge: use errors.Join Signed-off-by: Sebastiaan van Stijn --- cli/compose/loader/merge.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cli/compose/loader/merge.go b/cli/compose/loader/merge.go index 532d08a6c8e6..e69787cfac40 100644 --- a/cli/compose/loader/merge.go +++ b/cli/compose/loader/merge.go @@ -5,6 +5,7 @@ package loader import ( "cmp" + "errors" "fmt" "reflect" "slices" @@ -28,22 +29,26 @@ func (s *specials) Transformer(t reflect.Type) func(dst, src reflect.Value) erro func merge(configs []*types.Config) (*types.Config, error) { base := configs[0] for _, override := range configs[1:] { + var errs []error if services, err := mergeServices(base.Services, override.Services); err != nil { - return nil, fmt.Errorf("cannot merge services from %s: %w", override.Filename, err) + errs = append(errs, fmt.Errorf("cannot merge services: %w", err)) } else { base.Services = services } if err := mergo.Map(&base.Volumes, &override.Volumes, mergo.WithOverride); err != nil { - return nil, fmt.Errorf("cannot merge volumes from %s: %w", override.Filename, err) + errs = append(errs, fmt.Errorf("cannot merge volumes: %w", err)) } if err := mergo.Map(&base.Networks, &override.Networks, mergo.WithOverride); err != nil { - return nil, fmt.Errorf("cannot merge networks from %s: %w", override.Filename, err) + errs = append(errs, fmt.Errorf("cannot merge networks: %w", err)) } if err := mergo.Map(&base.Secrets, &override.Secrets, mergo.WithOverride); err != nil { - return nil, fmt.Errorf("cannot merge secrets from %s: %w", override.Filename, err) + errs = append(errs, fmt.Errorf("cannot merge secrets: %w", err)) } if err := mergo.Map(&base.Configs, &override.Configs, mergo.WithOverride); err != nil { - return nil, fmt.Errorf("cannot merge configs from %s: %w", override.Filename, err) + errs = append(errs, fmt.Errorf("cannot merge configs: %w", err)) + } + if err := errors.Join(errs...); err != nil { + return nil, errors.Join(fmt.Errorf("failed to merge file %s", override.Filename), err) } } return base, nil