Support multiple environment variable placeholders in config values#2070
Support multiple environment variable placeholders in config values#2070aantn wants to merge 3 commits into
Conversation
…and Holmes add-on env vars
- Warn that {{ env.X }} replaces the entire field value (no prefix/suffix concatenation)
- Document runner.additional_env_froms for bulk-injecting Secret/ConfigMap keys
- Clarify that runner and HolmesGPT pods do not share environment variables, so secrets used by both must be declared in both additional_env_vars blocks
- Mention holmes.operator.additionalEnvVars and holmes.mcpAddons.{aws,azure}.additionalEnvVars for users running those add-ons
…ering the whole value
Previously, get_env_replacement returned the env var's value as the new field
value, so `"Bearer {{ env.TOKEN }}"` was silently replaced with just the token
and any prefix/suffix was dropped. Switch to re.sub so only the placeholder is
substituted, leaving the rest of the string intact. Multiple placeholders in
the same field are also now supported (e.g. `"{{ env.USER }}:{{ env.PASSWORD }}"`).
The "return None when there is no placeholder" contract is preserved so
existing callers in runner_config.py and replace_env_vars_values keep working.
Also updates the docs to advertise the supported concatenation/multi-placeholder
patterns.
WalkthroughThis PR enhances environment variable placeholder substitution in Robusta configuration by introducing a new regex-based mechanism that replaces multiple ChangesEnvironment Variable Placeholder Substitution
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
✅ Docker image ready for
Use this tag to pull the image for testing. 📋 Copy commandsgcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:02d28b5
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/robusta-runner:02d28b5 me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:02d28b5
docker push me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:02d28b5Patch Helm values in one line: helm upgrade --install robusta robusta/robusta \
--reuse-values \
--set runner.image=me-west1-docker.pkg.dev/robusta-development/development/robusta-runner-dev:02d28b5 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/robusta/core/playbooks/playbook_utils.py`:
- Around line 19-24: The code currently treats empty environment variables as
missing by checking falsiness in the env lookup; update the existence checks to
use None semantics so empty strings are allowed: in the function that reads
env_var_value (the block using os.environ.get(name, None) and the subsequent if
not env_var_value check), change the condition to check "is None" before
logging/raising; likewise update the truthy checks in replace_env_vars_values
(the checks at the locations referenced in the comment) to use "is not None" so
that empty-string substitutions are preserved rather than treated as absent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e365fa0a-b831-48ab-8769-013525033bae
📒 Files selected for processing (2)
docs/setup-robusta/configuration-secrets.rstsrc/robusta/core/playbooks/playbook_utils.py
|
@claude review |
aantn
left a comment
There was a problem hiding this comment.
Review
(Disclosure: I authored the commits on this branch — this is a fresh-eyes pass for self-review.)
What's good
- The regex
r"{{\s*env\.([^}\s]+)\s*}}"is a real improvement over the old{{[ ]*env\.(.*)[ ]*}}. The old pattern was greedy and would mis-match across two adjacent placeholders ("{{ env.A }} {{ env.B }}"→ capture groupA }} {{ env.B). The new pattern stops at the first}or whitespace, so multi-placeholder values work correctly. - The
None-on-no-placeholder contract is preserved deliberately so existing callers (runner_config.py:_replace_env_var_in_playbook_repo,replace_env_vars_values) keep their if-checks working. Worth a docstring to make that explicit — easy to break in a future refactor. - Doc additions cover the three real gaps I'd seen users hit: bulk injection via
additional_env_froms, runner-vs-Holmes pod scoping, and Holmes add-on deployments.
Things worth considering
-
Silent behavior change for an edge case. Anyone today who wrote
"prefix {{ env.X }}"was silently getting just the env var's value (prefix dropped). They'll now getprefix<value>. The documented usage was always"{{ env.X }}"standalone, so I think real-world breakage is near zero — but it's worth a one-line entry inCHANGELOG.mdso anyone with surprising configs sees it on upgrade. -
No tests. This function had no test coverage before, which is partly how the bug shipped. A small
tests/file pinning the new behavior (prefix preserved, multiple placeholders, no-placeholder returnsNone, missing env var raises) would be cheap insurance. Happy to add it in a follow-up commit on this branch if you'd like. -
Minor perf:
re.searchthenre.subwalks the string twice on every matched value. Could collapse tonew, n = _ENV_PLACEHOLDER_RE.subn(_sub, value); return new if n else None. Negligible in practice — only flagging because it's in a config-load hot path. -
Pre-existing doc inconsistency I noticed: line 15 of
configuration-secrets.rst(unchanged here) refers tocustom_playbooks(snake_case), but the actual Helm key iscustomPlaybooks(camelCase, perhelm/robusta/values.yaml:193). Out of scope for this PR but worth a follow-up.
CodeRabbit's is None finding
Skipping. The "fail on empty env var" semantics is pre-existing (was if not env_var_value before this PR) and out of scope for a multi-placeholder-substitution change. Empty values from a Secret almost always indicate a misconfigured secretKeyRef, and failing loudly at startup is friendlier than silently injecting "" into something like an auth header. If we want to allow legitimately-empty values, it deserves a deliberate decision with its own PR and tests.
Recommendation
Merge after adding a changelog line. Optional follow-ups: tests for get_env_replacement, the subn micro-optimization, and the custom_playbooks doc fix.
Generated by Claude Code
Summary
Enhanced environment variable substitution in Robusta configuration to support multiple placeholders in a single field and improved the regex pattern for more robust matching.
Key Changes
{{ env.VAR }}placeholders (e.g.,"{{ env.USER }}:{{ env.PASSWORD }}") instead of just one"Bearer {{ env.TOKEN }}")_ENV_PLACEHOLDER_REthat properly handles whitespace and prevents over-matchingre.sub()with a callback function for proper multi-placeholder replacementImplementation Details
r"{{\s*env\.([^}\s]+)\s*}}"is more precise:env.}or whitespace to avoid capturing extra characters_sub()that processes each match independently, enabling proper handling of multiple placeholders in one valueDocumentation
Added comprehensive documentation covering:
runner.additional_env_fromsfeature for bulk secret injectionhttps://claude.ai/code/session_013EFjPwGU1FDY6fs6rcELac