-
Notifications
You must be signed in to change notification settings - Fork 2
feat(config): parse and resolve devcontainer secrets property #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,10 +41,19 @@ func resolveLifecycleEnv( | |
| ) | ||
| } | ||
|
|
||
| env := mergeRemoteEnv(mergedConfig.RemoteEnv, probedEnv, remoteUser) | ||
|
|
||
| // Resolve declared secrets from the host environment. | ||
| for name := range mergedConfig.Secrets { | ||
| if val := os.Getenv(name); val != "" { | ||
| env[name] = val | ||
| } | ||
| } | ||
|
Comment on lines
+46
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Empty-string host values silently skip declared secrets; also consider logging unresolved secrets. Two concerns on this block:
Suggested adjustment- // Resolve declared secrets from the host environment.
- for name := range mergedConfig.Secrets {
- if val := os.Getenv(name); val != "" {
- env[name] = val
- }
- }
+ // Resolve declared secrets from the host environment.
+ for name := range mergedConfig.Secrets {
+ if val, ok := os.LookupEnv(name); ok {
+ env[name] = val
+ } else {
+ log.Debugf("declared secret %q is not set in host environment; skipping", name)
+ }
+ }Note: the existing test asserts that an absent secret is not present in 🤖 Prompt for AI Agents |
||
|
|
||
| return lifecycleEnv{ | ||
| remoteUser: remoteUser, | ||
| workspaceFolder: setupInfo.SubstitutionContext.ContainerWorkspaceFolder, | ||
| remoteEnv: mergeRemoteEnv(mergedConfig.RemoteEnv, probedEnv, remoteUser), | ||
| remoteEnv: env, | ||
|
Comment on lines
+44
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In devcontainer.json, there is a "secrets" property for declaring recommended secrets, primarily used in GitHub Codespaces to prompt users to set user-specific secrets. These are not stored in the file but reference secrets provided by the implementing tool/service (e.g., Codespaces secrets). Secrets are handled similarly to "remoteEnv": implementing tools inject them as environment variables for the runtime environment (VS Code server, terminals, tasks, etc.) after the container's ENTRYPOINT. The devcontainers CLI supports passing secrets via --secrets-file for commands like "up", applying them like remoteEnv. Precedence: devcontainer.json takes precedence over image/feature metadata for properties like remoteEnv and containerEnv (per-variable last value wins, devcontainer.json last when order matters). Secrets follow similar logic if contributed by features/images. No native Docker buildkit --secret support in devcontainer.json; use workarounds like docker-compose build.secrets or build.options. Example declaration: { "secrets": { "MY_SECRET": { "description": "Personal API key" } }, "remoteEnv": { "MY_SECRET": "${secret:MY_SECRET}" } } Citations:
🏁 Script executed: # First, let's look at the full function and surrounding context
cat -n pkg/devcontainer/setup/lifecyclehooks.go | head -80Repository: devsy-org/devsy Length of output: 2961 🏁 Script executed: # Look for test cases related to secret handling
fd -t f lifecyclehooks_test.goRepository: devsy-org/devsy Length of output: 104 🏁 Script executed: # Search for how secrets are used elsewhere in the codebase
rg -i "secrets" pkg/devcontainer/setup/ -A 3 -B 3 --max-count=50Repository: devsy-org/devsy Length of output: 1754 🏁 Script executed: # Check for documentation or spec about secret precedence
fd -t f -i "spec\|readme\|doc" pkg/devcontainer/Repository: devsy-org/devsy Length of output: 41 🏁 Script executed: # View the full test case for secret handling
cat -n pkg/devcontainer/setup/lifecyclehooks_test.go | grep -A 40 "TestResolveLifecycleEnvIncludesSecrets"Repository: devsy-org/devsy Length of output: 1350 🏁 Script executed: # Find the mergeRemoteEnv function definition
rg "func mergeRemoteEnv" pkg/devcontainer/setup/ -A 20Repository: devsy-org/devsy Length of output: 1673 🏁 Script executed: # Check the Secrets configuration in the config package
rg "Secrets\s*map\[string\]" pkg/devcontainer/config/ -B 2 -A 2Repository: devsy-org/devsy Length of output: 494 🏁 Script executed: # Search for any comments or TODOs about secret precedence
rg -i "secret.*precedence\|precedence.*secret\|secret.*override\|override.*secret" pkg/devcontainer/Repository: devsy-org/devsy Length of output: 41 🏁 Script executed: # Check if there are any related GitHub issues or discussions referenced
rg -i "secret.*remoteenv\|remoteenv.*secret" pkg/devcontainer/ -B 3 -A 3Repository: devsy-org/devsy Length of output: 41 🏁 Script executed: # Look at git history or comments around the secret handling code
rg "Resolve declared secrets" pkg/devcontainer/ -B 5 -A 10Repository: devsy-org/devsy Length of output: 1111 Secrets applied after Secrets from the host environment (lines 47–50) are injected after 🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 12220
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 8867
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 1896
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 41
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 41
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 460
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 41
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 263
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 119
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 490
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 41
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 41
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 96
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 511
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 5049
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 3279
🏁 Script executed:
Repository: devsy-org/devsy
Length of output: 2881
Secrets from feature/image metadata are dropped during merge.
Per
MergeConfigurationinpkg/devcontainer/config/merge.go, theDevContainerConfigBase(which includesSecrets) is copied from the user config once at initialization (line 31) and never re-merged from theimageMetadataEntries. SinceImageMetadataembedsDevContainerConfigBase, any secrets declared in feature metadata are silently ignored.The codebase already uses
mergeMaps()for other maps likeRemoteEnvandContainerEnv. Apply the same pattern toSecretsto ensure feature-contributed secrets are properly merged (e.g., using a last-wins or first-wins policy with clear documentation).🤖 Prompt for AI Agents