From bf3c691d9e88add75d987a78eaf3f11e1e8ac042 Mon Sep 17 00:00:00 2001 From: Aleksey Levenstein Date: Fri, 17 Jul 2026 16:05:40 +0300 Subject: [PATCH 1/3] chore(deps): replace archived gopkg.in/yaml.v2 with go.yaml.in/yaml/v3 gopkg.in/yaml.v2 is archived. Switch config parsing to the maintained go.yaml.in/yaml/v3 (the YAML org's successor to gopkg.in/yaml.v3), which preserves yaml.v2 behavior: YAML 1.1 booleans (yes/no/on/off), octal-looking strings, strict unknown-field rejection, and the obsolete StringList unmarshaler. UnmarshalStrict is replaced by a decoder with KnownFields(true), treating an empty file as an empty config. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .golangci.yml | 7 ++++- docs/CHANGELOG.md | 1 + generate/config.go | 14 +++++++--- generate/generate_test.go | 7 +++-- .../TestValidConfigs-YAML11Booleans.yaml | 26 +++++++++++++++++++ .../testdata/validConfig/YAML11Booleans.yaml | 10 +++++++ go.mod | 2 +- go.sum | 4 +-- 8 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml create mode 100644 generate/testdata/validConfig/YAML11Booleans.yaml diff --git a/.golangci.yml b/.golangci.yml index ee64ed3b..dd04cc2f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -47,10 +47,15 @@ linters-settings: files: $all allow: - $gostd + # depguard resolves imports by longest-prefix match, so the + # "go.yaml.in/..." entry below registers a "go" prefix that shadows + # the shorter $gostd-provided stdlib "go/..." packages (go/token, + # go/ast, ...). Re-allow them explicitly. + - go/ - github.com/Khan/genqlient - github.com/vektah/gqlparser/v2 - golang.org/x/tools - - gopkg.in/yaml.v2 + - go.yaml.in/yaml/v3 - github.com/alexflint/go-arg - github.com/bmatcuk/doublestar/v4 - github.com/google/uuid diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7e6fe965..8b773e9c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -32,6 +32,7 @@ Note that genqlient now requires Go 1.23 or higher, and is tested through Go 1.2 ### Bug fixes: +- replaced the archived `gopkg.in/yaml.v2` dependency with the maintained `go.yaml.in/yaml/v3` (the YAML organization's successor to `gopkg.in/yaml.v3`) for config parsing. - fixed `pointer_omitempty` not being applied to list types when `use_struct_references` is enabled. List fields like `[String!]` now correctly get the `omitempty` JSON tag. - fixed minor typos and grammatical issues across the project diff --git a/generate/config.go b/generate/config.go index 9b37421c..e97548c8 100644 --- a/generate/config.go +++ b/generate/config.go @@ -1,15 +1,18 @@ package generate import ( + "bytes" _ "embed" + "errors" "fmt" "go/token" + "io" "os" "path/filepath" "strings" + "go.yaml.in/yaml/v3" "golang.org/x/tools/go/packages" - "gopkg.in/yaml.v2" ) var cfgFilenames = []string{".genqlient.yml", ".genqlient.yaml", "genqlient.yml", "genqlient.yaml"} @@ -322,8 +325,13 @@ func ReadAndValidateConfig(filename string) (*Config, error) { } var config Config - err = yaml.UnmarshalStrict(text, &config) - if err != nil { + // yaml.v3 has no UnmarshalStrict; a decoder with KnownFields(true) is the + // equivalent, rejecting unknown fields. An empty file decodes to io.EOF, + // which we treat as an empty config (as yaml.v2's UnmarshalStrict did). + dec := yaml.NewDecoder(bytes.NewReader(text)) + dec.KnownFields(true) + err = dec.Decode(&config) + if err != nil && !errors.Is(err, io.EOF) { return nil, errorf(nil, "invalid config file %v: %v", filename, err) } diff --git a/generate/generate_test.go b/generate/generate_test.go index 6db74343..42563aa1 100644 --- a/generate/generate_test.go +++ b/generate/generate_test.go @@ -1,6 +1,7 @@ package generate import ( + "bytes" "errors" "fmt" "os" @@ -9,7 +10,7 @@ import ( "strings" "testing" - "gopkg.in/yaml.v2" + "go.yaml.in/yaml/v3" "github.com/Khan/genqlient/internal/testutil" ) @@ -133,7 +134,9 @@ func getDefaultConfig(t *testing.T) *Config { t.Fatal(err) } - err = yaml.UnmarshalStrict(b, &config) + dec := yaml.NewDecoder(bytes.NewReader(b)) + dec.KnownFields(true) + err = dec.Decode(&config) if err != nil { t.Fatal(err) } diff --git a/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml b/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml new file mode 100644 index 00000000..12bfd7fd --- /dev/null +++ b/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml @@ -0,0 +1,26 @@ +(*generate.Config)({ + Schema: (generate.StringList) (len=1) { + (string) (len=35) "testdata/validConfig/schema.graphql" + }, + Operations: (generate.StringList) (len=1) { + (string) (len=39) "testdata/validConfig/operations.graphql" + }, + Generated: (string) (len=33) "testdata/validConfig/generated.go", + Package: (string) (len=11) "validConfig", + ExportOperations: (string) (len=25) "testdata/validConfig/0777", + ContextType: (string) (len=15) "context.Context", + ClientGetter: (string) "", + Bindings: (map[string]*generate.TypeBinding) , + PackageBindings: ([]*generate.PackageBinding) , + Casing: (generate.Casing) { + Default: (generate.CasingAlgorithm) "", + AllEnums: (generate.CasingAlgorithm) "", + Enums: (map[string]generate.CasingAlgorithm) + }, + Optional: (string) "", + OptionalGenericType: (string) "", + StructReferences: (bool) true, + Extensions: (bool) true, + baseDir: (string) (len=20) "testdata/validConfig", + pkgPath: (string) (len=55) "github.com/Khan/genqlient/generate/testdata/validConfig" +}) diff --git a/generate/testdata/validConfig/YAML11Booleans.yaml b/generate/testdata/validConfig/YAML11Booleans.yaml new file mode 100644 index 00000000..38f26961 --- /dev/null +++ b/generate/testdata/validConfig/YAML11Booleans.yaml @@ -0,0 +1,10 @@ +schema: schema.graphql +operations: operations.graphql + +# YAML 1.1 boolean spellings (yes/no/on/off) must still decode to bools, as +# they did under gopkg.in/yaml.v2, to avoid breaking existing config files. +use_struct_references: yes +use_extensions: on + +# Octal-looking strings must stay strings (e.g. "0777", not 511). +export_operations: 0777 diff --git a/go.mod b/go.mod index b07078e1..b0e62ca4 100644 --- a/go.mod +++ b/go.mod @@ -13,8 +13,8 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/stretchr/testify v1.9.0 github.com/vektah/gqlparser/v2 v2.5.19 + go.yaml.in/yaml/v3 v3.0.4 golang.org/x/tools v0.36.0 - gopkg.in/yaml.v2 v2.4.0 ) require ( diff --git a/go.sum b/go.sum index 2facde28..7c4c2c4f 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/vektah/gqlparser/v2 v2.5.19 h1:bhCPCX1D4WWzCDvkPl4+TP1N8/kLrWnp43egplt7iSg= github.com/vektah/gqlparser/v2 v2.5.19/go.mod h1:y7kvl5bBlDeuWIvLtA9849ncyvx6/lj06RsMrEjVy3U= +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/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= @@ -51,8 +53,6 @@ golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 596558b82ff8a3511768b7442281eba99c2678db Mon Sep 17 00:00:00 2001 From: Ben Kraft Date: Sat, 8 Aug 2026 14:58:52 -0700 Subject: [PATCH 2/3] Update generate/config.go --- generate/config.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/generate/config.go b/generate/config.go index e97548c8..1250a780 100644 --- a/generate/config.go +++ b/generate/config.go @@ -325,9 +325,6 @@ func ReadAndValidateConfig(filename string) (*Config, error) { } var config Config - // yaml.v3 has no UnmarshalStrict; a decoder with KnownFields(true) is the - // equivalent, rejecting unknown fields. An empty file decodes to io.EOF, - // which we treat as an empty config (as yaml.v2's UnmarshalStrict did). dec := yaml.NewDecoder(bytes.NewReader(text)) dec.KnownFields(true) err = dec.Decode(&config) From 6399789c8162fdc96a21cefa2933088b984504e6 Mon Sep 17 00:00:00 2001 From: Ben Kraft Date: Sat, 8 Aug 2026 15:02:00 -0700 Subject: [PATCH 3/3] Apply suggestion from @benjaminjkraft --- generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml b/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml index 12bfd7fd..43e882b9 100644 --- a/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml +++ b/generate/testdata/snapshots/TestValidConfigs-YAML11Booleans.yaml @@ -21,6 +21,7 @@ OptionalGenericType: (string) "", StructReferences: (bool) true, Extensions: (bool) true, + Flatten: (bool) false, baseDir: (string) (len=20) "testdata/validConfig", pkgPath: (string) (len=55) "github.com/Khan/genqlient/generate/testdata/validConfig" })