mirror of https://github.com/docker/buildx.git
Merge pull request #2625 from ndeloof/bump-compose-v2.29.1
Bump compose-go v2.1.5
This commit is contained in:
commit
897fc91802
2
go.mod
2
go.mod
|
@ -6,7 +6,7 @@ require (
|
||||||
github.com/Masterminds/semver/v3 v3.2.1
|
github.com/Masterminds/semver/v3 v3.2.1
|
||||||
github.com/Microsoft/go-winio v0.6.2
|
github.com/Microsoft/go-winio v0.6.2
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.26.6
|
github.com/aws/aws-sdk-go-v2/config v1.26.6
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.4
|
github.com/compose-spec/compose-go/v2 v2.1.5
|
||||||
github.com/containerd/console v1.0.4
|
github.com/containerd/console v1.0.4
|
||||||
github.com/containerd/containerd v1.7.19
|
github.com/containerd/containerd v1.7.19
|
||||||
github.com/containerd/continuity v0.4.3
|
github.com/containerd/continuity v0.4.3
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -84,8 +84,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
|
||||||
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
|
||||||
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.4 h1:+1UKMvbBJo22Bpulgb9KAeZwRT99hANf3tDQVeG6ZJo=
|
github.com/compose-spec/compose-go/v2 v2.1.5 h1:6YoC9ik3NXdSYtgRn51EMZ2DxzGPyGjZ8M0B7mXTXeQ=
|
||||||
github.com/compose-spec/compose-go/v2 v2.1.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
|
github.com/compose-spec/compose-go/v2 v2.1.5/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
|
||||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||||
|
|
|
@ -22,11 +22,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/v2/consts"
|
"github.com/compose-spec/compose-go/v2/consts"
|
||||||
"github.com/compose-spec/compose-go/v2/interpolation"
|
|
||||||
"github.com/compose-spec/compose-go/v2/override"
|
"github.com/compose-spec/compose-go/v2/override"
|
||||||
"github.com/compose-spec/compose-go/v2/paths"
|
"github.com/compose-spec/compose-go/v2/paths"
|
||||||
"github.com/compose-spec/compose-go/v2/template"
|
|
||||||
"github.com/compose-spec/compose-go/v2/transform"
|
|
||||||
"github.com/compose-spec/compose-go/v2/types"
|
"github.com/compose-spec/compose-go/v2/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,22 +68,10 @@ func applyServiceExtends(ctx context.Context, name string, services map[string]a
|
||||||
)
|
)
|
||||||
switch v := extends.(type) {
|
switch v := extends.(type) {
|
||||||
case map[string]any:
|
case map[string]any:
|
||||||
if opts.Interpolate != nil {
|
|
||||||
v, err = interpolation.Interpolate(v, *opts.Interpolate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = v["service"].(string)
|
ref = v["service"].(string)
|
||||||
file = v["file"]
|
file = v["file"]
|
||||||
opts.ProcessEvent("extends", v)
|
opts.ProcessEvent("extends", v)
|
||||||
case string:
|
case string:
|
||||||
if opts.Interpolate != nil {
|
|
||||||
v, err = opts.Interpolate.Substitute(v, template.Mapping(opts.Interpolate.LookupValue))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = v
|
ref = v
|
||||||
opts.ProcessEvent("extends", map[string]any{"service": ref})
|
opts.ProcessEvent("extends", map[string]any{"service": ref})
|
||||||
}
|
}
|
||||||
|
@ -190,12 +175,6 @@ func getExtendsBaseFromFile(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to make a canonical model so ResolveRelativePaths can operate on source:target short syntaxes
|
|
||||||
source, err = transform.Canonical(source, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var remotes []paths.RemoteResource
|
var remotes []paths.RemoteResource
|
||||||
for _, loader := range opts.RemoteResourceLoaders() {
|
for _, loader := range opts.RemoteResourceLoaders() {
|
||||||
remotes = append(remotes, loader.Accept)
|
remotes = append(remotes, loader.Accept)
|
||||||
|
|
|
@ -30,7 +30,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// loadIncludeConfig parse the required config from raw yaml
|
// loadIncludeConfig parse the required config from raw yaml
|
||||||
func loadIncludeConfig(source any, options *Options) ([]types.IncludeConfig, error) {
|
func loadIncludeConfig(source any) ([]types.IncludeConfig, error) {
|
||||||
if source == nil {
|
if source == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -45,23 +45,13 @@ func loadIncludeConfig(source any, options *Options) ([]types.IncludeConfig, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if options.Interpolate != nil {
|
|
||||||
for i, config := range configs {
|
|
||||||
interpolated, err := interp.Interpolate(config.(map[string]any), *options.Interpolate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
configs[i] = interpolated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var requires []types.IncludeConfig
|
var requires []types.IncludeConfig
|
||||||
err := Transform(source, &requires)
|
err := Transform(source, &requires)
|
||||||
return requires, err
|
return requires, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyInclude(ctx context.Context, workingDir string, environment types.Mapping, model map[string]any, options *Options, included []string) error {
|
func ApplyInclude(ctx context.Context, workingDir string, environment types.Mapping, model map[string]any, options *Options, included []string) error {
|
||||||
includeConfig, err := loadIncludeConfig(model["include"], options)
|
includeConfig, err := loadIncludeConfig(model["include"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,23 +367,6 @@ func loadYamlModel(ctx context.Context, config types.ConfigDetails, opts *Option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Interpolate != nil && !opts.SkipInterpolation {
|
|
||||||
dict, err = interp.Interpolate(dict, *opts.Interpolate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dict, err = transform.Canonical(dict, opts.SkipInterpolation)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dict, err = override.EnforceUnicity(dict)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !opts.SkipDefaultValues {
|
if !opts.SkipDefaultValues {
|
||||||
dict, err = transform.SetDefaultValues(dict)
|
dict, err = transform.SetDefaultValues(dict)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -432,6 +415,13 @@ func loadYamlFile(ctx context.Context, file types.ConfigFile, opts *Options, wor
|
||||||
return errors.New("Top-level object must be a mapping")
|
return errors.New("Top-level object must be a mapping")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Interpolate != nil && !opts.SkipInterpolation {
|
||||||
|
cfg, err = interp.Interpolate(cfg, *opts.Interpolate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fixEmptyNotNull(cfg)
|
fixEmptyNotNull(cfg)
|
||||||
|
|
||||||
if !opts.SkipExtends {
|
if !opts.SkipExtends {
|
||||||
|
@ -460,6 +450,11 @@ func loadYamlFile(ctx context.Context, file types.ConfigFile, opts *Options, wor
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dict, err = override.EnforceUnicity(dict)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if !opts.SkipValidation {
|
if !opts.SkipValidation {
|
||||||
if err := schema.Validate(dict); err != nil {
|
if err := schema.Validate(dict); err != nil {
|
||||||
return fmt.Errorf("validating %s: %w", file.Filename, err)
|
return fmt.Errorf("validating %s: %w", file.Filename, err)
|
||||||
|
@ -469,7 +464,15 @@ func loadYamlFile(ctx context.Context, file types.ConfigFile, opts *Options, wor
|
||||||
delete(dict, "version")
|
delete(dict, "version")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
dict, err = transform.Canonical(dict, opts.SkipInterpolation)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonical transformation can reveal duplicates, typically as ports can be a range and conflict with an override
|
||||||
|
dict, err = override.EnforceUnicity(dict)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var processor PostProcessor
|
var processor PostProcessor
|
||||||
|
|
|
@ -237,20 +237,33 @@ func mergeIPAMConfig(c any, o any, path tree.Path) (any, error) {
|
||||||
return ipamConfigs, nil
|
return ipamConfigs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertIntoMapping(a any, defaultValue any) map[string]any {
|
func convertIntoMapping(a any, defaultValue map[string]any) map[string]any {
|
||||||
switch v := a.(type) {
|
switch v := a.(type) {
|
||||||
case map[string]any:
|
case map[string]any:
|
||||||
return v
|
return v
|
||||||
case []any:
|
case []any:
|
||||||
converted := map[string]any{}
|
converted := map[string]any{}
|
||||||
for _, s := range v {
|
for _, s := range v {
|
||||||
converted[s.(string)] = defaultValue
|
if defaultValue == nil {
|
||||||
|
converted[s.(string)] = nil
|
||||||
|
} else {
|
||||||
|
// Create a new map for each key
|
||||||
|
converted[s.(string)] = copyMap(defaultValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyMap(m map[string]any) map[string]any {
|
||||||
|
c := make(map[string]any)
|
||||||
|
for k, v := range m {
|
||||||
|
c[k] = v
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
func override(_ any, other any, _ tree.Path) (any, error) {
|
func override(_ any, other any, _ tree.Path) (any, error) {
|
||||||
return other, nil
|
return other, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,24 +116,30 @@ func (r *relativePathsResolver) absPath(value any) (any, error) {
|
||||||
}
|
}
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("unexpected type %T", value)
|
return nil, fmt.Errorf("unexpected type %T", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *relativePathsResolver) absVolumeMount(a any) (any, error) {
|
func (r *relativePathsResolver) absVolumeMount(a any) (any, error) {
|
||||||
vol := a.(map[string]any)
|
switch vol := a.(type) {
|
||||||
if vol["type"] != types.VolumeTypeBind {
|
case map[string]any:
|
||||||
|
if vol["type"] != types.VolumeTypeBind {
|
||||||
|
return vol, nil
|
||||||
|
}
|
||||||
|
src, ok := vol["source"]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
||||||
|
}
|
||||||
|
abs, err := r.maybeUnixPath(src.(string))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
vol["source"] = abs
|
||||||
return vol, nil
|
return vol, nil
|
||||||
|
default:
|
||||||
|
// not using canonical format, skip
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
src, ok := vol["source"]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New(`invalid mount config for type "bind": field Source must not be empty`)
|
|
||||||
}
|
|
||||||
abs, err := r.maybeUnixPath(src.(string))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vol["source"] = abs
|
|
||||||
return vol, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *relativePathsResolver) volumeDriverOpts(a any) (any, error) {
|
func (r *relativePathsResolver) volumeDriverOpts(a any) (any, error) {
|
||||||
|
|
|
@ -155,8 +155,8 @@
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"cap_add": {"type": "array", "items": {"type": "string"}},
|
"cap_add": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"cap_drop": {"type": "array", "items": {"type": "string"}},
|
"cap_drop": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"cgroup": {"type": "string", "enum": ["host", "private"]},
|
"cgroup": {"type": "string", "enum": ["host", "private"]},
|
||||||
"cgroup_parent": {"type": "string"},
|
"cgroup_parent": {"type": "string"},
|
||||||
"command": {"$ref": "#/definitions/command"},
|
"command": {"$ref": "#/definitions/command"},
|
||||||
|
@ -216,9 +216,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"},
|
"device_cgroup_rules": {"$ref": "#/definitions/list_of_strings"},
|
||||||
"devices": {"type": "array", "items": {"type": "string"}},
|
"devices": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"dns": {"$ref": "#/definitions/string_or_list"},
|
"dns": {"$ref": "#/definitions/string_or_list"},
|
||||||
"dns_opt": {"type": "array","items": {"type": "string"}},
|
"dns_opt": {"type": "array","items": {"type": "string"}, "uniqueItems": true},
|
||||||
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
"dns_search": {"$ref": "#/definitions/string_or_list"},
|
||||||
"domainname": {"type": "string"},
|
"domainname": {"type": "string"},
|
||||||
"entrypoint": {"$ref": "#/definitions/command"},
|
"entrypoint": {"$ref": "#/definitions/command"},
|
||||||
|
@ -230,7 +230,8 @@
|
||||||
"items": {
|
"items": {
|
||||||
"type": ["string", "number"],
|
"type": ["string", "number"],
|
||||||
"format": "expose"
|
"format": "expose"
|
||||||
}
|
},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
"extends": {
|
"extends": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
@ -247,13 +248,14 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"external_links": {"type": "array", "items": {"type": "string"}},
|
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
"extra_hosts": {"$ref": "#/definitions/list_or_dict"},
|
||||||
"group_add": {
|
"group_add": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": ["string", "number"]
|
"type": ["string", "number"]
|
||||||
}
|
},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
"healthcheck": {"$ref": "#/definitions/healthcheck"},
|
||||||
"hostname": {"type": "string"},
|
"hostname": {"type": "string"},
|
||||||
|
@ -262,7 +264,7 @@
|
||||||
"ipc": {"type": "string"},
|
"ipc": {"type": "string"},
|
||||||
"isolation": {"type": "string"},
|
"isolation": {"type": "string"},
|
||||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||||
"links": {"type": "array", "items": {"type": "string"}},
|
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"logging": {
|
"logging": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
||||||
|
@ -348,7 +350,8 @@
|
||||||
"patternProperties": {"^x-": {}}
|
"patternProperties": {"^x-": {}}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
"privileged": {"type": ["boolean", "string"]},
|
"privileged": {"type": ["boolean", "string"]},
|
||||||
"profiles": {"$ref": "#/definitions/list_of_strings"},
|
"profiles": {"$ref": "#/definitions/list_of_strings"},
|
||||||
|
@ -363,7 +366,7 @@
|
||||||
"scale": {
|
"scale": {
|
||||||
"type": ["integer", "string"]
|
"type": ["integer", "string"]
|
||||||
},
|
},
|
||||||
"security_opt": {"type": "array", "items": {"type": "string"}},
|
"security_opt": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||||
"shm_size": {"type": ["number", "string"]},
|
"shm_size": {"type": ["number", "string"]},
|
||||||
"secrets": {"$ref": "#/definitions/service_config_or_secret"},
|
"secrets": {"$ref": "#/definitions/service_config_or_secret"},
|
||||||
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
"sysctls": {"$ref": "#/definitions/list_or_dict"},
|
||||||
|
@ -429,11 +432,13 @@
|
||||||
"patternProperties": {"^x-": {}}
|
"patternProperties": {"^x-": {}}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
"volumes_from": {
|
"volumes_from": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string"}
|
"items": {"type": "string"},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
"working_dir": {"type": "string"}
|
"working_dir": {"type": "string"}
|
||||||
},
|
},
|
||||||
|
@ -828,7 +833,8 @@
|
||||||
|
|
||||||
"list_of_strings": {
|
"list_of_strings": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string"}
|
"items": {"type": "string"},
|
||||||
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"list_or_dict": {
|
"list_or_dict": {
|
||||||
|
@ -842,7 +848,7 @@
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
{"type": "array", "items": {"type": "string"}}
|
{"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ github.com/cenkalti/backoff/v4
|
||||||
# github.com/cespare/xxhash/v2 v2.2.0
|
# github.com/cespare/xxhash/v2 v2.2.0
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
github.com/cespare/xxhash/v2
|
github.com/cespare/xxhash/v2
|
||||||
# github.com/compose-spec/compose-go/v2 v2.1.4
|
# github.com/compose-spec/compose-go/v2 v2.1.5
|
||||||
## explicit; go 1.21
|
## explicit; go 1.21
|
||||||
github.com/compose-spec/compose-go/v2/cli
|
github.com/compose-spec/compose-go/v2/cli
|
||||||
github.com/compose-spec/compose-go/v2/consts
|
github.com/compose-spec/compose-go/v2/consts
|
||||||
|
|
Loading…
Reference in New Issue