Skip to content

Commit fa2d4eb

Browse files
committed
ui: make update button stop before start
1 parent 5131129 commit fa2d4eb

File tree

4 files changed

+69
-26
lines changed

4 files changed

+69
-26
lines changed

site/src/api/api.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,7 @@ class ApiMethods {
22372237
* - Update the build parameters and check if there are missed parameters for
22382238
* the newest version
22392239
* - If there are missing parameters raise an error
2240+
* - Stop the workspace with the current template version if it is already running
22402241
* - Create a build with the latest version and updated build parameters
22412242
*/
22422243
updateWorkspace = async (
@@ -2274,6 +2275,19 @@ class ApiMethods {
22742275
throw new MissingBuildParameters(missingParameters, activeVersionId);
22752276
}
22762277

2278+
// Stop the workspace if it is already running.
2279+
if (workspace.latest_build.status === "running") {
2280+
const stopBuild = await this.stopWorkspace(workspace.id);
2281+
const awaitedStopBuild = await this.waitForBuild(stopBuild);
2282+
// If the stop is canceled halfway through, we bail.
2283+
// This is the same behaviour as restartWorkspace.
2284+
if (awaitedStopBuild?.status === "canceled") {
2285+
return Promise.reject(
2286+
new Error("Workspace stop was canceled, not proceeding with update."),
2287+
);
2288+
}
2289+
}
2290+
22772291
return this.postWorkspaceBuild(workspace.id, {
22782292
transition: "start",
22792293
template_version_id: activeVersionId,

site/src/modules/workspaces/actions.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ import type { Workspace } from "api/typesGenerated";
66
const actionTypes = [
77
"start",
88
"starting",
9-
// Replaces start when an update is required.
9+
// Replaces start when an update is available.
1010
"updateAndStart",
11+
// Replaces start when an update is required.
12+
"updateAndStartRequireActiveVersion",
1113
"stop",
1214
"stopping",
1315
"restart",
1416
"restarting",
15-
// Replaces restart when an update is required.
17+
// Replaces restart when an update is available.
1618
"updateAndRestart",
19+
// Replaces restart when an update is required.
20+
"updateAndRestartRequireActiveVersion",
1721
"deleting",
18-
"update",
1922
"updating",
2023
"activate",
2124
"activating",
@@ -74,10 +77,10 @@ export const abilitiesByWorkspaceStatus = (
7477
const actions: ActionType[] = ["stop"];
7578

7679
if (workspace.template_require_active_version && workspace.outdated) {
77-
actions.push("updateAndRestart");
80+
actions.push("updateAndRestartRequireActiveVersion");
7881
} else {
7982
if (workspace.outdated) {
80-
actions.unshift("update");
83+
actions.unshift("updateAndRestart");
8184
}
8285
actions.push("restart");
8386
}
@@ -99,10 +102,10 @@ export const abilitiesByWorkspaceStatus = (
99102
const actions: ActionType[] = [];
100103

101104
if (workspace.template_require_active_version && workspace.outdated) {
102-
actions.push("updateAndStart");
105+
actions.push("updateAndStartRequireActiveVersion");
103106
} else {
104107
if (workspace.outdated) {
105-
actions.unshift("update");
108+
actions.unshift("updateAndStart");
106109
}
107110
actions.push("start");
108111
}
@@ -128,7 +131,7 @@ export const abilitiesByWorkspaceStatus = (
128131
}
129132

130133
if (workspace.outdated) {
131-
actions.unshift("update");
134+
actions.unshift("updateAndStart");
132135
}
133136

134137
return {

site/src/pages/WorkspacePage/WorkspaceActions/Buttons.tsx

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,39 @@ export interface ActionButtonProps {
2121
tooltipText?: string;
2222
}
2323

24-
export const UpdateButton: FC<ActionButtonProps> = ({
24+
export const UpdateAndStartButton: FC<ActionButtonProps> = ({
2525
handleAction,
2626
loading,
2727
}) => {
2828
return (
29-
<TopbarButton
30-
disabled={loading}
31-
data-testid="workspace-update-button"
32-
onClick={() => handleAction()}
33-
>
34-
<CloudIcon />
35-
{loading ? <>Updating&hellip;</> : <>Update&hellip;</>}
36-
</TopbarButton>
29+
<Tooltip title="Start workspace with the latest template version.">
30+
<TopbarButton
31+
disabled={loading}
32+
data-testid="workspace-update-button"
33+
onClick={() => handleAction()}
34+
>
35+
<CirclePlayIcon />
36+
{loading ? <>Updating&hellip;</> : <>Update&hellip;</>}
37+
</TopbarButton>
38+
</Tooltip>
39+
);
40+
};
41+
42+
export const UpdateAndRestartButton: FC<ActionButtonProps> = ({
43+
handleAction,
44+
loading,
45+
}) => {
46+
return (
47+
<Tooltip title="Stop workspace, if running, and restart it with the latest template version.">
48+
<TopbarButton
49+
disabled={loading}
50+
data-testid="workspace-update-and-restart-button"
51+
onClick={() => handleAction()}
52+
>
53+
<RotateCcwIcon />
54+
{loading ? <>Updating&hellip;</> : <>Update and restart&hellip;</>}
55+
</TopbarButton>
56+
</Tooltip>
3757
);
3858
};
3959

@@ -84,9 +104,9 @@ export const StartButton: FC<ActionButtonPropsWithWorkspace> = ({
84104
);
85105
};
86106

87-
export const UpdateAndStartButton: FC<ActionButtonProps> = ({
88-
handleAction,
89-
}) => {
107+
export const UpdateAndStartButtonRequireActiveVersion: FC<
108+
ActionButtonProps
109+
> = ({ handleAction }) => {
90110
return (
91111
<Tooltip title="This template requires automatic updates on workspace startup. Contact your administrator if you want to preserve the template version.">
92112
<TopbarButton onClick={() => handleAction()}>
@@ -138,9 +158,9 @@ export const RestartButton: FC<ActionButtonPropsWithWorkspace> = ({
138158
);
139159
};
140160

141-
export const UpdateAndRestartButton: FC<ActionButtonProps> = ({
142-
handleAction,
143-
}) => {
161+
export const UpdateAndRestartButtonRequireActiveVersion: FC<
162+
ActionButtonProps
163+
> = ({ handleAction }) => {
144164
return (
145165
<Tooltip title="This template requires automatic updates on workspace startup. Contact your administrator if you want to preserve the template version.">
146166
<TopbarButton onClick={() => handleAction()}>

site/src/pages/WorkspacePage/WorkspaceActions/WorkspaceActions.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import {
1818
RestartButton,
1919
StartButton,
2020
StopButton,
21+
UpdateAndRestartButtonRequireActiveVersion,
2122
UpdateAndRestartButton,
23+
UpdateAndStartButtonRequireActiveVersion,
2224
UpdateAndStartButton,
23-
UpdateButton,
2425
} from "./Buttons";
2526
import { DebugButton } from "./DebugButton";
2627
import { RetryButton } from "./RetryButton";
@@ -81,10 +82,15 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
8182

8283
// A mapping of button type to the corresponding React component
8384
const buttonMapping: Record<ActionType, ReactNode> = {
84-
update: <UpdateButton handleAction={handleUpdate} />,
8585
updateAndStart: <UpdateAndStartButton handleAction={handleUpdate} />,
86+
updateAndStartRequireActiveVersion: (
87+
<UpdateAndStartButtonRequireActiveVersion handleAction={handleUpdate} />
88+
),
8689
updateAndRestart: <UpdateAndRestartButton handleAction={handleUpdate} />,
87-
updating: <UpdateButton loading handleAction={handleUpdate} />,
90+
updateAndRestartRequireActiveVersion: (
91+
<UpdateAndRestartButtonRequireActiveVersion handleAction={handleUpdate} />
92+
),
93+
updating: <UpdateAndStartButton loading handleAction={handleUpdate} />,
8894
start: (
8995
<StartButton
9096
workspace={workspace}

0 commit comments

Comments
 (0)