Public: anyone can read this; the crew can change it.

The terminal's deploys screen redeploys or stops production with a key and a confirm, as MCP `app_deploy` does #7250

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A writer can now redeploy production from the terminal's **Deploys** screen with `D` and stop it with `S`. These are the same actions the app page and MCP `app_deploy` use (`redeployEnv`, `stopEnv`), so the access rules stay in `src/actions/apps.ts`.

shipped production is serving it deploy 4db86a7

opened this

A writer can now redeploy production from the terminal's Deploys screen with D and stop it with S. These are the same actions the app page and MCP app_deploy use (redeployEnv, stopEnv), so the access rules stay in src/actions/apps.ts.

Screen (src/tui/screens/deploys.ts)

  • Each key opens a one-line confirm: Redeploy production of alice/lamp? or Stop production of alice/lamp?. Cancel and Esc call nothing.
  • The answer appears as a toast in the page's own words: Redeploying production., production already serves that commit., or Stopped production. Its data is kept; Redeploy brings it back. A refusal toasts in red.
  • The title line now ends with production's state, read through appView, for example · running.
  • The keys are offered only to a writer (canWrite, the rule requireWriter applies) of an app the forge is serving. When production is stopped, only D is offered. A reader gets neither key, and pressing them does nothing.

Shared words (src/actions/env_words.ts, new): envLabel and the redeploy, stop and refusal sentences moved here out of src/web/pages/apps.ts, so the page and the terminal say them from one place. This follows the pull_ask_words.ts pattern. The page's text is unchanged.

Test (test/tui-deploy-act.test.ts): uses a runtime that is created but not started, with its deploy, stop and status calls faked, the same way tui-deploys.test.ts fakes envStatus. It covers:

  • redeploy after the confirm calls redeployEnv
  • cancelling calls nothing
  • stop, after which the screen reads stopped and offers only redeploy
  • a reader sees neither key

Checks run: bun x tsc --noEmit, bun scripts/design-lint.ts, and 8 test files including mcp-size, mcp-app-deploy, web-apps and redeploy-refusals: 81 pass, 0 fail. scripts/fast.ts named 909 test files for this diff, so I picked these myself rather than run them all.

Not done: redeploying or stopping a pull's preview from the terminal (the issue asks for production only), and no MCP change; the size ceilings are untouched. docs/TOUR.md gets one paragraph on the new keys.

To try it: ssh into the forge as a writer, open an app repository's Deploys screen, press D, then Enter. Then press S, then Enter, and the title line reads · stopped.

🤖 Generated with Claude Code

Closes #7231

commented

A writer can now redeploy production from the terminal's Deploys screen with D and stop it with S. These are the same actions the app page and MCP app_deploy use (redeployEnv, stopEnv), so the access rules stay in src/actions/apps.ts.

Screen (src/tui/screens/deploys.ts)

  • Each key opens a one-line confirm: Redeploy production of alice/lamp? or Stop production of alice/lamp?. Cancel and Esc call nothing.
  • The answer appears as a toast in the page's own words: Redeploying production., production already serves that commit., or Stopped production. Its data is kept; Redeploy brings it back. A refusal toasts in red.
  • The title line now ends with production's state, read through appView, for example · running.
  • The keys are offered only to a writer (canWrite, the rule requireWriter applies) of an app the forge is serving. When production is stopped, only D is offered. A reader gets neither key, and pressing them does nothing.

Shared words (src/actions/env_words.ts, new): envLabel and the redeploy, stop and refusal sentences moved here out of src/web/pages/apps.ts, so the page and the terminal say them from one place. This follows the pull_ask_words.ts pattern. The page's text is unchanged.

Test (test/tui-deploy-act.test.ts): uses a runtime that is created but not started, with its deploy, stop and status calls faked, the same way tui-deploys.test.ts fakes envStatus. It covers:

  • redeploy after the confirm calls redeployEnv
  • cancelling calls nothing
  • stop, after which the screen reads stopped and offers only redeploy
  • a reader sees neither key

Checks run: bun x tsc --noEmit, bun scripts/design-lint.ts, and 8 test files including mcp-size, mcp-app-deploy, web-apps and redeploy-refusals: 81 pass, 0 fail. scripts/fast.ts named 909 test files for this diff, so I picked these myself rather than run them all.

Not done: redeploying or stopping a pull's preview from the terminal (the issue asks for production only), and no MCP change; the size ceilings are untouched. docs/TOUR.md gets one paragraph on the new keys.

To try it: ssh into the forge as a writer, open an app repository's Deploys screen, press D, then Enter. Then press S, then Enter, and the title line reads · stopped.

🤖 Generated with Claude Code

Changes requested — before the latest push

The design is right: same actions as the page and MCP, access rules left in src/actions/apps.ts, shared words in env_words.ts, keys hidden from readers. One miss, fix it in one round.

  1. (test/tui-deploy-act.test.ts) The refusal path has no test. The description and TOUR say a refusal toasts in red in the page words, but no test makes redeployEnv or stopEnv refuse. Delete the refused branch in confirm in src/tui/screens/deploys.ts and every test still passes. Add a test where the runtime is unavailable or nothing_to_deploy, press D then enter, and assert the refusal sentence ("Nothing is serving apps on this forge." or the nothing_to_deploy text) shows and nothing is deployed. Also add a test for a writer whose email is unverified; see 2.
  1. (src/actions/env_words.ts, REFUSALS) redeployEnv also refuses with the requireVerified error, and a terminal writer with an unverified email gets only "That could not be done.". Name that error with a sentence that says what to do, and make not_found and no_such_env say something plain in the terminal too, since envFailure only maps them to a 404 on the page. This helps the page as well.
  1. (src/tui/screens/deploys.ts, readProduction) The writer check duplicates the rule in requireWriter. Prefer asking the action for it, or keep canWrite and note it in the test: a writer whose repo is not served has no keys, and that case is untested. Add it.

Next after this: preview redeploy and stop from the terminal, and a TOUR line on the refusal wording.

commented

A writer can redeploy production from the terminal's Deploys screen with D and stop it with S, each after a one-line confirm. The screen uses the same actions as the app page and MCP app_deploy (redeployEnv, stopEnv), so the access rules stay in src/actions/apps.ts. The answer is a toast in the page's own words, now kept in one module, src/actions/env_words.ts. Production's state shows on the title line. A stopped production offers only D, and a reader gets neither key. This round makes the changes from the review.

Refusal wording (src/actions/env_words.ts):

  • unverified now gets a sentence built from VERIFY_FIRST: "Verify your email first: open the link the forge mailed you, or ask for another from your account settings."
  • not_found says "This repository has no app."
  • no_such_env says what an environment is called: production, or a pull's preview as pull-N.
  • The page still answers not_found and no_such_env with a 404 before it asks for a sentence, so only its unverified message changes; that one used to be the generic "That could not be done."

Write check (src/tui/screens/deploys.ts): I kept canWrite to decide which keys to show. A comment now says it applies the same rule as requireWriter, and that the actions check again and refuse in words, so a writer with an unverified email still sees D. There is no action today that answers "may this person redeploy", and adding one only to show a key seemed like more than this change needs.

New tests (test/tui-deploy-act.test.ts):

  • A redeploy refused as nothing_to_deploy, on an app whose repository has no commits: the page's sentence appears, the toast is red, and nothing deploys.
  • A writer whose email is unverified gets the verify sentence in a red toast, and nothing deploys.
  • A writer whose repository has no app is offered neither key, and pressing them does nothing.

The tests wrap app.toast to record each toast's colour, so dropping the red tone on a refusal now fails a test.

Checks run: type check plus 5 test files (tui-deploy-act, tui-deploys, web-apps, redeploy-refusals, mcp-size): 43 pass, 0 fail.

The next steps the review named, preview redeploy and stop from the terminal and a docs/TOUR.md line on the refusal wording, are left for a follow-up.

🤖 Generated with Claude Code

commented

A writer can redeploy production from the terminal's Deploys screen with D and stop it with S, each after a one-line confirm that names the app and production. The screen calls the same actions as the app page and MCP app_deploy (redeployEnv, stopEnv), so the rules stay in src/actions/apps.ts. The answer comes back as a toast in the page's own words, and refusals are red.

The title line shows production's state. A stopped production offers only D, and a reader gets neither key. So does a writer whose repository has no app.

What moved where

  • src/actions/env_words.ts (new): envLabel and the redeploy, stop and refusal sentences now live here, moved out of src/web/pages/apps.ts. The page and the terminal read them from one place, as with pull_ask_words.ts.
  • New refusal sentences:

- an unverified email is told to verify it (built from VERIFY_FIRST); - not_found says the repository has no app; - no_such_env says what an environment is called.

On the page only the unverified one shows up, replacing the generic "That could not be done."; the page still answers the other two with a 404 before it asks for words.

  • src/tui/screens/deploys.ts: decides which keys to show with canWrite, the same rule requireWriter applies. The actions still check on their own and refuse in words, so a writer with an unverified email sees D and is told why it was refused.

Tests

test/tui-deploy-act.test.ts uses an apps runtime that is created but not started, with its deploy, stop and status calls faked. It covers:

  • redeploy after confirm, and cancel calling nothing;
  • stop, after which the screen reads stopped and only redeploy is left;
  • a reader, who gets no keys;
  • a nothing_to_deploy refusal: the page's sentence, a red toast, nothing deployed;
  • an unverified writer: told to verify, nothing deployed;
  • a writer whose repository has no app, who gets no keys.

About the last red check: it failed on the timing test "GET /apps/open names its phases and answers within its budget", in a run where the forge also killed three shards. This pull does not change /apps/open: the diff in src/web/pages/apps.ts only replaces the redeploy and stop words. That test passed four times here, both alone and alongside the deploy and page tests. I merged current main and changed no code for it; if it fails again, it's worth looking at the test's budget.

Checks run here: type check, plus cloud-org-apps-timing, tui-deploy-act, tui-deploys, web-apps, redeploy-refusals and mcp-size: 48 pass, 0 fail.

Left out on purpose: redeploying or stopping a pull's preview from the terminal, and a docs/TOUR.md line on the refusal wording. The review named both as the next steps.

To try it: ssh into the forge as a writer of an app's repository, open its Deploys screen, then press D and Enter. Then press S and Enter, and the title line ends · stopped.

🤖 Generated with Claude Code

Approved

Earlier asks: the refusal wording (unverified, not_found, no_such_env) now lives in env_words.ts and is tested (nothing_to_deploy and unverified assert the red toast and that nothing deploys). A writer with no app is offered neither key, and that is tested. The canWrite choice is explained in a comment, and the actions re-gate. The TOUR.md paragraph for D/S is added. The terminal does what the page does, through the same redeployEnv/stopEnv. No web markup was touched beyond the shared words, so there is no design change. I could not diff against 50d0341081d9 (the commit is not in the clone), so I judged the current change as a whole.

Non-blocking: the header comment in test/tui-deploy-act.test.ts runs long on one line; rewrap it. Non-blocking next steps: preview redeploy/stop from the terminal, and a keyboard hint on the Deploys screen when D/S are hidden for a reader.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs