Skip to content

Commit 570e5f0

Browse files
committed
fix(helm): drop empty-string shadowing in app/realtime env merge
Sprig 'merge' treats "" as a real value, so a default-empty app.env.BETTER_AUTH_URL would shadow a non-empty realtime.env override and the URL would never reach the rendered Secret. Replace 'merge' with an explicit two-pass overlay that filters empties before writing, mirroring the same pattern already used in deployment-realtime.yaml's existingSecret block. Adds two regression tests: realtime.env-only value reaches the Secret when app.env is empty, and app.env still wins on collision when both are non-empty (48 tests total).
1 parent 51cbb9e commit 570e5f0

2 files changed

Lines changed: 53 additions & 9 deletions

File tree

helm/sim/templates/secrets-app.yaml

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,32 @@ type: Opaque
2020
stringData:
2121
{{- $chartComputed := list "DATABASE_URL" "SOCKET_SERVER_URL" "OLLAMA_URL" }}
2222
{{- /*
23-
Sprig `merge` keeps the FIRST source's value on key collision. Listing
24-
app.env first makes app.env authoritative for shared keys (e.g.
25-
BETTER_AUTH_SECRET, BETTER_AUTH_URL) — both pods mount this Secret via
26-
envFrom, so the app container must not be silently overwritten by a
27-
realtime-side value.
23+
Intent: app.env is authoritative for shared keys (both pods envFrom this
24+
Secret, so the app container must not be silently overwritten by a
25+
realtime-side value), BUT empty strings must never win.
26+
27+
Sprig `merge` treats "" as a real value, so a default-empty app.env entry
28+
would shadow a non-empty realtime.env entry. Build the effective dict
29+
manually: start from realtime.env, then overlay non-empty app.env values
30+
on top — this gives app.env-wins-on-collision without empty-string
31+
shadowing. Mirrors the pattern used in deployment-realtime.yaml.
2832
*/}}
29-
{{- $merged := merge (dict) (.Values.app.env | default dict) (.Values.realtime.env | default dict) }}
30-
{{- range $key, $value := $merged }}
31-
{{- if not (has $key $chartComputed) }}
33+
{{- $appEnv := .Values.app.env | default dict }}
34+
{{- $rtEnv := .Values.realtime.env | default dict }}
35+
{{- $effective := dict }}
36+
{{- range $key, $value := $rtEnv }}
3237
{{- if and (ne (toString $value) "") (ne (toString $value) "<nil>") }}
33-
{{ $key }}: {{ $value | quote }}
38+
{{- $_ := set $effective $key $value }}
3439
{{- end }}
3540
{{- end }}
41+
{{- range $key, $value := $appEnv }}
42+
{{- if and (ne (toString $value) "") (ne (toString $value) "<nil>") }}
43+
{{- $_ := set $effective $key $value }}
44+
{{- end }}
45+
{{- end }}
46+
{{- range $key, $value := $effective }}
47+
{{- if not (has $key $chartComputed) }}
48+
{{ $key }}: {{ $value | quote }}
49+
{{- end }}
3650
{{- end }}
3751
{{- end }}

helm/sim/tests/secret-modes_test.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,33 @@ tests:
8686
content:
8787
secretRef:
8888
name: my-existing-secret
89+
90+
- it: realtime.env-only value reaches the Secret when app.env entry is empty (cursor bugbot fix)
91+
template: secrets-app.yaml
92+
set:
93+
app.env.BETTER_AUTH_SECRET: x
94+
app.env.ENCRYPTION_KEY: x
95+
app.env.INTERNAL_API_SECRET: x
96+
app.env.CRON_SECRET: x
97+
app.env.BETTER_AUTH_URL: ""
98+
realtime.env.BETTER_AUTH_URL: "https://realtime.example.com"
99+
postgresql.auth.password: x
100+
asserts:
101+
- equal:
102+
path: stringData.BETTER_AUTH_URL
103+
value: "https://realtime.example.com"
104+
105+
- it: app.env wins over realtime.env on collision when both are non-empty
106+
template: secrets-app.yaml
107+
set:
108+
app.env.BETTER_AUTH_SECRET: x
109+
app.env.ENCRYPTION_KEY: x
110+
app.env.INTERNAL_API_SECRET: x
111+
app.env.CRON_SECRET: x
112+
app.env.NEXT_PUBLIC_APP_URL: "https://app.example.com"
113+
realtime.env.NEXT_PUBLIC_APP_URL: "https://realtime.example.com"
114+
postgresql.auth.password: x
115+
asserts:
116+
- equal:
117+
path: stringData.NEXT_PUBLIC_APP_URL
118+
value: "https://app.example.com"

0 commit comments

Comments
 (0)