feat: Add !literal YAML function to preserve template syntax#1879
feat: Add !literal YAML function to preserve template syntax#1879
Conversation
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>
📝 WalkthroughWalkthroughAdds a new YAML tag function Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (2)
🧰 Additional context used📓 Path-based instructions (3)**/*.go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
**/*_test.go📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
website/**📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)
Files:
🧠 Learnings (11)📓 Common learnings📚 Learning: 2025-09-30T19:03:50.738ZApplied to files:
📚 Learning: 2025-11-24T17:35:37.209ZApplied to files:
📚 Learning: 2025-12-16T18:20:55.614ZApplied to files:
📚 Learning: 2025-12-16T18:20:55.614ZApplied to files:
📚 Learning: 2025-11-24T17:35:37.209ZApplied to files:
📚 Learning: 2024-12-01T00:33:20.298ZApplied to files:
📚 Learning: 2024-12-03T04:01:16.446ZApplied to files:
📚 Learning: 2025-01-19T22:30:27.600ZApplied to files:
📚 Learning: 2025-01-19T22:30:27.600ZApplied to files:
📚 Learning: 2024-12-12T15:17:45.245ZApplied to files:
🧬 Code graph analysis (1)pkg/utils/yaml_utils_test.go (3)
🪛 LanguageToolwebsite/docs/functions/yaml/index.mdx[style] ~82-~82: Consider using the typographical ellipsis character here instead. (ELLIPSIS) [style] ~82-~82: Consider using the typographical ellipsis character here instead. (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)
🔇 Additional comments (3)
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. Comment |
Dependency Review✅ No vulnerabilities or license issues found.Scanned FilesNone |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
@coderabbitai full review please |
|
@aknysh: I'll conduct a full review of all the changes in this PR. 🧠 Learnings used✅ Actions performedFull review triggered. |
|
@aknysh: I'll conduct a comprehensive review of all the changes in this PR, including the implementation, tests, documentation, and PRD. 🧠 Learnings used✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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.
📒 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 thewebsite/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 thewebsite/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.mdxwebsite/docs/functions/yaml/index.mdxwebsite/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 usingfmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: usegofmtandgoimportsto 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
Adddefer 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.gopkg/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.mdxwebsite/docs/functions/yaml/index.mdxwebsite/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.mdxwebsite/docs/functions/yaml/index.mdxpkg/utils/yaml_utils.gowebsite/blog/2025-12-16-literal-yaml-function.mdxdocs/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.mdxwebsite/docs/functions/yaml/index.mdxpkg/utils/yaml_utils.gowebsite/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.mdxwebsite/docs/functions/yaml/index.mdxpkg/utils/yaml_utils.gowebsite/blog/2025-12-16-literal-yaml-function.mdxdocs/prd/yaml-literal-function.mdpkg/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.mdxpkg/utils/yaml_utils.gowebsite/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.gopkg/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.
|
These changes were released in v1.202.0-rc.5. |
|
These changes were released in v1.203.0-test.1. |
What
Add a new
!literalYAML 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!literalfunction provides a clean, self-documenting solution that resolves this common pain point.References
!include.rawand!templateSee documentation for usage examples and common use cases.
Summary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.