Skip to content

[go-fan] Go Module Review: goccy/go-yaml #16054

@github-actions

Description

@github-actions

🐹 Go Fan Report: goccy/go-yaml

Module Overview

github.com/goccy/go-yaml is a modern, pure-Go YAML parser and encoder built from scratch as a superior alternative to the de facto standard go-yaml/yaml library. This module provides exceptional parsing capabilities, beautiful error messages, and advanced features that make working with YAML a joy!

Why it's awesome:

  • ✅ Passes 60+ more YAML Test Suite cases than go-yaml/yaml
  • ✅ Written in idiomatic Go (not a C port)
  • Actively maintained - commits from TODAY (2026-02-16)!
  • ✅ Beautiful colored error messages with source code context
  • ✅ Advanced features like YAML Path, AST manipulation, anchor/alias support

Current Usage in gh-aw

Summary Statistics

  • Files Using Module: 47 files
  • Total API Calls: 101 occurrences across 45 files
  • Version: v1.19.2 (latest release, already up-to-date!)
  • Import Count: High usage throughout workflow compilation and parsing

Key APIs Used

  • yaml.Marshal() / yaml.Unmarshal() - Core marshaling/unmarshaling
  • yaml.MarshalWithOptions() - Custom marshaling with options
  • yaml.MapSlice / yaml.MapItem - Deterministic field ordering
  • yaml.EncodeOption - Customization (Indent, UseLiteralStyleIfMultiline)

Primary Use Cases

1. Workflow YAML Generation (pkg/workflow/yaml.go:185)

Excellent abstraction layer for generating GitHub Actions workflows with conventional field ordering:

// Custom function using yaml.MapSlice for deterministic ordering
func MarshalWithFieldOrder(data map[string]any, priorityFields []string) ([]byte, error) {
    orderedData := OrderMapFields(data, priorityFields)
    return yaml.MarshalWithOptions(orderedData, DefaultMarshalOptions...)
}

Why this is great:

  • Ensures workflows follow GitHub Actions conventions (name, on, permissions, jobs)
  • Makes git diffs meaningful and predictable
  • Improves readability for developers

2. Standard Marshal Options (pkg/workflow/yaml_options.go:13)

Centralized configuration for consistent YAML output:

var DefaultMarshalOptions = []yaml.EncodeOption{
    yaml.Indent(2),                        // GitHub Actions standard
    yaml.UseLiteralStyleIfMultiline(true), // Better multiline readability
}

3. YAML Parsing (pkg/parser/yaml_import.go:95)

Robust parsing of GitHub Actions workflow files with validation:

var workflow map[string]any
if err := yaml.Unmarshal(content, &workflow); err != nil {
    return "", "", fmt.Errorf("failed to parse YAML workflow: %w", err)
}

4. Error Handling (pkg/parser/yaml_error_test.go)

Custom error extraction with comprehensive test coverage for accurate error reporting.

Research Findings

Recent Updates (VERY Active!)

🔥 TODAY's Commits (2026-02-16)

  1. Fix empty sequence item consuming sibling mapping key (Fix: Ensure localhost domains are always included in Playwright allowed_domains #850)

    • Fixed parser ambiguity when empty - is followed by mapping key
    • Prevents incorrect YAML parsing in edge cases
  2. Fix sibling anchor aliases silently resolving to nil (Update Playwright MCP configuration to use Docker instead of npx #848)

    • Fixed context map mutation causing false self-recursion detection
    • Ensures anchor references work correctly in nested structures

These fixes show the library is extremely responsive to bugs!

Recent Releases

v1.19.2 (2026-01-08) - Current version ✅

  • Fix anchor reference regression in nested structures

v1.19.1 (2025-12-17)

  • Fix decoding of integer map keys
  • Support line comments for flow sequences/maps

v1.19.0 (2025-11-29)

  • RawMessage support (like json.RawMessage) - NEW!
  • Non-string map keys - NEW!
  • Normalize CR/CRLF in multiline strings
  • Decode option for field prefixes

Best Practices from Maintainers

  1. Use yaml.MapSlice for deterministic ordering ✅ - Already doing this!
  2. Leverage FormatErrorWithToken() for pretty errors - Opportunity
  3. Use YAML Path for queries - Not currently utilized
  4. Consider RawMessage for deferred decoding - Could be useful
  5. Register custom marshalers for domain types - Advanced feature

Improvement Opportunities

🏃 Quick Wins

1. Explore YAML Path for Query Operations (Low Effort, HIGH Value)

What: Built-in YAML Path support for querying YAML structures

Example Usage:

path, err := yaml.PathString("$.jobs[*].steps[?(@.uses)]")
var actionSteps []string
if err := path.Read(strings.NewReader(yamlContent), &actionSteps); err != nil {
    // handle error
}
// actionSteps now contains all steps that use actions!

Potential Applications:

  • Workflow validation: Find all action usages, check versions
  • Security analysis: Query for secrets usage patterns
  • Metrics collection: Extract job dependencies, step counts
  • Configuration extraction: Pull specific values without full unmarshal

Benefit: Simpler, more expressive code for workflow analysis and validation.

2. Consider Using FormatErrorWithToken for Error Messages

What: Native API for formatting YAML errors with source context

Current State: Custom regex parsing in pkg/parser/yaml_error_test.go

Opportunity: Use yaml.FormatError() or FormatErrorWithToken() for consistent error formatting with better source code context and optional colorization.

3. Add Test Coverage for Recent Bug Fixes

What: Add test cases for edge cases fixed in #850 and #848

Why: TODAY's commits fix subtle parser bugs. Adding tests ensures gh-aw workflows don't hit these edge cases.

Where: Test files that parse complex YAML with anchors or empty sequences.

✨ Feature Opportunities

4. Consider RawMessage for Dynamic Workflow Schemas

What: New yaml.RawMessage type (added in v1.19.0) for deferred decoding

Use Case: Workflow steps with variable schemas where structure isn't known upfront

Example:

type WorkflowStep struct {
    Name string           `yaml:"name"`
    ID   string           `yaml:"id,omitempty"`
    Uses string           `yaml:"uses,omitempty"`
    Raw  yaml.RawMessage  `yaml:",inline"` // Defer decoding
}

Benefit: More flexible parsing of extensible workflow features.

5. Smart Anchor Option for Workflow Reuse

What: v1.16.0 feature for automatic anchor generation

Use Case: Generate workflows with reusable step definitions

Benefit: Automatic deduplication of repeated structures via YAML anchors/aliases, reducing workflow file size and improving maintainability.

6. Leverage YAML Playground for Debugging

What: Official playground at (goccy.github.io/redacted)

Use Case: Visualize YAML processing for debugging complex workflows

Benefit: Helps users understand how gh-aw parses and generates YAML.

📐 Best Practice Alignment

7. Already Excellent! ✅✅✅

The gh-aw codebase demonstrates exceptional usage of goccy/go-yaml:

  • Deterministic ordering via yaml.MapSlice
  • Consistent options via DefaultMarshalOptions
  • Clean abstractions (MarshalWithFieldOrder, OrderMapFields)
  • GitHub Actions conventions (field ordering, null handling, key unquoting)
  • Proper error handling with custom extraction
  • Separation of concerns (dedicated YAML files)

The custom MarshalWithFieldOrder() function is a textbook example of how to use yaml.MapSlice for deterministic YAML generation!

🔧 General Improvements

8. Document Library Choice

What: Add documentation explaining why goccy/go-yaml was chosen over go-yaml/yaml

Where: Architecture docs or contributing guide

Key Points:

  • 60+ more YAML Test Suite passes
  • Better error messages
  • Active maintenance (commits today!)
  • Native Go implementation
  • Advanced features (YAML Path, AST manipulation)

Benefit: Helps contributors understand the decision and appreciate the library's advantages.

9. Consider Using AutoInt Option

What: v1.16.0 option for automatic integer type inference

Where: Workflow input parsing with mixed number types

Benefit: Automatically decode YAML numbers as the most appropriate Go type (int, int64, uint, etc.).

10. Explore Custom Marshaler Context (v1.18.0)

What: Custom marshalers/unmarshalers now receive context

Use Case: Pass environment-specific state during workflow generation

Benefit: More flexible marshaling for complex domain objects.

Recommendations

Priority 1: Stay Current ✅ (Already Done!)

  • Status: gh-aw is on v1.19.2 (latest release)
  • Action: Continue monitoring for updates - this library is VERY active!

Priority 2: Explore YAML Path (Low Effort, High Value)

  • Effort: LOW - simple API, well-documented
  • Value: HIGH - could simplify many validation/query operations
  • Timeline: Experiment in workflow validation code
  • Example: Query for all GitHub Actions versions, check for outdated actions

Priority 3: Add Edge Case Tests (Low Effort, Medium Value)

  • Effort: LOW - add test cases
  • Value: MEDIUM - prevent regressions
  • Timeline: Next test cleanup sprint
  • What: Test empty sequences, nested anchors (recent bug fixes)

Priority 4: Consider RawMessage (Medium Effort, Medium Value)

  • Effort: MEDIUM - requires refactoring
  • Value: MEDIUM - better for extensible features
  • Timeline: When adding dynamic workflow features

Priority 5: Document Library Choice (Low Effort, Low Value)

  • Effort: LOW - write documentation
  • Value: LOW - nice-to-have for contributors
  • Timeline: During next documentation pass

Conclusion

gh-aw's usage of goccy/go-yaml is exemplary! 🎉

The codebase demonstrates:

  • ✅ Excellent abstractions (MarshalWithFieldOrder)
  • ✅ Proper use of advanced features (yaml.MapSlice)
  • ✅ Consistent configuration (DefaultMarshalOptions)
  • ✅ Clean separation of concerns
  • ✅ Already on the latest version

The main opportunities are optional enhancements rather than fixes:

  1. Explore YAML Path for simpler queries
  2. Consider RawMessage for future extensibility
  3. Add tests for recent bug fixes

Why This Module Rocks 🚀

  • 60+ more test cases passed than go-yaml/yaml
  • Active maintenance (commits from TODAY!)
  • Better errors with source code context and colors
  • Advanced features (YAML Path, anchors, AST manipulation)
  • Pure Go implementation (not a C port)
  • No dependencies
  • 2,109 stars and growing!

Module Summary Saved: scratchpad/mods/go-yaml.md

References:

Generated by Go Fan 🐹 - Your Daily Go Module Reviewer
Workflow Run: §22053663600


Note: This was intended to be a discussion, but discussions could not be created due to permissions issues. This issue was created as a fallback.

Tip: Discussion creation may fail if the specified category is not announcement-capable. Consider using the "Announcements" category or another announcement-capable category in your workflow configuration.

Generated by Go Fan

  • expires on Feb 23, 2026, 7:27 AM UTC

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions