feat(config): unify env and forced_env with interpolation support#6
feat(config): unify env and forced_env with interpolation support#6
Conversation
Merge `env` and `forced_env` into a single `env` key with three value types:
- Exact credential reference: value matches a defined credential name
- Template interpolation: `{{ credential-name }}` substituted inline
- Literal value: no credential refs, used as-is
All env entries are now admin-controlled (forced) and cannot be overridden
by client requests.
Changes:
- Add interpolate.go with FindCredentialRefs, Interpolate, ResolveEnvValue
- Update config validation to support unified env with template refs
- Update executor to use ResolveEnvValue for all three value types
- Deprecate forced_env (still works with warning)
- Update README with new env syntax documentation
BREAKING: None - forced_env still works (deprecated)
There was a problem hiding this comment.
Pull request overview
This PR unifies the env and forced_env configuration fields into a single env key that supports three value types: exact credential references, template interpolation with {{ credential-name }} syntax, and literal values. All entries are admin-controlled and cannot be overridden by client requests. The forced_env field is deprecated but remains functional for backward compatibility.
Changes:
- Introduces a new interpolation module (
internal/config/interpolate.go) with functions for parsing and resolving credential references in env values - Updates config validation to handle the three env value types (exact credential, interpolated template, or literal)
- Modifies executor environment building to use the new unified env resolution system
- Adds comprehensive unit tests for interpolation logic and updates existing tests for the unified behavior
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
internal/config/interpolate.go |
New module implementing credential reference parsing, classification, and interpolation with {{ name }} syntax |
internal/config/interpolate_test.go |
Comprehensive unit tests for all interpolation functions covering edge cases and error scenarios |
internal/config/config.go |
Updated validation logic to support unified env with three value types and emit deprecation warnings for forced_env |
internal/config/config_test.go |
Updated tests to reflect new behavior where plain values are literals and only {{ refs }} require credentials |
internal/daemon/executor.go |
Modified environment building to resolve env values using the new classification and interpolation system |
internal/daemon/executor_env_test.go |
New tests verifying literal values, override protection, and admin-controlled dangerous variables in unified env |
README.md |
Updated documentation with clear examples of the three env value types and deprecation notice for forced_env |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
internal/config/interpolate.go
Outdated
| // NormalizeCredentialRef trims whitespace from a credential ref. | ||
| // "{{ foo }}" → "foo" | ||
| func NormalizeCredentialRef(ref string) string { | ||
| return strings.TrimSpace(ref) | ||
| } |
There was a problem hiding this comment.
The NormalizeCredentialRef function is defined but never used in the codebase. Consider removing it to reduce dead code, or if it's intended for future use, document its purpose and mark it with a TODO comment.
internal/daemon/executor.go
Outdated
| } | ||
| if value == "" { | ||
| return nil, fmt.Errorf("empty credential: %s", credName) | ||
| return "", fmt.Errorf("empty value") |
There was a problem hiding this comment.
The error message "empty value" doesn't include the credential name, which could make debugging harder. Consider including the credential name in the error: fmt.Errorf("credential %s returned empty value", name). This error will be wrapped with the env var name at line 291, providing full context.
- Remove unused NormalizeCredentialRef function (dead code) - Improve error message to include credential name for debugging
Dead code - logic already inlined in ClassifyEnvValue.
Summary
envandforced_envinto a singleenvkey with three value types:{{ credential-name }}→ substituted inlineforced_env(still works with warning for backward compatibility)Example
Test plan
interpolate_test.go)go test ./...)