Skip to content

feat(site/src): add restart action to workspace overflow menu - #29309

Merged
jeremyruppel merged 2 commits into
mainfrom
jeremy/devex-977-add-restart-action-to-workspace-overflow-menu
Sep 16, 2026
Merged

jeremyruppel merged 2 commits into
mainfrom
jeremy/devex-977-add-restart-action-to-workspace-overflow-menu

Conversation

@jeremyruppel

@jeremyruppel jeremyruppel commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Restart… action to the three-dot overflow menu for each workspace on the /workspaces page (DEVEX-977). Previously users had to open a workspace to restart it.

  • New Restart… item in WorkspaceMoreActions, shown only for running workspaces (abilities.actions.includes("restart")), with a confirmation dialog consistent with the existing Stop flow.
  • Because API.restartWorkspace resolves only after the full stop→start sequence and the workspaces list has no live (websocket) updates, the row is optimistically set to stopping when the restart begins. This shows progress immediately and flips the list to its fast poll interval, which then tracks the real stopping → starting → running transitions. The optimistic change is rolled back if the request fails.
Screen.Recording.2026-09-14.at.5.02.36.PM.mov

Changes

  • WorkspaceMoreActions.tsx: new onRestart/isRestarting props and Restart… menu item.
  • WorkspacesTable.tsx: restart mutation wired to a ConfirmDialog, gated on the running-state ability, with optimistic status update + rollback.
  • api/queries/workspaces.ts: setOptimisticWorkspaceListBuildStatus helper that patches the row's build status across cached list queries and returns a rollback closure.
  • Tests: unit test for the optimistic helper (patch + rollback) and interaction tests for the menu (restart runs; absent for stopped workspaces).

Testing

  • pnpm --dir site exec vitest run (new/updated tests pass)
  • pnpm --dir site exec tsc --noEmit
  • make fmt / make lint
Implementation plan

DEVEX-977: Add Restart action to the workspace overflow menu

Goal

Add a Restart… action to the three-dot overflow menu for each workspace row on
the /workspaces page, so users can restart a running workspace directly from the
list without opening the workspace.

Context / findings

  • The overflow menu is WorkspaceMoreActions
    (site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx).
    It currently renders: Stop, Settings, Change version, Duplicate, Download logs,
    and Delete. Stop is passed in from the parent via an onStop callback +
    isStopping flag, with the confirmation dialog owned by the parent.
  • The parent is WorkspaceActionsCell inside
    site/src/pages/WorkspacesPage/WorkspacesTable.tsx. It computes abilities
    via abilitiesByWorkspaceStatus and already wires up stopWorkspace mutation
    plus a ConfirmDialog for stop; onStop opens that dialog.
  • abilitiesByWorkspaceStatus (site/src/modules/workspaces/actions.ts) already
    includes "restart" in the actions list for running workspaces (when not
    gated behind update-required flows). So the eligibility signal already exists:
    abilities.actions.includes("restart").
  • Restart API: API.restartWorkspace({ workspace, buildParameters }). It performs
    stop → waitForBuild → start → waitForBuild, returns void, and bails if the
    stop is canceled.

Approach

Mirror the existing onStop pattern so the menu stays a presentational component
and the parent owns the mutation + confirmation dialog.

1. WorkspacesTable.tsxWorkspaceActionsCell

  • Add a restart mutation using API.restartWorkspace directly.
  • Pass onRestart (gated on abilities.actions.includes("restart")) and
    isRestarting to WorkspaceMoreActions.
  • Add a ConfirmDialog (type="info") for restart confirmation.
  • Keep restart parameter-less (no ephemeral parameter prompting) to match the
    table's existing simple start/stop behavior.

2. WorkspaceMoreActions.tsx

  • Extend props with onRestart?/isRestarting? and render a Restart…
    DropdownMenuItem next to Stop.

3. Row status feedback

  • The list has no websocket; it only polls, fast (5s) only when a row is in an
    active build status. API.restartWorkspace resolves only at the very end, so
    the row would otherwise stay running. Optimistically set the row to
    stopping on mutate (with rollback on error) so the row updates immediately
    and the fast poll tracks the real transitions.

4. Tests

  • Unit test the optimistic cache helper (patch + rollback).
  • Interaction test: open the menu on a running workspace, confirm restart,
    assert API.restartWorkspace is called; assert the item is absent for stopped
    workspaces.

Decisions

  • Reuse the table's ConfirmDialog (consistent with Stop) rather than the
    single-page WarningDialog.
  • Ephemeral build parameters are intentionally not handled from the list view,
    consistent with the existing list-view start/stop actions.

🤖 Generated by Coder Agents.

Add a Restart action to the three-dot overflow menu for running workspaces on the /workspaces page. Optimistically reflects the restart in the row so the list tracks the stopping/starting transitions.

Generated by Coder Agents.
@linear-code

linear-code Bot commented Sep 14, 2026

Copy link
Copy Markdown

DEVEX-977

@jeremyruppel
jeremyruppel marked this pull request as ready for review September 14, 2026 21:06
nickvigilante added a commit that referenced this pull request Sep 15, 2026
…29364)

doc-check started a review chat on every non-draft pull request. A
review loads the full skill context, the content guidelines, and the
cumulative diff before it can conclude anything, so a dependency bump or
a test-only change paid that cost only for the skill's own "what not to
comment on" list to produce silence. With the wait raised to 40 minutes
in #29363, such a run can also hold a runner idle for most of that.

This classifies the changed paths first and skips the review when every
changed file is in a class with no user-facing documentation surface.
Comparing the match count against the total is what makes it "every
file", so a diff that mixes a test file with a CLI flag still gets a
full review.

CI that builds, deploys, previews, or reviews the docs is carved back
out of the `.github` skip, because a change there can change the docs
themselves. The `doc-check` label and a manual dispatch bypass the skip
entirely, so a review stays forceable from the pull request.

Tier-2 and tier-3 priors move into `path-priors.md`, loaded only when
the pre-filter is inconclusive, so they cost nothing on a skipped run.

## Verification

Dry-ran the filter list against real and synthetic file lists with the
same globber the action uses.

| Pull request | Files | Outcome |
|---|---|---|
| #29309 restart action | 5 | REVIEW, 3 files outside the skip classes |
| #29363 doc-check timeout | 1 | REVIEW, `ci_docs` carve-out fires |
| #29306 Mermaid diagrams | 5 | REVIEW, 2 files outside the skip classes
|
| `go.mod` + `go.sum` | 2 | SKIP |
| Go test + React test | 2 | SKIP |
| `site/src/index.css` | 1 | SKIP |
| `cli/server.go` + its test | 2 | REVIEW |
| Regenerated CLI docs + `cli/list.go` | 2 | REVIEW |
| `.github/workflows/release.yaml` | 1 | SKIP |

`make pre-commit` passes, including `lint/actions/actionlint`.

<details>
<summary>Why the patterns use the <code>**/*</code> form</summary>

The globber treats a `**` glued to a suffix inconsistently. Verified
against picomatch with `dot: true`:

| Pattern | `coderd/database/db_test.go` | `foo_test.go` |
|---|---|---|
| `**_test.go` | no match | match |
| `**/*_test.go` | match | match |

`**.test.ts` happens to match at any depth, but `**_test.go` only
matches the repo root, so a nested Go test would have leaked through and
started a review. Every pattern in the filter uses `**/*` instead, which
behaves the same at every depth including the root.
`.github/workflows/ci.yaml` carries a related note about the same class
of bug in a different action's globber.

</details>

<details>
<summary>Implementation plan and decision log</summary>

Part of a broader restructure of the doc-check skill. The audit found
five defects: no path pre-filter, no commit scoping, duplicated rules,
no likelihood model, and no destination for adjacent docs-gap ideas.
This PR addresses the first, which is the largest token win and the
lowest risk. The remainder is tracked separately.

**Rejected: `paths-ignore` on the `pull_request` trigger.** It does
express "all changed files match" for free, which was the initial plan.
But it applies to the trigger as a whole, including `labeled` and
`ready_for_review`, so a `doc-check` label on a CSS-only pull request
would have been filtered out too and the manual override would have
silently died. A job-level filter step costs about 20 seconds of runner
time and keeps the override working, so the filter lives in the job and
the trigger is untouched.

**Rejected: negation patterns for the docs-affecting CI carve-out.**
`!`-prefixed patterns inside the `nodocs` filter would have made the
result depend on pattern order. A separate `ci_docs` filter that must be
empty is explicit and reads as what it means.

**Deliberately not skipped: `coderd/database/migrations/`.** A migration
alone has no user surface, but migrations usually ship next to an API
change, and the all-files-must-match rule already handles that case.
Left to the agent rather than hardcoded either way.

**Known limitation.** A user-facing default change can hide inside an
otherwise-skippable path. The all-files-must-match rule plus the label
override is the mitigation; a path-only gate cannot close this
completely.

**Follow-ups this does not do.** Commit-scoped incremental reviews, a
`concurrency` block, splitting `SKILL.md` and deleting the rules it
restates from the content guidelines, run-outcome reporting so silence
and failure are distinguishable, and routing adjacent docs-gap ideas
into Linear.

</details>

DOCS-920

> Generated by Coder Agents on behalf of @nickvigilante.

@aqandrew aqandrew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this, thanks! I was just searching for a button that restarts workspaces the other day

Comment thread site/src/api/queries/workspaces.test.ts Outdated
@jeremyruppel
jeremyruppel merged commit b2aea05 into main Sep 16, 2026
26 checks passed
@jeremyruppel
jeremyruppel deleted the jeremy/devex-977-add-restart-action-to-workspace-overflow-menu branch September 16, 2026 14:19
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 16, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants