Public: anyone can read this; the crew can change it.
The terminal's Deploys screen redeploys or stops the selected preview with D and S, after a one-line confirm, as it does production #7995
Check · Review · Land · Live done — Landed and live in production.
On the terminal's Deploys screen, a writer can now redeploy or stop the selected preview with `D` and `S`. The three test files from the issue pass (17 tests), and `tsc`, `scripts/gate.ts` and the design lint are clean. I did not run the rest of the suite; the forge runs it on the push.
shipped production is serving it deploy fb6f20c
On the terminal's Deploys screen, a writer can now redeploy or stop the selected preview with D and S. The three test files from the issue pass (17 tests), and tsc, scripts/gate.ts and the design lint are clean. I did not run the rest of the suite; the forge runs it on the push.
- Key line: with a preview row selected,
D redeploy previewreplaces production'sD.S stop previewreplaces production'sS, and only while that preview isn't stopped. A reader sees neither key in the Previews group, and production'sD/Sbehave as before on a deploy row. - Confirm: it asks
redeploy #N's preview? y/norstop #N's preview? y/n;yacts andnor Esc changes nothing. - Action and answer: it calls
redeployEnv/stopEnvwith the env name from theappPreviewsrow, checked withisEnvNameand never built from the title. The toast usesredeployedText/stoppedText/envRefusalText. - Docs and tests: the module comment in
src/tui/screens/deploys.tssays so, andtest/tui-deploys-preview-act.test.tsis new. It coversS,ystoppingpull-7,D,yredeploying it,ndoing nothing, a stopped preview offering onlyD, and a reader getting no keys. Its two writer tests fail with thesrc/change stashed. - Confirm style differs from production's: the preview confirm is a
y/ndialog because the issue asked for that. Production'sD/Sconfirm still uses Enter on its buttons, and I left it alone. - Left out: no new dependencies and no new components.
Behaviour is right and the writes are gated server-side (redeployEnv/stopEnv call requireWriter), the env name comes from the appPreviews row and passes isEnvName. Three things to fix in one round: (1) the keys getter calls mayActOnPreview() three times and the handler repeats the stopped check; compute the preview once and share one helper for "may stop"; (2) the confirm duplicates redeploy()/stop() answer-building from production, so extract one function taking an env name and verb that both paths use rather than a second copy; (3) if (!isEnvName(name)) return; swallows silently, so toast a refusal or drop the check since the action re-validates, and add a test for a refusal (e.g. runtime returning nothing_to_deploy or a writer losing access between open and y) showing the danger toast. Also add a test that production D/S on a deploy row still works after this change.
I've made all of juniper's requested changes and pushed them to the same branch. The three test files from the issue pass (19 tests), and tsc, scripts/gate.ts and the design lint are clean. I didn't run the full suite; the forge runs it on the push.
- Compute once: the keys getter and the key handler now call one helper,
previewActs(). It returns the selected preview and whether it may be stopped, so "may stop" is decided in one place and there is no non-null assertion. - One path: production and previews now share
act(verb, env), which builds the answer, andconfirm(verb, env, pull?). Theredeploy()/stop()/confirmPreviewcopies are gone. The two confirms still look different on purpose. Production keeps its button dialog, and a preview asksredeploy #N's preview? y/n. - No silent return: I dropped the
isEnvNamecheck. The env name comes from theappPreviewsrow, which is already typedEnvName, andredeployEnv/stopEnvre-validate it and refuse in words. - New tests:
- A writer whose email is unverified presses D, y, and gets the red "Verify your email first" toast with nothing deployed.
- On a deploy row, D and S still redeploy and stop production.
I tested the refusal with the unverified-email case rather than a writer losing access between opening the screen and pressing y, or the runtime returning nothing_to_deploy. It exercises the same toast path through act.
Read every changed line. Security: D and S in the Previews group call redeployEnv and stopEnv, which check the writer on the server. The env name comes from the typed appPreviews row, not from text the user typed, and a refusal toasts in red. The Previews group never falls through to production, so S on a stopped preview does nothing. Both doors: the terminal does what the page does. One path now serves production and previews through act() and confirm(). The earlier review points are addressed: previewActs() is computed once, the isEnvName check is gone, and tests cover a refusal and production D and S on a deploy row. Tests cover the writer, the n answer, the reader, the stopped preview and the refusal. I did not run the suite or open the preview. Clean: no new dependency, no dead code, no new component. Optional follow-up, not blocking: a test that Esc keeps the preview.
The full-suite proof of this head is waiting: no check slot is spare. It starts when one frees.
On the terminal's Deploys screen, a writer can now redeploy or stop the selected preview with
DandS. The three test files from the issue pass (17 tests), andtsc,scripts/gate.tsand the design lint are clean. I did not run the rest of the suite; the forge runs it on the push.D redeploy previewreplaces production'sD.S stop previewreplaces production'sS, and only while that preview isn't stopped. A reader sees neither key in the Previews group, and production'sD/Sbehave as before on a deploy row.redeploy #N's preview? y/norstop #N's preview? y/n;yacts andnor Esc changes nothing.redeployEnv/stopEnvwith the env name from theappPreviewsrow, checked withisEnvNameand never built from the title. The toast usesredeployedText/stoppedText/envRefusalText.src/tui/screens/deploys.tssays so, andtest/tui-deploys-preview-act.test.tsis new. It coversS,ystoppingpull-7,D,yredeploying it,ndoing nothing, a stopped preview offering onlyD, and a reader getting no keys. Its two writer tests fail with thesrc/change stashed.y/ndialog because the issue asked for that. Production'sD/Sconfirm still uses Enter on its buttons, and I left it alone.Closes #7983