Relationships
#2492 Add a literal() CEL function so one string can mix swamp expressions with another service template syntax
Opened by hammz · 9/24/2026· Shipped 9/29/2026
Follow-up split out of #2424 (item 2 in that issue).
Request
A CEL function literal("...") that returns its string argument unchanged, so one value can mix a real swamp expression with another service's {{...}} template syntax and keep checking the swamp part:
message: ${{ inputs.env }} alert, crashed on ${{ literal('{{host.name}}') }}#2424 adds a per-field declaration for fields that are entirely foreign template text. This covers the mixed case.
Blocker
Every scanner for ${{ ... }} ends the expression at the first closing double brace, including one inside a CEL string literal. EXPRESSION_PATTERN in src/domain/expressions/expression_parser.ts is lazy (.+?), so ${{ literal('{{host.name}}') }} is extracted as literal('{{host.name and fails to parse. A plain CEL string literal such as ${{ '{{host.name}}' }} breaks the same way. Around 13 files carry their own ${{ regex (expression_parser, workflows/evaluate, for_each_expansion_service, trigger_input_resolver, workflows/validation_service, step_task, expression_evaluators, sensitive_field_extractor, env_var_detector, data_writer, vault_reference_extractor, deferred_expression, datastore_expression_resolver). They would all need a shared, quote-aware scanner.
Once the scanner is quote-aware, a plain CEL string literal already returns its text unchanged, so literal() is mostly readability sugar on top of that.
The model-validate malformed-expression check must also skip text inside quoted CEL strings, or it flags the braces that literal() protects.
Workaround today
CEL concatenation passes validate, method run and workflow run: ${{ '{' + '{host.name}' + '}' }}.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.