Skip to content

Commit b84ef1a

Browse files
authored
Merge pull request #305 from dgageot/better-yaml
Better yaml
2 parents b63071d + b774256 commit b84ef1a

10 files changed

Lines changed: 32 additions & 66 deletions

File tree

.golangci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,19 @@ linters:
3333
deny:
3434
- pkg: github.com/docker/cagent/internal
3535
desc: don't use /internal/ from /pkg/
36+
old_yaml:
37+
files:
38+
- "**/*.go"
39+
deny:
40+
- pkg: gopkg.in/yaml.v3
41+
desc: don't use deprecated gopkg.in/yaml.v3, use github.com/goccy/go-yaml instead
3642
testify_is_for_tests:
3743
files:
3844
- "**/*.go"
3945
- "!**/*_test.go"
4046
deny:
4147
- pkg: github.com/stretchr/testify
48+
desc: don't use testify in production code
4249
gocritic:
4350
disabled-checks:
4451
- dupImport

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018
1313
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250721205738-ea66aa652ee0
1414
github.com/fatih/color v1.18.0
15+
github.com/goccy/go-yaml v1.18.0
1516
github.com/google/go-containerregistry v0.20.6
1617
github.com/google/uuid v1.6.0
1718
github.com/labstack/echo/v4 v4.13.4
@@ -25,7 +26,6 @@ require (
2526
go.opentelemetry.io/otel/trace v1.38.0
2627
golang.org/x/term v0.34.0
2728
google.golang.org/genai v1.22.0
28-
gopkg.in/yaml.v3 v3.0.1
2929
modernc.org/sqlite v1.39.0
3030
)
3131

@@ -121,6 +121,7 @@ require (
121121
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
122122
google.golang.org/grpc v1.75.0 // indirect
123123
google.golang.org/protobuf v1.36.8 // indirect
124+
gopkg.in/yaml.v3 v3.0.1 // indirect
124125
modernc.org/libc v1.66.3 // indirect
125126
modernc.org/mathutil v1.7.1 // indirect
126127
modernc.org/memory v1.11.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
9191
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
9292
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
9393
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
94+
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
95+
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
9496
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
9597
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
9698
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=

pkg/config/config.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
v0 "github.com/docker/cagent/pkg/config/v0"
1010
v1 "github.com/docker/cagent/pkg/config/v1"
1111
latest "github.com/docker/cagent/pkg/config/v2"
12-
"gopkg.in/yaml.v3"
12+
"github.com/goccy/go-yaml"
1313
)
1414

1515
// LoadConfigSecure loads the configuration from a file with path validation
@@ -80,22 +80,22 @@ func ValidatePathInDirectory(path, allowedDir string) (string, error) {
8080
func loadConfig(path string) (*latest.Config, error) {
8181
data, err := os.ReadFile(path)
8282
if err != nil {
83-
return nil, fmt.Errorf("failed to read config file: %w", err)
83+
return nil, fmt.Errorf("reading config file: %w", err)
8484
}
8585

8686
var raw map[string]any
8787
if err := yaml.Unmarshal(data, &raw); err != nil {
88-
return nil, fmt.Errorf("failed to parse config file %s: %w", path, err)
88+
return nil, fmt.Errorf("parsing config file %s\n%s", path, yaml.FormatError(err, true, true))
8989
}
9090

9191
oldConfig, err := parseCurrentVersion(data, raw["version"])
9292
if err != nil {
93-
return nil, fmt.Errorf("failed to parse config file %s: %w", path, err)
93+
return nil, fmt.Errorf("parsing config file %s\n%s", path, yaml.FormatError(err, true, true))
9494
}
9595

9696
config, err := migrateToLatestConfig(oldConfig)
9797
if err != nil {
98-
return nil, fmt.Errorf("failed to migrate config: %w", err)
98+
return nil, fmt.Errorf("migrating config: %w", err)
9999
}
100100

101101
if err := validateConfig(&config); err != nil {

pkg/config/v0/load.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
package v0
22

3-
import (
4-
"bytes"
5-
6-
"gopkg.in/yaml.v3"
7-
)
3+
import "github.com/goccy/go-yaml"
84

95
func Load(data []byte) (Config, error) {
106
var cfg Config
11-
12-
decoder := yaml.NewDecoder(bytes.NewReader(data))
13-
decoder.KnownFields(true)
14-
err := decoder.Decode(&cfg)
15-
if err != nil {
16-
return cfg, err
17-
}
18-
19-
return cfg, nil
7+
err := yaml.UnmarshalWithOptions(data, &cfg, yaml.Strict())
8+
return cfg, err
209
}

pkg/config/v1/load.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
package v1
22

3-
import (
4-
"bytes"
5-
6-
"gopkg.in/yaml.v3"
7-
)
3+
import "github.com/goccy/go-yaml"
84

95
func Load(data []byte) (Config, error) {
106
var cfg Config
11-
12-
decoder := yaml.NewDecoder(bytes.NewReader(data))
13-
decoder.KnownFields(true)
14-
err := decoder.Decode(&cfg)
15-
if err != nil {
16-
return cfg, err
17-
}
18-
19-
return cfg, nil
7+
err := yaml.UnmarshalWithOptions(data, &cfg, yaml.Strict())
8+
return cfg, err
209
}

pkg/config/v2/load.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,9 @@
11
package v2
22

3-
import (
4-
"bytes"
5-
6-
"gopkg.in/yaml.v3"
7-
)
3+
import "github.com/goccy/go-yaml"
84

95
func Load(data []byte) (Config, error) {
106
var cfg Config
11-
12-
decoder := yaml.NewDecoder(bytes.NewReader(data))
13-
decoder.KnownFields(true)
14-
err := decoder.Decode(&cfg)
15-
if err != nil {
16-
return cfg, err
17-
}
18-
19-
return cfg, nil
7+
err := yaml.UnmarshalWithOptions(data, &cfg, yaml.Strict())
8+
return cfg, err
209
}

pkg/gateway/catalog.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"net/http"
88
"strings"
99

10-
"gopkg.in/yaml.v3"
10+
"github.com/goccy/go-yaml"
1111
)
1212

1313
const DockerCatalogURL = "https://desktop.docker.com/mcp/catalog/v2/catalog.yaml"

pkg/server/server.go

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ import (
1818
"time"
1919

2020
"dario.cat/mergo"
21-
"github.com/labstack/echo/v4"
22-
"github.com/labstack/echo/v4/middleware"
23-
"gopkg.in/yaml.v3"
24-
2521
"github.com/docker/cagent/pkg/api"
2622
"github.com/docker/cagent/pkg/config"
2723
latest "github.com/docker/cagent/pkg/config/v2"
@@ -35,6 +31,9 @@ import (
3531
"github.com/docker/cagent/pkg/session"
3632
"github.com/docker/cagent/pkg/team"
3733
"github.com/docker/cagent/pkg/teamloader"
34+
"github.com/goccy/go-yaml"
35+
"github.com/labstack/echo/v4"
36+
"github.com/labstack/echo/v4/middleware"
3837
)
3938

4039
type Server struct {
@@ -218,16 +217,11 @@ func (s *Server) editAgentConfig(c echo.Context) error {
218217
}
219218

220219
// Marshal the merged configuration to YAML
221-
var buf bytes.Buffer
222-
encoder := yaml.NewEncoder(&buf)
223-
encoder.SetIndent(2)
224-
err = encoder.Encode(mergedConfig)
220+
yamlData, err := yaml.MarshalWithOptions(mergedConfig, yaml.Indent(2))
225221
if err != nil {
226222
slog.Error("Failed to marshal merged config to YAML", "error", err)
227223
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to generate merged YAML configuration"})
228224
}
229-
encoder.Close()
230-
yamlData := buf.Bytes()
231225

232226
// Combine shebang, version, and merged YAML content
233227
finalContent := shebang + versionLine
@@ -346,16 +340,11 @@ func (s *Server) createAgentConfig(c echo.Context) error {
346340
}
347341

348342
// Marshal to YAML with custom indentation (2 spaces)
349-
var buf bytes.Buffer
350-
encoder := yaml.NewEncoder(&buf)
351-
encoder.SetIndent(1)
352-
err := encoder.Encode(agentConfig)
343+
yamlData, err := yaml.MarshalWithOptions(agentConfig, yaml.Indent(2))
353344
if err != nil {
354345
slog.Error("Failed to marshal agent config to YAML", "error", err)
355346
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to generate YAML configuration"})
356347
}
357-
encoder.Close()
358-
yamlData := buf.Bytes()
359348

360349
// Prepend shebang line to the YAML content
361350
shebang := "#!/usr/bin/env cagent run\nversion: \"1\"\n\n"

pkg/tools/mcp/gateway.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/docker/cagent/pkg/environment"
1313
"github.com/docker/cagent/pkg/gateway"
1414
"github.com/docker/cagent/pkg/tools"
15-
"gopkg.in/yaml.v3"
15+
"github.com/goccy/go-yaml"
1616
)
1717

1818
const ENV_DOCKER_MCP_URL_PREFIX = "DOCKER_MCP_URL_"

0 commit comments

Comments
 (0)