Skip to content

fix(workspace-server): skip provision pipeline on Restart for runtime=external - #2412

Merged
HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/restart-external-no-revoke
Apr 30, 2026
Merged

HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/restart-external-no-revoke

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

  • Manual `POST /workspaces/:id/restart` on a `runtime=external` workspace ran the full re-provision pipeline → `issueAndInjectToken` → `RevokeAllForWorkspace`, silently destroying the operator's local bearer token on every Restart click.
  • Auto-restart (`runRestartCycle`, line 436) already short-circuits external — this patch mirrors that for the manual handler so the two paths agree.
  • Returns `200 OK` with `{status: noop, runtime: external, message: ...}` so the canvas can show the operator that the fix is on their side rather than silently no-op'ing.

Why this matters

Reported during this session: I was running the molecule MCP channel plugin against a long-lived external workspace, the canvas surfaced "workspace dead — restart?", clicking Restart silently revoked my token, and my poller 401-spammed until I manually regenerated from the Tokens tab. Every external workspace operator hits this the first time their canvas suggests a restart.

Test plan

  • `go test ./internal/handlers/ -run TestRestartHandler -count=1` — 5/5 pass including the new `TestRestartHandler_ExternalRuntimeNoOps`
  • `go test ./internal/handlers/ -count=1` — full handlers suite green
  • sqlmock asserts no DB writes occur after the short-circuit (token revoke / status update would trigger an "unexpected query" failure)
  • Verify on staging once merged: hit `/workspaces/:external-id/restart` on a tenant with a live external workspace, confirm `status=noop` response and the local poller's token still works

🤖 Generated with Claude Code

…=external

POST /workspaces/:id/restart on a runtime=external workspace ran the full
re-provision pipeline (Stop → provisionWorkspace*), which calls
issueAndInjectToken → RevokeAllForWorkspace. For external workspaces
(operator-driven, no container/EC2) that silently destroyed the operator's
local bearer token on every "Restart" click in the canvas — the local
poller would then 401-spam against /activity until the operator manually
regenerated from the Tokens tab.

The auto-restart path (runRestartCycle, line 436) already short-circuits
runtime=external. This patch mirrors that for the manual handler so the
two paths agree, and surfaces a 200 OK with a clear message so the
canvas can tell the operator the fix is on their side rather than
silently no-op'ing.

Test coverage: TestRestartHandler_ExternalRuntimeNoOps asserts the
short-circuit fires *before* any DB write or provision call. sqlmock's
"unexpected query" failure mode would catch a regression that
re-introduced the token revoke or the status=provisioning UPDATE.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HongmingWang-Rabbit
HongmingWang-Rabbit added this pull request to the merge queue Apr 30, 2026
Merged via the queue into staging with commit d2046c3 Apr 30, 2026
20 of 21 checks passed
@HongmingWang-Rabbit
HongmingWang-Rabbit deleted the fix/restart-external-no-revoke branch April 30, 2026 22:15
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
…ural) for Gitea 1.22.6 API (#1306)' (#2412) from fix/1306-gitea-label-singular into main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant