Skip to content

Replace regex-based interpolation with character scanner#4747

Open
shreyas-goenka wants to merge 9 commits intomainfrom
interpolation-parser-pr1
Open

Replace regex-based interpolation with character scanner#4747
shreyas-goenka wants to merge 9 commits intomainfrom
interpolation-parser-pr1

Conversation

@shreyas-goenka
Copy link
Copy Markdown
Contributor

@shreyas-goenka shreyas-goenka commented Mar 15, 2026

Summary

Replaces the regex-based variable reference parser with a character scanner. No change in interpolation semantics — all existing configurations produce identical results.

  • Token-based parser in libs/interpolation/ with structured ParseError for precise diagnostics
  • WarnMalformedReferences mutator emits warnings for invalid references like ${foo.bar-}
  • Cross-language tests (testdata/variable_references.json) keep Go parser and Python regex in sync
  • Acceptance tests for malformed refs, nested refs (2-level and 3-level), edge cases

Test plan

  • go test ./libs/interpolation/... ./libs/dyn/dynvar/... ./bundle/config/mutator/...
  • Acceptance tests: var_in_var, var_in_var_3level, malformed_reference, bad_syntax, unterminated_ref, empty_ref, leading_digit_ref, dollar_before_non_brace
  • Both terraform and direct engines produce identical output

This pull request was AI-assisted by Isaac.

- Move interpolation parser to libs/interpolation/ (independent of dyn)
- Use \$ -> $ and \\ -> \ escape sequences (Bash convention)
- Reject nested ${} constructs as errors
- Replace strings.Replace interpolation with token-based concatenation
- Add WarnMalformedReferences mutator for early parse error warnings
- Add NewRefWithDiagnostics for surfacing parse errors as diagnostics

Co-authored-by: Isaac
@eng-dev-ecosystem-bot
Copy link
Copy Markdown
Collaborator

eng-dev-ecosystem-bot commented Mar 15, 2026

Commit: 033b1a2

Run: 23658316193

Env 🟨​KNOWN 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 10 270 816 7:38
🟨​ aws windows 7 10 272 814 6:17
💚​ aws-ucws linux 7 10 366 732 9:01
💚​ aws-ucws windows 7 10 368 730 6:13
💚​ azure linux 1 12 273 814 7:30
💚​ azure windows 1 12 275 812 5:38
💚​ azure-ucws linux 1 12 371 728 10:36
💚​ azure-ucws windows 1 12 373 726 6:25
💚​ gcp linux 1 12 269 817 6:20
💚​ gcp windows 1 12 271 815 4:58
17 interesting tests: 10 SKIP, 7 KNOWN
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_projects/update_display_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
Top 20 slowest tests (at least 2 minutes):
duration env testname
4:20 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:53 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:48 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:45 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:42 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:27 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:15 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:09 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:55 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:54 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:47 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:47 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:46 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:42 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:40 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:40 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:22 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:18 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:15 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:12 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

The var_in_var test used ${var.foo_${var.tail}} which relied on
undocumented nested reference behavior (the test itself noted:
"not officially supported... might start to reject this in the future").
The new parser now rejects nested ${} constructs as intended.

Co-authored-by: Isaac
Add acceptance tests for escape sequences, unterminated refs, empty refs,
leading digit keys, and dollar-before-non-brace. Consolidate standalone
unit tests into table-driven TestParse and TestParseErrors. Add breaking
change entry to NEXT_CHANGELOG for nested variable reference rejection.

Co-authored-by: Isaac
…errors

Add ParseError type to interpolation package so callers can access the
position offset separately from the message. Update WarnMalformedReferences
to include the config path (e.g. bundle.name) in diagnostics and incorporate
the position into the column location. Remove redundant Validate method.

Co-authored-by: Isaac
The parser now treats outer ${...} prefixes as literal text when a
nested ${ is encountered, allowing inner references to be resolved
first. Multi-round resolution progressively resolves from inside out.

Co-authored-by: Isaac
Shared test cases in libs/interpolation/testdata/variable_references.json
are consumed by both the Go parser (TestParsePureVariableReferences) and
the Python regex (test_pure_variable_reference) to verify they agree on
which strings are pure variable references.

When modifying the parser, add test cases to the JSON file so both
languages are validated.

Co-authored-by: Isaac
Escape sequences (\$ and \\) are incompatible with multi-round variable
resolution: escapes consumed in round N produce bare ${...} text that
round N+1 incorrectly resolves as a real variable reference. Remove
escape support entirely and defer to a follow-up if needed.

Co-authored-by: Isaac
Co-authored-by: Isaac
@shreyas-goenka
Copy link
Copy Markdown
Contributor Author

shreyas-goenka commented Mar 27, 2026

Note: As a followup we'll also add the ability to escape variable references in the syntax. This work enables us to add fancier syntax for interpolation in DABs and unblocks supporting variable interpolation for the script section in DABs.

@shreyas-goenka shreyas-goenka marked this pull request as ready for review March 27, 2026 17:15
@github-actions
Copy link
Copy Markdown

Suggested reviewers

Based on git history of the changed files, these people are best suited to review:

  • @denik -- recent work in ./, bundle/phases/, libs/dyn/dynvar/

Confidence: high

Eligible reviewers

Based on CODEOWNERS, these people or teams could also review:

@andrewnester, @anton-107, @pietern, @simonfaltum

Suggestions based on git history of 40 changed files (7 scored). See CODEOWNERS for path-specific ownership rules.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants