Add --from-secret and --from-env flags to set-build-env
Summary
Implement secure credential handling for build environment variables during protocol builds (npx://, uvx://, go://). This allows users to reference ToolHive secrets or shell environment variables instead of storing sensitive values in the configuration file.
Closes the implementation portion of the proposal in #2859
Large PR Justification
- Feature + Tests: ~350 lines are unit tests for the new functionality
- Interface changes must be atomic: The Provider interface requires all implementations to be updated simultaneously to avoid build failures
- Three-source resolution is interdependent: The
--from-secret,--from-env, and literal value paths share validation, conflict detection, and build-time resolution logic that cannot be meaningfully separated
New Features
--from-secret flag
Reference a ToolHive secret by name. The secret is validated to exist at configuration time and resolved at build time.
thv secret set npm-registry "https://:[email protected]"
thv config set-build-env --from-secret NPM_CONFIG_REGISTRY npm-registry
--from-env flag
Read value from the shell environment at build time. Useful for CI/CD where secrets are injected via environment.
thv config set-build-env --from-env GITHUB_TOKEN
# At build time, $GITHUB_TOKEN is read from the shell
Configuration Model
Three separate sections keep sensitive values out of the config file:
build_env:
GOPRIVATE: "github.com/myorg/*" # Literal values only
build_env_from_secrets:
NPM_CONFIG_REGISTRY: "npm-registry" # Secret name, not value
build_env_from_shell:
- GITHUB_TOKEN # Variable name only
Security
| Property | Description |
|---|---|
| No cleartext secrets | Config stores references, not values |
| Validation at config time | --from-secret validates secret exists |
| Validation at build time | Secret values checked for dangerous characters |
| Multi-stage isolation | Credentials only in builder stage, not final image |
Multi-Stage Build Isolation
All protocol build templates use multi-stage Docker builds. The BuildEnv variables are only set in the builder stage:
| Template | Final Stage Copies Only |
|---|---|
| npx.tmpl | node_modules, package.json, package-lock.json |
| uvx.tmpl | /opt/uv-tools |
| go.tmpl | /app/mcp-server binary |
Changes
pkg/config/config.go: AddBuildEnvFromSecretsandBuildEnvFromShellfieldspkg/config/interface.go: Add provider interface methodspkg/config/buildenv.go: Add helper functions and conflict checkingcmd/thv/app/config_buildenv.go: Add--from-secretand--from-envflagspkg/runner/protocol.go: Resolve values from all 3 sources at build timepkg/config/buildenv_test.go: Add unit tests
Test plan
- [x]
task lintpasses - [x]
task testpasses - [ ] Manual testing of
--from-secretworkflow - [ ] Manual testing of
--from-envworkflow
🤖 Generated with Claude Code
Codecov Report
:x: Patch coverage is 39.77273% with 106 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 56.58%. Comparing base (a5ff43f) to head (3e5e8b7).
:warning: Report is 5 commits behind head on main.
Additional details and impacted files
@@ Coverage Diff @@
## main #2860 +/- ##
==========================================
- Coverage 56.66% 56.58% -0.08%
==========================================
Files 322 322
Lines 31279 31449 +170
==========================================
+ Hits 17723 17796 +73
- Misses 12038 12117 +79
- Partials 1518 1536 +18
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review.