Skip to content

feat: Add !literal YAML function to preserve template syntax#1879

Merged
aknysh merged 4 commits intomainfrom
osterman/yaml-literal-function
Dec 17, 2025
Merged

feat: Add !literal YAML function to preserve template syntax#1879
aknysh merged 4 commits intomainfrom
osterman/yaml-literal-function

Conversation

@osterman
Copy link
Member

@osterman osterman commented Dec 16, 2025

What

Add a new !literal YAML function that preserves values exactly as written, bypassing template processing. This enables passing template-like syntax ({{...}}, ${...}) to downstream tools without Atmos attempting to evaluate them.

Why

Users frequently need to pass template syntax to Terraform, Helm, ArgoCD, and other tools. Previously, they had to use awkward escaping patterns like "{{'{{value}}'}}". The !literal function provides a clean, self-documenting solution that resolves this common pain point.

References

  • Implements feature discussed in YAML functions design
  • Improves DX by eliminating need for complex escape sequences
  • Follows existing patterns like !include.raw and !template

See documentation for usage examples and common use cases.

Summary by CodeRabbit

  • New Features

    • Added a YAML literal function (!literal) that preserves values exactly as written, bypassing template processing to safely pass template-like syntax to downstream tools (Terraform, Helm, ArgoCD, Kustomize).
  • Documentation

    • New docs page, examples, and a blog post demonstrating usage and common scenarios.
  • Tests

    • Comprehensive test coverage across scalars, lists, multiline values, special characters, nesting, and mixed-tag scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

Add a new !literal YAML function that bypasses template processing to preserve values exactly as written. This enables passing template-like syntax ({{...}}, ${...}) to downstream tools like Terraform, Helm, and ArgoCD without Atmos attempting to evaluate them.

- Add AtmosYamlFuncLiteral constant and register in YAML tags map
- Implement early processing of !literal tags in processCustomTags()
- Add 8 comprehensive unit tests covering various use cases
- Document the feature with full API reference and examples
- Update YAML functions index page with !literal entry
- Add blog post explaining the feature and use cases

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@osterman osterman requested a review from a team as a code owner December 16, 2025 21:28
@github-actions github-actions bot added the size/l Large size PR label Dec 16, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

📝 Walkthrough

Walkthrough

Adds a new YAML tag function !literal that marks YAML nodes to be preserved verbatim (no Atmos template evaluation); includes PRD, implementation in YAML utilities, tests covering behaviors, and user-facing docs plus a blog post.

Changes

Cohort / File(s) Summary
PRD & Design
docs/prd/yaml-literal-function.md
New PRD describing problem, proposed !literal syntax/behavior, implementation approach, alternatives, and success metrics.
Core YAML utils
pkg/utils/yaml_utils.go
Adds AtmosYamlFuncLiteral constant; registers it in AtmosYamlTags and atmosYamlTagsMap; updates processCustomTags to clear !literal tag and preserve node value without template evaluation.
Tests
pkg/utils/yaml_utils_test.go
New tests for !literal: preserves template-like syntax, works in lists, multiline scalars, preserves special characters, mixes with other tags, empty values, nested maps, and inline arrays.
Documentation
website/docs/functions/yaml/literal.mdx, website/docs/functions/yaml/index.mdx
New function doc page and index updates with examples (Terraform, Helm, ArgoCD, Kustomize), rationale, and usage guidance.
Blog post
website/blog/2025-12-16-literal-yaml-function.mdx
New blog announcing !literal, with examples and quick-start guidance for downstream tool use cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify processCustomTags reliably clears the !literal tag and that preserved values skip any template evaluation pipeline.
  • Confirm atmosYamlTagsMap lookup behavior matches other tags and covers scalars, sequences, and mappings without edge-case regressions.
  • Review new tests for coverage of nested and inline scenarios and ensure no false positives/negatives in parsing.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: introducing a new !literal YAML function to preserve template syntax without processing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/yaml-literal-function

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e9dd9e7 and f0424a3.

📒 Files selected for processing (2)
  • pkg/utils/yaml_utils_test.go (2 hunks)
  • website/docs/functions/yaml/index.mdx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • pkg/utils/yaml_utils_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • pkg/utils/yaml_utils_test.go
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/functions/yaml/index.mdx
🧠 Learnings (11)
📓 Common learnings
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:37.766Z
Learning: cloudposse/atmos: For PRD docs (docs/prd/*.md), markdownlint issues like MD040/MD010/MD034 can be handled in a separate documentation cleanup commit and should not block the current PR.
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Applied to files:

  • pkg/utils/yaml_utils_test.go
  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions for performance tracking; use nil if no atmosConfig param

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2024-12-12T15:17:45.245Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: examples/demo-atmos.d/atmos.d/tools/helmfile.yml:10-10
Timestamp: 2024-12-12T15:17:45.245Z
Learning: In `examples/demo-atmos.d/atmos.d/tools/helmfile.yml`, when suggesting changes to `kubeconfig_path`, ensure that the values use valid Go template syntax.

Applied to files:

  • website/docs/functions/yaml/index.mdx
🧬 Code graph analysis (1)
pkg/utils/yaml_utils_test.go (3)
pkg/utils/yaml_utils.go (2)
  • AtmosYamlFuncLiteral (33-33)
  • UnmarshalYAMLFromFileWithPositions (729-783)
pkg/schema/schema.go (1)
  • AtmosConfiguration (54-99)
cmd/cmd_utils.go (1)
  • Contains (1257-1264)
🪛 LanguageTool
website/docs/functions/yaml/index.mdx

[style] ~82-~82: Consider using the typographical ellipsis character here instead.
Context: ... it to pass template-like syntax (e.g., {{...}} or ${...}) to downstream tools ...

(ELLIPSIS)


[style] ~82-~82: Consider using the typographical ellipsis character here instead.
Context: ...emplate-like syntax (e.g., {{...}} or ${...}) to downstream tools like Terrafor...

(ELLIPSIS)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Summary
🔇 Additional comments (3)
website/docs/functions/yaml/index.mdx (1)

185-189: Excellent examples demonstrating !literal usage.

The examples clearly show how to use !literal to preserve template syntax for downstream tools (Helm, Terraform) and cover both single values and arrays.

pkg/utils/yaml_utils_test.go (2)

766-766: Proper test maintenance for the new tag.

Correctly adds AtmosYamlFuncLiteral to the expected tags list, ensuring the map validation test covers the new !literal tag.


992-1149: Comprehensive test coverage for the !literal tag.

The eight test functions provide excellent coverage of the new !literal YAML function:

  • Basic template syntax preservation
  • Different YAML styles (block and flow)
  • Edge cases (empty values, special characters, multiline)
  • Integration with other tags
  • Various contexts (maps, lists, nested structures)

All tests follow best practices with clear assertions and meaningful test data.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 16, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

@osterman osterman added the minor New features that do not break anything label Dec 16, 2025
@codecov
Copy link

codecov bot commented Dec 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.04%. Comparing base (40387cd) to head (f0424a3).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1879      +/-   ##
==========================================
+ Coverage   73.00%   73.04%   +0.04%     
==========================================
  Files         606      606              
  Lines       56336    56339       +3     
==========================================
+ Hits        41127    41153      +26     
+ Misses      12296    12276      -20     
+ Partials     2913     2910       -3     
Flag Coverage Δ
unittests 73.04% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/utils/yaml_utils.go 81.84% <100.00%> (+0.15%) ⬆️

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aknysh
Copy link
Member

aknysh commented Dec 16, 2025

@coderabbitai full review please

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

@aknysh: I'll conduct a full review of all the changes in this PR.


🧠 Learnings used
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

@aknysh: I'll conduct a comprehensive review of all the changes in this PR, including the implementation, tests, documentation, and PRD.


🧠 Learnings used
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.

Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:37.766Z
Learning: cloudposse/atmos: For PRD docs (docs/prd/*.md), markdownlint issues like MD040/MD010/MD034 can be handled in a separate documentation cleanup commit and should not block the current PR.
✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/utils/yaml_utils_test.go (1)

1089-1092: Clarify the comment about !random processing.

The comment states "actual processing happens later in the pipeline," but at this YAML parsing stage, the !random tag is simply preserved as a string value like "!random 100" without any random number generation. Consider clarifying that the test verifies the tag is preserved (not processed yet) rather than implying processing occurs.

Apply this diff to clarify:

-	// Random should be processed (value will be a string like "!random 100" at this stage,
-	// actual processing happens later in the pipeline).
-	// We just verify it's present and not the literal "!random 100".
+	// Random tag is preserved for later processing (at this stage it's stored as "!random 100").
+	// We just verify the key is present in the result.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 40387cd and e9dd9e7.

📒 Files selected for processing (6)
  • docs/prd/yaml-literal-function.md (1 hunks)
  • pkg/utils/yaml_utils.go (4 hunks)
  • pkg/utils/yaml_utils_test.go (2 hunks)
  • website/blog/2025-12-16-literal-yaml-function.mdx (1 hunks)
  • website/docs/functions/yaml/index.mdx (2 hunks)
  • website/docs/functions/yaml/literal.mdx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in the website/ directory when adding new features, ensure consistency between CLI help text and website documentation, and follow the website's documentation structure and style
Keep website code in the website/ directory, follow the existing website architecture and style, and test website changes locally before committing
Keep CLI documentation and website documentation in sync and document new features on the website with examples and use cases

Files:

  • website/docs/functions/yaml/literal.mdx
  • website/docs/functions/yaml/index.mdx
  • website/blog/2025-12-16-literal-yaml-function.mdx
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: NEVER use fmt.Fprintf(os.Stdout/Stderr) or fmt.Println(); use data.* or ui.* functions instead
All comments must end with periods (enforced by godot linter)
Organize imports in three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages; maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions for performance tracking; use nil if no atmosConfig param
All errors MUST be wrapped using static errors defined in errors/errors.go; use errors.Join for combining multiple errors; use fmt.Errorf with %w for adding string context; use error builder for complex errors; use errors.Is() for error checking; NEVER use dynamic errors directly
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation; never create manual mocks
Keep files small...

Files:

  • pkg/utils/yaml_utils.go
  • pkg/utils/yaml_utils_test.go
website/blog/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

website/blog/**/*.mdx: Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, after intro, and only tags from website/blog/tags.yml
Blog posts MUST use only tags defined in website/blog/tags.yml and authors defined in website/blog/authors.yml; valid tags are: feature, enhancement, bugfix, dx, breaking-change, security, documentation, deprecation, core; never invent new tags

Files:

  • website/blog/2025-12-16-literal-yaml-function.mdx
docs/prd/**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

All Product Requirement Documents (PRDs) MUST be placed in docs/prd/ with kebab-case filenames

Files:

  • docs/prd/yaml-literal-function.md
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Prefer unit tests with mocks over integration tests; use interfaces + dependency injection for testability; generate mocks with go.uber.org/mock/mockgen; use table-driven tests; target >80% coverage
Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Files:

  • pkg/utils/yaml_utils_test.go
🧠 Learnings (20)
📓 Common learnings
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1868
File: tests/test-cases/auth-mock.yaml:243-245
Timestamp: 2025-12-16T01:01:24.471Z
Learning: In the Atmos test framework (tests/test-cases/*.yaml), the `!not` YAML tag in skip conditions has special semantics: `os: !not windows` means "skip on Windows" (not "skip on non-Windows"). The tag processing is project-specific and differs from standard boolean negation.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.
📚 Learning: 2024-12-03T04:01:16.446Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx:0-0
Timestamp: 2024-12-03T04:01:16.446Z
Learning: In the `terraform.output.mdx` documentation file (`website/docs/core-concepts/stacks/yaml-functions/terraform.output.mdx`), the cache invalidation and cache scope behavior for the `!terraform.output` function are already described.

Applied to files:

  • website/docs/functions/yaml/literal.mdx
  • website/docs/functions/yaml/index.mdx
  • website/blog/2025-12-16-literal-yaml-function.mdx
📚 Learning: 2024-12-01T00:33:20.298Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 810
File: examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml:28-32
Timestamp: 2024-12-01T00:33:20.298Z
Learning: In `examples/tests/stacks/catalog/terraform/template-functions-test2/defaults.yaml`, `!exec atmos terraform output` is used in examples to demonstrate its usage, even though `!terraform.output` is the recommended approach according to the documentation.

Applied to files:

  • website/docs/functions/yaml/literal.mdx
  • website/docs/functions/yaml/index.mdx
  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-16-literal-yaml-function.mdx
  • docs/prd/yaml-literal-function.md
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!env` is used to retrieve environment variables and assign them to sections in stack manifests. It supports both simple types (string, number, boolean) and complex types (JSON-encoded lists, maps, objects).

Applied to files:

  • website/docs/functions/yaml/literal.mdx
  • website/docs/functions/yaml/index.mdx
  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-16-literal-yaml-function.mdx
📚 Learning: 2025-09-30T19:03:50.738Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 1560
File: pkg/utils/string_utils.go:43-64
Timestamp: 2025-09-30T19:03:50.738Z
Learning: In the Atmos codebase, YAML tags like !terraform.output rely on positional arguments, so the SplitStringByDelimiter function in pkg/utils/string_utils.go must preserve empty strings (even after trimming quotes) to maintain the correct number of positional arguments. Filtering out empty values after trimming would collapse the array and break these function calls.

Applied to files:

  • website/docs/functions/yaml/literal.mdx
  • website/docs/functions/yaml/index.mdx
  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-16-literal-yaml-function.mdx
  • docs/prd/yaml-literal-function.md
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-01-19T22:30:27.600Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-01-19T22:30:27.600Z
Learning: The Atmos YAML function `!include` allows downloading local or remote files from different sources and assigning their contents to sections in stack manifests. It supports various protocols (file, http, git, s3, etc.) and can filter content using YQ expressions.

Applied to files:

  • website/docs/functions/yaml/index.mdx
  • pkg/utils/yaml_utils.go
  • website/blog/2025-12-16-literal-yaml-function.mdx
📚 Learning: 2024-12-12T15:17:45.245Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: examples/demo-atmos.d/atmos.d/tools/helmfile.yml:10-10
Timestamp: 2024-12-12T15:17:45.245Z
Learning: In `examples/demo-atmos.d/atmos.d/tools/helmfile.yml`, when suggesting changes to `kubeconfig_path`, ensure that the values use valid Go template syntax.

Applied to files:

  • website/docs/functions/yaml/index.mdx
📚 Learning: 2025-04-24T01:40:13.576Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1202
File: pkg/config/process_yaml.go:0-0
Timestamp: 2025-04-24T01:40:13.576Z
Learning: When processing YAML nodes with custom directives in Go using gopkg.in/yaml.v3, setting node.Tag = "" is sufficient to prevent re-processing of the node. It's not necessary to also clear node.Value after updating the configuration store (e.g., Viper), as the original value doesn't affect subsequent operations once the tag is removed.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions for performance tracking; use nil if no atmosConfig param

Applied to files:

  • pkg/utils/yaml_utils.go
  • pkg/utils/yaml_utils_test.go
📚 Learning: 2024-10-20T13:12:46.499Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 736
File: pkg/config/const.go:6-6
Timestamp: 2024-10-20T13:12:46.499Z
Learning: In `cmd/cmd_utils.go`, it's acceptable to have hardcoded references to `atmos.yaml` in logs, and it's not necessary to update them to use the `CliConfigFileName` constant.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Atmos uses Gitleaks pattern library (120+ patterns) for secret masking; disable with atmos terraform plan --mask=false

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to website/blog/**/*.mdx : Follow PR template (what/why/references); PRs labeled minor/major MUST include blog post at website/blog/YYYY-MM-DD-feature-name.mdx with YAML front matter, <!--truncate--> after intro, and only tags from website/blog/tags.yml

Applied to files:

  • website/blog/2025-12-16-literal-yaml-function.mdx
📚 Learning: 2025-12-13T06:07:34.794Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1686
File: docs/prd/tool-dependencies-integration.md:58-64
Timestamp: 2025-12-13T06:07:34.794Z
Learning: For docs in the cloudposse/atmos repository under docs/prd/, markdownlint issues MD040, MD010, and MD034 should be deferred to a separate documentation cleanup commit and must not block the current PR. If needed, address these issues in a follow-up PR dedicated to documentation improvements.

Applied to files:

  • docs/prd/yaml-literal-function.md
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-12-16T18:20:55.614Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T18:20:55.614Z
Learning: Applies to **/*_test.go : Test behavior, not implementation; never test stub functions; avoid tautological tests; make code testable via DI; no coverage theater; remove always-skipped tests; use errors.Is() for error checking

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • pkg/utils/yaml_utils_test.go
📚 Learning: 2025-12-16T01:01:24.471Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1868
File: tests/test-cases/auth-mock.yaml:243-245
Timestamp: 2025-12-16T01:01:24.471Z
Learning: In the Atmos test framework (tests/test-cases/*.yaml), the `!not` YAML tag in skip conditions has special semantics: `os: !not windows` means "skip on Windows" (not "skip on non-Windows"). The tag processing is project-specific and differs from standard boolean negation.

Applied to files:

  • pkg/utils/yaml_utils_test.go
🪛 LanguageTool
website/docs/functions/yaml/literal.mdx

[style] ~138-~138: Consider using the typographical ellipsis character here instead.
Context: ...tions. When your configuration contains {{...}} or ${...} syntax intended for down...

(ELLIPSIS)


[style] ~138-~138: Consider using the typographical ellipsis character here instead.
Context: ...our configuration contains {{...}} or ${...} syntax intended for downstream tools,...

(ELLIPSIS)


[style] ~196-~196: Consider using the typographical ellipsis character here instead.
Context: ...se !literal whenever you need to pass {{...}}, ${...}, or similar template synta...

(ELLIPSIS)


[style] ~196-~196: Consider using the typographical ellipsis character here instead.
Context: ...lwhenever you need to pass{{...}}, ${...}`, or similar template syntax to a down...

(ELLIPSIS)


[style] ~196-~196: Using many exclamation marks might seem excessive (in this case: 12 exclamation marks for a text that’s 2291 characters long)
Context: ...ing to evaluate something it shouldn't, !literal is the solution. :::

(EN_EXCESSIVE_EXCLAMATION)

website/docs/functions/yaml/index.mdx

[style] ~82-~82: Consider using the typographical ellipsis character here instead.
Context: ... it to pass template-like syntax (e.g., {{...}} or ${...}) to downstream tools ...

(ELLIPSIS)


[style] ~82-~82: Consider using the typographical ellipsis character here instead.
Context: ...emplate-like syntax (e.g., {{...}} or ${...}) to downstream tools like Terrafor...

(ELLIPSIS)


[grammar] ~83-~83: Please add a punctuation mark at the end of paragraph.
Context: ...CD without Atmos attempting to evaluate them - The [!aws.account_id](/functi...

(PUNCTUATION_PARAGRAPH_END)

website/blog/2025-12-16-literal-yaml-function.mdx

[style] ~97-~97: Using many exclamation marks might seem excessive (in this case: 3 exclamation marks for a text that’s 1185 characters long)
Context: ...{config_path}} ``` ## Get Started The !literal function is available now. Chec...

(EN_EXCESSIVE_EXCLAMATION)


[style] ~97-~97: The verb “check out” can sound colloquial in this context. Consider using a more formal alternative.
Context: ...e !literal function is available now. Check out the [documentation](/functions/yaml/lit...

(CHECK_OUT_OUR)

docs/prd/yaml-literal-function.md

[style] ~5-~5: Consider using the typographical ellipsis character here instead.
Context: ...ass through template-like syntax (e.g., {{...}}) to downstream tools without Atmos a...

(ELLIPSIS)


[typographical] ~65-~65: Consider using a typographic opening quote here.
Context: ... YAML tag function that marks values as "do not process." ### Syntax ```yaml # ...

(EN_QUOTES)


[typographical] ~65-~65: Consider using a typographic close quote here.
Context: ...on that marks values as "do not process." ### Syntax ```yaml # Single value ema...

(EN_QUOTES)


[typographical] ~101-~101: Consider using a typographic opening quote here.
Context: ...late processing in later stages ## Why "Nice to Have" (Not Critical) ### It's S...

(EN_QUOTES)


[typographical] ~101-~101: Consider using a typographic close quote here.
Context: ...ng in later stages ## Why "Nice to Have" (Not Critical) ### It's Solvable Today...

(EN_QUOTES)


[typographical] ~125-~125: Consider using a typographic opening quote here.
Context: ... - Consistent: One clear way to say "don't process this" - Readable: Inte...

(EN_QUOTES)


[typographical] ~125-~125: Consider using a typographic close quote here.
Context: ...One clear way to say "don't process this" - Readable: Intent is obvious at a ...

(EN_QUOTES)


[typographical] ~130-~130: Consider using a typographic opening quote here.
Context: ...educes Support Burden Common question: "How do I pass {{...}} to Terraform wit...

(EN_QUOTES)


[style] ~130-~130: Consider using the typographical ellipsis character here instead.
Context: ...Burden Common question: "How do I pass {{...}} to Terraform without Atmos processin...

(ELLIPSIS)


[typographical] ~156-~156: Consider using typographic quotation marks here.
Context: ...n| Simple | Too vague, doesn't convey "no processing" | Rejected | |!static` | Clear opposi...

(EN_QUOTES)


[typographical] ~157-~157: Consider using typographic quotation marks here.
Context: ...ected | | !static | Clear opposite of "dynamic" | Could be confused with static files/r...

(EN_QUOTES)


[typographical] ~165-~165: Consider using a typographic opening quote here.
Context: ...tructure engineers 3. Self-documenting: "this is the literal value, don't interpr...

(EN_QUOTES)


[typographical] ~165-~165: Consider using a typographic close quote here.
Context: ...is the literal value, don't interpret it" 4. Clear semantic meaning across progra...

(EN_QUOTES)


[typographical] ~199-~199: Consider using a typographic opening quote here.
Context: ...eral` is cleaner for the common case of "don't process this entire value." ## Su...

(EN_QUOTES)


[typographical] ~199-~199: Consider using a typographic close quote here.
Context: ...ase of "don't process this entire value." ## Success Metrics - Reduction in Git...

(EN_QUOTES)


[typographical] ~211-~211: Consider using typographic quotation marks here.
Context: ...les in template documentation 3. Add to "Common Patterns" or FAQ section ## Out of Scope - Part...

(EN_QUOTES)


[style] ~216-~216: Using many exclamation marks might seem excessive (in this case: 30 exclamation marks for a text that’s 5828 characters long)
Context: ... - Recursive literal (literal values in !include files) - handle separately if n...

(EN_EXCESSIVE_EXCLAMATION)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (8)
pkg/utils/yaml_utils_test.go (1)

992-1150: Excellent test coverage for the new !literal function.

The 8 test functions comprehensively cover the feature's behavior across various scenarios: template syntax preservation, list contexts, multiline values, special characters, mixed usage with other tags, empty values, nested structures, and inline arrays. The tests are well-focused and verify behavior rather than implementation details.

website/docs/functions/yaml/index.mdx (1)

186-189: Clear examples showing !literal usage.

The examples effectively demonstrate the three main use cases: Helm template expressions, Terraform variable syntax, and inline array usage. These align well with the documentation and help users understand when to use !literal.

website/blog/2025-12-16-literal-yaml-function.mdx (1)

1-97: Well-structured blog post meeting all requirements.

The blog post follows the required format with proper YAML front matter, uses an allowed tag ("feature"), includes the truncate marker after the intro, and provides clear problem/solution/use-cases structure. The examples are practical and demonstrate real-world scenarios effectively.

As per coding guidelines: PRs labeled minor/major must include a blog post, and this satisfies that requirement.

pkg/utils/yaml_utils.go (3)

33-33: Constant definition follows established pattern.

The new AtmosYamlFuncLiteral constant is correctly defined alongside other YAML function constants.


56-56: Tag registration is complete and correct.

The !literal tag is properly registered in both the AtmosYamlTags slice (for iteration) and atmosYamlTagsMap (for O(1) lookup). This ensures the tag is recognized by hasCustomTags and processCustomTags.

Also applies to: 75-75


611-619: Implementation correctly preserves literal values.

The !literal handling follows the established pattern for early-processed tags like !include. By clearing the tag and continuing without modification, the value passes through template processing untouched. The placement before the atmosYamlTagsMap check ensures !literal takes precedence.

website/docs/functions/yaml/literal.mdx (1)

1-197: Comprehensive documentation with excellent examples.

This documentation page is thorough and well-structured. It includes clear usage examples, covers diverse use cases (Terraform, Helm, ArgoCD, regex patterns), explains the problem it solves, and provides a comparison table with other functions. The tip box at the end gives users clear guidance on when to use !literal.

docs/prd/yaml-literal-function.md (1)

1-217: Thorough PRD documenting design decisions.

The PRD provides comprehensive context for the !literal feature, including problem statement, real-world use cases, naming alternatives with rationale, and clear scope boundaries. The decision to choose !literal over alternatives like !raw is well-justified. This document effectively captures the design thinking behind the feature.

As per coding guidelines: PRDs must be placed in docs/prd/ with kebab-case filenames, which is satisfied here.

@aknysh aknysh merged commit 41250de into main Dec 17, 2025
57 checks passed
@aknysh aknysh deleted the osterman/yaml-literal-function branch December 17, 2025 13:58
@github-actions
Copy link

These changes were released in v1.202.0-rc.5.

@github-actions
Copy link

These changes were released in v1.203.0-test.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything size/l Large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants