Skip to content

Commit 2ec4cbb

Browse files
feat(setup): prompt for the chat key in k8s mode
The dev and compose flows minted a chat key and wrote the Chat opt-out alongside it; k8s did neither, so a cluster install with no COPILOT_API_KEY in its Helm values rendered a Chat module that rejects every message. Prompt with the same flow and feed both values into `app.env`, which the chart already renders as arbitrary container env. Reading the previous release's key matters here in a way it does not for the file-based modes: `helm upgrade` without `--reuse-values` keeps only what this document carries, so a key the user elects to keep has to be re-supplied or it is silently dropped. Splits the release-values read from the secret-reuse check so both the key and the secrets come from one `helm get values` call, and carries the mothership override across for the same mint-here-validate-there reason the other modes document. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ErcRgvi7VQBeKDQ3MBMha
1 parent 9df71be commit 2ec4cbb

1 file changed

Lines changed: 38 additions & 7 deletions

File tree

scripts/setup/modes/k8s.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { generateSecret, ROOT } from '../env-files.ts'
66
import { SetupError } from '../errors.ts'
77
import { waitFor } from '../probes.ts'
88
import * as p from '../prompter.ts'
9+
import { chatFlagValues, mothershipOverride, promptCopilotKey } from '../steps.ts'
910
import { glyph, theme } from '../theme.ts'
1011

1112
const APP_URL = 'http://localhost:3000'
@@ -276,15 +277,29 @@ async function helmInstall(
276277
}
277278
}
278279

279-
function existingReleaseSecrets(context: string): Record<string, string> | null {
280+
interface ReleaseValues {
281+
app?: { env?: Record<string, string> }
282+
postgresql?: { auth?: { password?: string } }
283+
}
284+
285+
/** Values of the installed release, or `null` when there is no release yet. */
286+
function existingReleaseValues(context: string): ReleaseValues | null {
280287
const scope = ['--kube-context', context, '-n', NAMESPACE]
281288
const status = spawnSync('helm', ['status', RELEASE, ...scope], { stdio: 'ignore' })
282289
if (status.status !== 0) return null
283-
const values = JSON.parse(
290+
return JSON.parse(
284291
run('helm', ['get', 'values', RELEASE, ...scope, '-o', 'json'], 'helm get values failed')
285-
) as { app?: { env?: Record<string, string> }; postgresql?: { auth?: { password?: string } } }
286-
const env = values.app?.env ?? {}
287-
const password = values.postgresql?.auth?.password
292+
) as ReleaseValues
293+
}
294+
295+
/**
296+
* The previous release's secrets, or `null` when any are missing — a partial set
297+
* cannot be reused, since regenerating only some of them invalidates sessions
298+
* and stored credentials encrypted under the originals.
299+
*/
300+
function reusableSecrets(values: ReleaseValues | null): Record<string, string> | null {
301+
const env = values?.app?.env ?? {}
302+
const password = values?.postgresql?.auth?.password
288303
if (
289304
!env.BETTER_AUTH_SECRET ||
290305
!env.ENCRYPTION_KEY ||
@@ -323,7 +338,8 @@ export async function runK8sMode(detection: Detection): Promise<void> {
323338
// credentials to an unintended cluster.
324339
const context = await ensureLocalContext(detection)
325340

326-
const reused = existingReleaseSecrets(context)
341+
const releaseValues = existingReleaseValues(context)
342+
const reused = reusableSecrets(releaseValues)
327343
const secrets = reused ?? {
328344
BETTER_AUTH_SECRET: generateSecret(),
329345
ENCRYPTION_KEY: generateSecret(),
@@ -333,6 +349,21 @@ export async function runK8sMode(detection: Detection): Promise<void> {
333349
}
334350
if (reused) p.log.step('Reusing secrets from the existing release')
335351

352+
// Before the key is minted: a half-set override mints against one environment
353+
// and validates against the other, and warning afterwards is too late — the
354+
// bad key is already deployed.
355+
const overrides = mothershipOverride()
356+
const copilotKey = await promptCopilotKey(releaseValues?.app?.env?.COPILOT_API_KEY)
357+
358+
// `helm upgrade` without `--reuse-values` keeps only what this document
359+
// carries, so a key the user chose to keep has to be re-supplied here.
360+
const appEnv: Record<string, string> = {
361+
...secrets,
362+
...overrides,
363+
...(copilotKey ? { COPILOT_API_KEY: copilotKey } : {}),
364+
...chatFlagValues(copilotKey),
365+
}
366+
336367
const spin = p.spinner()
337368
spin.start('helm upgrade --install (first run pulls images — this can take several minutes)…')
338369
try {
@@ -355,7 +386,7 @@ export async function runK8sMode(detection: Detection): Promise<void> {
355386
'--timeout',
356387
'15m',
357388
],
358-
secretValues(secrets),
389+
secretValues(appEnv),
359390
context,
360391
spin
361392
)

0 commit comments

Comments
 (0)