feat: add workspace restart functionality to API (#25757)

This models restart as durable orchestration of existing stop and
start workspace builds instead of adding a new restart transition.
Keeping restart as two existing transitions preserves the current
build/provisioner model.

The child start build is created only after the parent stop build
succeeds, rather than being inserted immediately in a pending
state. That keeps `workspace_builds` aligned with actual
provisioner-ready work and avoids introducing a second
pending-build lifecycle that the provisioner and build acquisition
paths would need to understand.

Refs: https://linear.app/codercom/issue/PLAT-143
This commit is contained in:
George K
2026-07-07 09:18:30 -07:00
committed by GitHub
parent ba094c5706
commit 6af0f4d698
45 changed files with 4412 additions and 144 deletions
+5
View File
@@ -219,6 +219,11 @@ const (
APIKeyScopeWorkspaceAgentResourceMonitorCreate APIKeyScope = "workspace_agent_resource_monitor:create"
APIKeyScopeWorkspaceAgentResourceMonitorRead APIKeyScope = "workspace_agent_resource_monitor:read"
APIKeyScopeWorkspaceAgentResourceMonitorUpdate APIKeyScope = "workspace_agent_resource_monitor:update"
APIKeyScopeWorkspaceBuildOrchestrationAll APIKeyScope = "workspace_build_orchestration:*"
APIKeyScopeWorkspaceBuildOrchestrationCreate APIKeyScope = "workspace_build_orchestration:create"
APIKeyScopeWorkspaceBuildOrchestrationDelete APIKeyScope = "workspace_build_orchestration:delete"
APIKeyScopeWorkspaceBuildOrchestrationRead APIKeyScope = "workspace_build_orchestration:read"
APIKeyScopeWorkspaceBuildOrchestrationUpdate APIKeyScope = "workspace_build_orchestration:update"
APIKeyScopeWorkspaceDormantAll APIKeyScope = "workspace_dormant:*"
APIKeyScopeWorkspaceDormantApplicationConnect APIKeyScope = "workspace_dormant:application_connect"
APIKeyScopeWorkspaceDormantCreate APIKeyScope = "workspace_dormant:create"
+2
View File
@@ -52,6 +52,7 @@ const (
ResourceWorkspace RBACResource = "workspace"
ResourceWorkspaceAgentDevcontainers RBACResource = "workspace_agent_devcontainers"
ResourceWorkspaceAgentResourceMonitor RBACResource = "workspace_agent_resource_monitor"
ResourceWorkspaceBuildOrchestration RBACResource = "workspace_build_orchestration"
ResourceWorkspaceDormant RBACResource = "workspace_dormant"
ResourceWorkspaceProxy RBACResource = "workspace_proxy"
)
@@ -130,6 +131,7 @@ var RBACResourceActions = map[RBACResource][]RBACAction{
ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionCreateAgent, ActionDelete, ActionDeleteAgent, ActionRead, ActionShare, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate, ActionUpdateAgent},
ResourceWorkspaceAgentDevcontainers: {ActionCreate},
ResourceWorkspaceAgentResourceMonitor: {ActionCreate, ActionRead, ActionUpdate},
ResourceWorkspaceBuildOrchestration: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionCreateAgent, ActionDelete, ActionDeleteAgent, ActionRead, ActionShare, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate, ActionUpdateAgent},
ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
}
+28
View File
@@ -136,6 +136,34 @@ type CreateWorkspaceBuildRequest struct {
TemplateVersionPresetID uuid.UUID `json:"template_version_preset_id,omitempty" format:"uuid"`
// Reason sets the reason for the workspace build.
Reason CreateWorkspaceBuildReason `json:"reason,omitempty" validate:"omitempty,oneof=dashboard cli ssh_connection vscode_connection jetbrains_connection task_manual_pause"`
// OnSuccess queues a follow-up workspace build after this build succeeds.
// It currently supports restarting a workspace by starting it after a
// successful stop build.
OnSuccess *CreateWorkspaceBuildOnSuccessRequest `json:"on_success,omitempty"`
}
// CreateWorkspaceBuildOnSuccessRequest queues a follow-up build that
// runs after the parent build succeeds. It currently supports
// restarting a workspace: the parent build must be a "stop" and this
// child build a "start". The child build inherits LogLevel and Reason
// from the parent CreateWorkspaceBuildRequest.
type CreateWorkspaceBuildOnSuccessRequest struct {
// TemplateVersionID pins the child build to a specific template
// version. Pinning requires permission to update the template,
// since the active version may change before the child build
// runs. When empty, the child build uses the template's active
// version at the time it runs.
TemplateVersionID uuid.UUID `json:"template_version_id,omitempty" format:"uuid"`
// Transition must be "start". The parent build's transition must
// be "stop".
Transition WorkspaceTransition `json:"transition" validate:"oneof=start,required"`
// RichParameterValues are applied to the child build. Parameters
// not listed here fall back to their values from the previous
// build, matching normal build behavior.
RichParameterValues []WorkspaceBuildParameter `json:"rich_parameter_values,omitempty"`
// TemplateVersionPresetID selects a preset for the child build.
// It requires TemplateVersionID to also be set.
TemplateVersionPresetID uuid.UUID `json:"template_version_preset_id,omitempty" format:"uuid"`
}
type WorkspaceOptions struct {