Repository: compose-spec/compose-go
Pull request #795 (2025-06-05 17:43:26)

Update go-yaml to the official fork
This PR updates go-yaml to the new official fork in the Yaml org, https://github.com/yaml/go-yaml 

glours: Hey @lionello 
It seems there is some conflicts to be resolved before we can merge the PR, can you handle this?

Patch:
diff --git a/cli/options.go b/cli/options.go
index 65bc4d7..13a3824 100644
--- a/cli/options.go
+++ b/cli/options.go
@@ -25,7 +25,7 @@ import (
 	"strings"
 
 	"github.com/sirupsen/logrus"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 
 	"github.com/compose-spec/compose-go/v2/consts"
 	"github.com/compose-spec/compose-go/v2/dotenv"
diff --git a/cmd/main.go b/cmd/main.go
index b734c71..e206909 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -24,7 +24,7 @@ import (
 	"os"
 
 	"github.com/compose-spec/compose-go/v2/cli"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 func main() {
diff --git a/go.mod b/go.mod
index 9133ce4..afd3c52 100644
--- a/go.mod
+++ b/go.mod
@@ -14,9 +14,9 @@ require (
 	github.com/sirupsen/logrus v1.9.0
 	github.com/stretchr/testify v1.8.4
 	github.com/xhit/go-str2duration/v2 v2.1.0
+	go.yaml.in/yaml/v3 v3.0.4
 	golang.org/x/sync v0.3.0
 	golang.org/x/text v0.14.0
-	gopkg.in/yaml.v3 v3.0.1
 	gotest.tools/v3 v3.4.0
 )
 
@@ -24,4 +24,5 @@ require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	golang.org/x/sys v0.5.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 788e3d6..8c45364 100644
--- a/go.sum
+++ b/go.sum
@@ -31,6 +31,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
 github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
 github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
+go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
diff --git a/loader/loader.go b/loader/loader.go
index 8e54af8..035c881 100644
--- a/loader/loader.go
+++ b/loader/loader.go
@@ -43,7 +43,7 @@ import (
 	"github.com/compose-spec/compose-go/v2/validation"
 	"github.com/go-viper/mapstructure/v2"
 	"github.com/sirupsen/logrus"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 // Options supported by Load
diff --git a/loader/reset.go b/loader/reset.go
index f975d6d..ea98dd9 100644
--- a/loader/reset.go
+++ b/loader/reset.go
@@ -22,7 +22,7 @@ import (
 	"strings"
 
 	"github.com/compose-spec/compose-go/v2/tree"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 )
 
 type ResetProcessor struct {
diff --git a/parsing.md b/parsing.md
index 54f29d8..d8ffbc6 100644
--- a/parsing.md
+++ b/parsing.md
@@ -1,11 +1,11 @@
 # Compose file parsing
 
-This document describes the logic parsing and merging compose file 
+This document describes the logic parsing and merging compose file
 and overrides.
 
 ## Phase 1: parse yaml document
 
-Yaml document is parsed using de-facto standard [go-yaml](https://github.com/go-yaml/yaml)
+Yaml document is parsed using de-facto standard [go-yaml](https://github.com/yaml/go-yaml)
 library. This one manages anchors and aliases, which are only supported within
 a yaml document (an override can't refer to another compose file anchor)
 
@@ -74,7 +74,7 @@ for `!reset` to remove an element from original service definition.
 A compose file can use `include` to rely on compose resources defined by third-parties
 as a separate compose file
 
-Included compose definition is fully parsed (as described in this document) then included 
+Included compose definition is fully parsed (as described in this document) then included
 to the compose yaml model being processed. Conflicting resources are detected and rejected
 
 The resulting compose model is equivalent to a copy/paste of the included compose model
@@ -82,19 +82,19 @@ The resulting compose model is equivalent to a copy/paste of the included compos
 
 # Phase 8: merge overrides
 
-If loaded document is an override, the yaml tree is merged with the one from 
+If loaded document is an override, the yaml tree is merged with the one from
 main compose file. `!reset` can be used to remove elements.
-The merge logic generally is "_append to lists, replace in mapping_" with a 
+The merge logic generally is "_append to lists, replace in mapping_" with a
 few exceptions:
 - shell commands always are replaced by an override
-- `options` is only merged if both file declare the same `driver`, otherwise 
+- `options` is only merged if both file declare the same `driver`, otherwise
   the override fully replaces the original.
 - Attributes which can be expressed both as a mapping and a sequence are converted
   so that merge can apply on equivalent data structures.
 
 # Phase 9: enforce unicity
 
-While modeled as a list, some attributes actually require some unicity to be 
+While modeled as a list, some attributes actually require some unicity to be
 applied. Volume mount definition for a service typically must be unique
 regarding the target mount path. As such attribute can be defined as a single
 string and set by a variable, we have to apply the "_append to list_" merge
@@ -113,7 +113,7 @@ must result into an error being reported to the user
 networks:
   foo:
     external: true
-    driver: macvlan # This will trigger an error, as external network should not have any resource creation parameter set 
+    driver: macvlan # This will trigger an error, as external network should not have any resource creation parameter set
 ```
 
 # Phase 11: transform into canonical representation
@@ -123,13 +123,13 @@ syntax. It also supports use of single string or list of strings for some
 repeatable attributes. Some attributes can be declared both as a list of
 key=value strings or as a yaml mapping.
 
-During loading, all those attributes are transformed into canonical 
+During loading, all those attributes are transformed into canonical
 representation, so that we get a single format that will match to go structs
 for binding.
 
 # Phase 12: set-defaults
 
-Some attributes are required by the model but optional in the compose file, as an implicit 
+Some attributes are required by the model but optional in the compose file, as an implicit
 default value is defined by the specification, like [`build.context`](https://github.com/compose-spec/compose-spec/blob/master/build.md#context)
 During this phase, such unset attributes get default value assigned.
 
@@ -162,7 +162,7 @@ volumes:
 
 Eventually, the yaml tree can be unmarshalled into go structs. We rely on
 [mapstructure](https://github.com/go-viper/mapstructure/) library for this purpose.
-Decoder is configured so that custom decode function can be defined by target type, 
+Decoder is configured so that custom decode function can be defined by target type,
 allowing type conversions. For example, byte units (`640k`) and durations set in yaml
 as plain string are actually modeled in go types as `int64`.
 
diff --git a/types/command.go b/types/command.go
index 90d575d..7e56ce2 100644
--- a/types/command.go
+++ b/types/command.go
@@ -34,7 +34,7 @@ import "github.com/mattn/go-shellwords"
 // preserved so that it can override any base value (e.g. container entrypoint).
 //
 // The different semantics between YAML and JSON are due to limitations with
-// JSON marshaling + `omitempty` in the Go stdlib, while gopkg.in/yaml.v3 gives
+// JSON marshaling + `omitempty` in the Go stdlib, while go.yaml.in/yaml/v3 gives
 // us more flexibility via the yaml.IsZeroer interface.
 //
 // In the future, it might make sense to make fields of this type be
@@ -58,7 +58,7 @@ func (s ShellCommand) IsZero() bool {
 // accurately if the `omitempty` struct tag is omitted/forgotten.
 //
 // A similar MarshalJSON() implementation is not needed because the Go stdlib
-// already serializes nil slices to `null`, whereas gopkg.in/yaml.v3 by default
+// already serializes nil slices to `null`, whereas go.yaml.in/yaml/v3 by default
 // serializes nil slices to `[]`.
 func (s ShellCommand) MarshalYAML() (interface{}, error) {
 	if s == nil {
diff --git a/types/project.go b/types/project.go
index eab046a..52e13bc 100644
--- a/types/project.go
+++ b/types/project.go
@@ -32,8 +32,8 @@ import (
 	"github.com/compose-spec/compose-go/v2/utils"
 	"github.com/distribution/reference"
 	godigest "github.com/opencontainers/go-digest"
+	"go.yaml.in/yaml/v3"
 	"golang.org/x/sync/errgroup"
-	"gopkg.in/yaml.v3"
 )
 
 // Project is the result of loading a set of compose files


Test patch:
diff --git a/loader/normalize_test.go b/loader/normalize_test.go
index d85d0b1..eb2c9e4 100644
--- a/loader/normalize_test.go
+++ b/loader/normalize_test.go
@@ -20,7 +20,7 @@ import (
 	"testing"
 
 	"github.com/compose-spec/compose-go/v2/types"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 	"gotest.tools/v3/assert"
 )
 
@@ -78,23 +78,23 @@ networks:
 func TestNormalizeVolumes(t *testing.T) {
 	project := `
 name: myProject
-volumes:  
-  myExternalVol: 
+volumes:
+  myExternalVol:
     external: true
   myvol: {}
-  myNamedVol: 
+  myNamedVol:
     name: CustomName
 `
 
 	expected := `
 name: myProject
-volumes:  
-  myExternalVol: 
+volumes:
+  myExternalVol:
     name: myExternalVol
     external: true
-  myvol: 
+  myvol:
     name: myProject_myvol
-  myNamedVol: 
+  myNamedVol:
     name: CustomName
 `
 	var model map[string]any
@@ -114,14 +114,14 @@ func TestNormalizeDependsOn(t *testing.T) {
 name: myProject
 services:
   foo:
-    depends_on: 
+    depends_on:
       bar:
         condition: service_healthy
         required: true
         restart: true
     network_mode: service:zot
 
-  bar: 
+  bar:
     volumes_from:
       - zot
       - container:xxx
@@ -184,7 +184,7 @@ services:
     volumes_from: [quux]
     links: [corge]
     depends_on: # explicit dependency MUST not be overridden
-      foo: 
+      foo:
         condition: service_healthy
 `
 
@@ -199,25 +199,25 @@ services:
     volumes_from: [quux]
     links: [corge]
     depends_on: # explicit dependency MUST not be overridden
-      foo: 
+      foo:
         condition: service_healthy
-      bar: 
+      bar:
         condition: service_started
         restart: true
         required: true
-      baz: 
+      baz:
         condition: service_started
         restart: true
         required: true
-      qux: 
+      qux:
         condition: service_started
         restart: true
         required: true
-      quux: 
+      quux:
         condition: service_started
         required: true
         restart: false
-      corge: 
+      corge:
         condition: service_started
         restart: true
         required: true
@@ -243,13 +243,13 @@ networks:
 func TestImplicitContextPath(t *testing.T) {
 	project := `
 name: myProject
-services: 
+services:
   test:
     build: {}
 `
 	expected := `
 name: myProject
-services: 
+services:
   test:
     build:
       context: .
@@ -276,7 +276,7 @@ networks:
 func TestNormalizeDefaultNetwork(t *testing.T) {
 	project := `
 name: myProject
-services:  
+services:
   test:
     image: test
 `
@@ -286,8 +286,8 @@ name: myProject
 networks:
   default:
     name: myProject_default
-services:  
-  test: 
+services:
+  test:
     image: test
     networks:
       default: null
@@ -307,8 +307,8 @@ services:
 func TestNormalizeCustomNetwork(t *testing.T) {
 	project := `
 name: myProject
-services:  
-  test: 
+services:
+  test:
     networks:
       my_network: null
 networks:
@@ -320,8 +320,8 @@ name: myProject
 networks:
   my_network:
     name: myProject_my_network
-services:  
-  test: 
+services:
+  test:
     networks:
       my_network: null
 `
@@ -340,8 +340,8 @@ services:
 func TestNormalizeEnvironment(t *testing.T) {
 	project := `
 name: myProject
-services:  
-  test: 
+services:
+  test:
     environment:
       - FOO
       - BAR
@@ -353,8 +353,8 @@ name: myProject
 networks:
   default:
     name: myProject_default
-services:  
-  test: 
+services:
+  test:
     environment:
       - FOO
       - BAR=bar
diff --git a/override/merge_test.go b/override/merge_test.go
index e218646..53bf761 100644
--- a/override/merge_test.go
+++ b/override/merge_test.go
@@ -19,7 +19,7 @@ package override
 import (
 	"testing"
 
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 	"gotest.tools/v3/assert"
 )
 
diff --git a/schema/schema_test.go b/schema/schema_test.go
index 9287ad1..0e46234 100644
--- a/schema/schema_test.go
+++ b/schema/schema_test.go
@@ -22,7 +22,7 @@ import (
 	"testing"
 
 	"github.com/santhosh-tekuri/jsonschema/v6"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 	"gotest.tools/v3/assert"
 )
 
diff --git a/transform/envfile_test.go b/transform/envfile_test.go
index ea14244..b6a5051 100644
--- a/transform/envfile_test.go
+++ b/transform/envfile_test.go
@@ -20,7 +20,7 @@ import (
 	"testing"
 
 	"github.com/compose-spec/compose-go/v2/tree"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 	"gotest.tools/v3/assert"
 )
 
diff --git a/types/types_test.go b/types/types_test.go
index 527cce3..f79ceac 100644
--- a/types/types_test.go
+++ b/types/types_test.go
@@ -23,7 +23,7 @@ import (
 	"strings"
 	"testing"
 
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
diff --git a/validation/validation_test.go b/validation/validation_test.go
index a2bfee0..bc8f8db 100644
--- a/validation/validation_test.go
+++ b/validation/validation_test.go
@@ -20,7 +20,7 @@ import (
 	"testing"
 
 	"github.com/compose-spec/compose-go/v2/tree"
-	"gopkg.in/yaml.v3"
+	"go.yaml.in/yaml/v3"
 	"gotest.tools/v3/assert"
 )