Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit491e0e3

Browse files
authored
fix: display explicit 'retry' button(s) when a workspace fails (#10720)
* refactor: remove workspace error enums* fix: add in retry button for failed workspaces* fix: make handleBuildRetry auto-detect debug permissions* chore: consolidate retry messaging* chore: update renderWorkspacePage to accept parameters* chore: make workspace test helpers take explicit workspace parameter* refactor: update how parameters for tests are defined* fix: update old tests to be correctly parameterized
1 parent65c726e commit491e0e3

File tree

7 files changed

+371
-228
lines changed

7 files changed

+371
-228
lines changed

‎site/src/pages/WorkspacePage/Workspace.stories.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Meta, StoryObj } from "@storybook/react";
33
import{WatchAgentMetadataContext}from"components/Resources/AgentMetadata";
44
import{ProvisionerJobLog}from"api/typesGenerated";
55
import*asMocksfrom"testHelpers/entities";
6-
import{Workspace,WorkspaceErrors}from"./Workspace";
6+
import{Workspace}from"./Workspace";
77
import{withReactContext}from"storybook-react-context";
88
importEventSourcefrom"eventsourcemock";
99
import{ProxyContext,getPreferredProxy}from"contexts/ProxyContext";
@@ -133,7 +133,7 @@ export const Failed: Story = {
133133
...Running.args,
134134
workspace:Mocks.MockFailedWorkspace,
135135
workspaceErrors:{
136-
[WorkspaceErrors.BUILD_ERROR]:Mocks.mockApiError({
136+
buildError:Mocks.mockApiError({
137137
message:"A workspace build is already active.",
138138
}),
139139
},
@@ -172,7 +172,6 @@ export const FailedWithRetry: Story = {
172172
},
173173
},
174174
},
175-
canRetryDebugMode:true,
176175
buildLogs:<WorkspaceBuildLogsSectionlogs={makeFailedBuildLogs()}/>,
177176
},
178177
};
@@ -224,7 +223,7 @@ export const GetBuildsError: Story = {
224223
args:{
225224
...Running.args,
226225
workspaceErrors:{
227-
[WorkspaceErrors.GET_BUILDS_ERROR]:Mocks.mockApiError({
226+
getBuildsError:Mocks.mockApiError({
228227
message:"There is a problem fetching builds.",
229228
}),
230229
},
@@ -235,7 +234,7 @@ export const CancellationError: Story = {
235234
args:{
236235
...Failed.args,
237236
workspaceErrors:{
238-
[WorkspaceErrors.CANCELLATION_ERROR]:Mocks.mockApiError({
237+
cancellationError:Mocks.mockApiError({
239238
message:"Job could not be canceled.",
240239
}),
241240
},

‎site/src/pages/WorkspacePage/Workspace.tsx

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ import { BuildsTable } from "./BuildsTable";
2929
import{WorkspaceDeletedBanner}from"./WorkspaceDeletedBanner";
3030
import{WorkspaceStats}from"./WorkspaceStats";
3131

32-
exportenumWorkspaceErrors{
33-
GET_BUILDS_ERROR="getBuildsError",
34-
BUILD_ERROR="buildError",
35-
CANCELLATION_ERROR="cancellationError",
36-
}
32+
exporttypeWorkspaceError=
33+
|"getBuildsError"
34+
|"buildError"
35+
|"cancellationError";
36+
37+
exporttypeWorkspaceErrors=Partial<Record<WorkspaceError,unknown>>;
38+
3739
exportinterfaceWorkspaceProps{
3840
scheduleProps:{
3941
onDeadlinePlus:(hours:number)=>void;
@@ -56,16 +58,17 @@ export interface WorkspaceProps {
5658
resources?:TypesGen.WorkspaceResource[];
5759
canUpdateWorkspace:boolean;
5860
updateMessage?:string;
59-
canRetryDebugMode:boolean;
6061
canChangeVersions:boolean;
6162
hideSSHButton?:boolean;
6263
hideVSCodeDesktopButton?:boolean;
63-
workspaceErrors:Partial<Record<WorkspaceErrors,unknown>>;
64+
workspaceErrors:WorkspaceErrors;
6465
buildInfo?:TypesGen.BuildInfoResponse;
6566
sshPrefix?:string;
6667
template?:TypesGen.Template;
6768
quotaBudget?:number;
69+
canRetryDebugMode:boolean;
6870
handleBuildRetry:()=>void;
71+
handleBuildRetryDebug:()=>void;
6972
buildLogs?:React.ReactNode;
7073
builds:TypesGen.WorkspaceBuild[]|undefined;
7174
onLoadMoreBuilds:()=>void;
@@ -87,55 +90,39 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
8790
handleCancel,
8891
handleSettings,
8992
handleChangeVersion,
90-
handleDormantActivate:handleDormantActivate,
93+
handleDormantActivate,
9194
workspace,
9295
isUpdating,
9396
isRestarting,
9497
resources,
9598
builds,
9699
canUpdateWorkspace,
97100
updateMessage,
98-
canRetryDebugMode,
99101
canChangeVersions,
100102
workspaceErrors,
101103
hideSSHButton,
102104
hideVSCodeDesktopButton,
103105
buildInfo,
104106
sshPrefix,
105107
template,
108+
canRetryDebugMode,
106109
handleBuildRetry,
110+
handleBuildRetryDebug,
107111
buildLogs,
108112
onLoadMoreBuilds,
109113
isLoadingMoreBuilds,
110114
hasMoreBuilds,
111115
canAutostart,
112116
})=>{
113117
constnavigate=useNavigate();
114-
constserverVersion=buildInfo?.version||"";
115118
const{ saveLocal, getLocal}=useLocalStorage();
116119

117-
constbuildError=Boolean(workspaceErrors[WorkspaceErrors.BUILD_ERROR])&&(
118-
<ErrorAlert
119-
error={workspaceErrors[WorkspaceErrors.BUILD_ERROR]}
120-
dismissible
121-
/>
122-
);
123-
124-
constcancellationError=Boolean(
125-
workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR],
126-
)&&(
127-
<ErrorAlert
128-
error={workspaceErrors[WorkspaceErrors.CANCELLATION_ERROR]}
129-
dismissible
130-
/>
131-
);
132-
133-
lettransitionStats:TypesGen.TransitionStats|undefined=undefined;
134-
if(template!==undefined){
135-
transitionStats=ActiveTransition(template,workspace);
136-
}
137-
138120
const[showAlertPendingInQueue,setShowAlertPendingInQueue]=useState(false);
121+
122+
// 2023-11-15 - MES - This effect will be called every single render because
123+
// "now" will always change and invalidate the dependency array. Need to
124+
// figure out if this effect really should run every render (possibly meaning
125+
// no dependency array at all), or how to get the array stabilized (ideal)
139126
constnow=dayjs();
140127
useEffect(()=>{
141128
if(
@@ -174,6 +161,9 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
174161
constautoStartFailing=workspace.autostart_schedule&&!canAutostart;
175162
constrequiresManualUpdate=updateRequired&&autoStartFailing;
176163

164+
consttransitionStats=
165+
template!==undefined ?ActiveTransition(template,workspace) :undefined;
166+
177167
return(
178168
<>
179169
<FullWidthPageHeader>
@@ -213,8 +203,11 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
213203
handleUpdate={handleUpdate}
214204
handleCancel={handleCancel}
215205
handleSettings={handleSettings}
206+
handleRetry={handleBuildRetry}
207+
handleRetryDebug={handleBuildRetryDebug}
216208
handleChangeVersion={handleChangeVersion}
217209
handleDormantActivate={handleDormantActivate}
210+
canRetryDebug={canRetryDebugMode}
218211
canChangeVersions={canChangeVersions}
219212
isUpdating={isUpdating}
220213
isRestarting={isRestarting}
@@ -244,8 +237,15 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
244237
{updateMessage&&<AlertDetail>{updateMessage}</AlertDetail>}
245238
</Alert>
246239
))}
247-
{buildError}
248-
{cancellationError}
240+
241+
{Boolean(workspaceErrors.buildError)&&(
242+
<ErrorAlerterror={workspaceErrors.buildError}dismissible/>
243+
)}
244+
245+
{Boolean(workspaceErrors.cancellationError)&&(
246+
<ErrorAlerterror={workspaceErrors.cancellationError}dismissible/>
247+
)}
248+
249249
{workspace.latest_build.status==="running"&&
250250
!workspace.health.healthy&&(
251251
<Alert
@@ -311,16 +311,15 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
311311
<Alert
312312
severity="error"
313313
actions={
314-
canRetryDebugMode&&(
315-
<Button
316-
key={0}
317-
onClick={handleBuildRetry}
318-
variant="text"
319-
size="small"
320-
>
321-
Try in debug mode
322-
</Button>
323-
)
314+
<Button
315+
onClick={
316+
canRetryDebugMode ?handleBuildRetryDebug :handleBuildRetry
317+
}
318+
variant="text"
319+
size="small"
320+
>
321+
Retry{canRetryDebugMode&&" in debug mode"}
322+
</Button>
324323
}
325324
>
326325
<AlertTitle>Workspace build failed</AlertTitle>
@@ -357,17 +356,15 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
357356
showBuiltinApps={canUpdateWorkspace}
358357
hideSSHButton={hideSSHButton}
359358
hideVSCodeDesktopButton={hideVSCodeDesktopButton}
360-
serverVersion={serverVersion}
359+
serverVersion={buildInfo?.version||""}
361360
onUpdateAgent={handleUpdate}// On updating the workspace the agent version is also updated
362361
/>
363362
)}
364363
/>
365364
)}
366365

367-
{workspaceErrors[WorkspaceErrors.GET_BUILDS_ERROR] ?(
368-
<ErrorAlert
369-
error={workspaceErrors[WorkspaceErrors.GET_BUILDS_ERROR]}
370-
/>
366+
{workspaceErrors.getBuildsError ?(
367+
<ErrorAlerterror={workspaceErrors.getBuildsError}/>
371368
) :(
372369
<BuildsTable
373370
builds={builds}

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

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
1+
import{typeFC}from"react";
2+
importtype{Workspace,WorkspaceBuildParameter}from"api/typesGenerated";
3+
import{BuildParametersPopover}from"./BuildParametersPopover";
4+
5+
importTooltipfrom"@mui/material/Tooltip";
16
importButtonfrom"@mui/material/Button";
2-
importBlockIconfrom"@mui/icons-material/Block";
7+
importLoadingButtonfrom"@mui/lab/LoadingButton";
8+
importButtonGroupfrom"@mui/material/ButtonGroup";
39
importCloudQueueIconfrom"@mui/icons-material/CloudQueue";
410
importCropSquareIconfrom"@mui/icons-material/CropSquare";
511
importPlayCircleOutlineIconfrom"@mui/icons-material/PlayCircleOutline";
612
importReplayIconfrom"@mui/icons-material/Replay";
7-
import{FC}from"react";
8-
importBlockOutlinedfrom"@mui/icons-material/BlockOutlined";
9-
importButtonGroupfrom"@mui/material/ButtonGroup";
10-
import{Workspace,WorkspaceBuildParameter}from"api/typesGenerated";
11-
import{BuildParametersPopover}from"./BuildParametersPopover";
13+
importBlockIconfrom"@mui/icons-material/Block";
14+
importOutlinedBlockIconfrom"@mui/icons-material/BlockOutlined";
1215
importPowerSettingsNewIconfrom"@mui/icons-material/PowerSettingsNew";
13-
importLoadingButtonfrom"@mui/lab/LoadingButton";
14-
importTooltipfrom"@mui/material/Tooltip";
16+
importRetryIconfrom"@mui/icons-material/BuildOutlined";
17+
importRetryDebugIconfrom"@mui/icons-material/BugReportOutlined";
1518

16-
interfaceWorkspaceAction{
19+
interfaceWorkspaceActionProps{
1720
loading?:boolean;
1821
handleAction:()=>void;
1922
disabled?:boolean;
2023
tooltipText?:string;
2124
}
2225

23-
exportconstUpdateButton:FC<WorkspaceAction>=({
26+
exportconstUpdateButton:FC<WorkspaceActionProps>=({
2427
handleAction,
2528
loading,
2629
})=>{
@@ -37,7 +40,7 @@ export const UpdateButton: FC<WorkspaceAction> = ({
3740
);
3841
};
3942

40-
exportconstActivateButton:FC<WorkspaceAction>=({
43+
exportconstActivateButton:FC<WorkspaceActionProps>=({
4144
handleAction,
4245
loading,
4346
})=>{
@@ -54,7 +57,7 @@ export const ActivateButton: FC<WorkspaceAction> = ({
5457
};
5558

5659
exportconstStartButton:FC<
57-
Omit<WorkspaceAction,"handleAction">&{
60+
Omit<WorkspaceActionProps,"handleAction">&{
5861
workspace:Workspace;
5962
handleAction:(buildParameters?:WorkspaceBuildParameter[])=>void;
6063
}
@@ -63,7 +66,7 @@ export const StartButton: FC<
6366
<ButtonGroup
6467
variant="outlined"
6568
sx={{
66-
// Workaround to make the border transitionssmmothly on button groups
69+
// Workaround to make the border transitionssmoothly on button groups
6770
"& > button:hover + button":{
6871
borderLeft:"1px solid #FFF",
6972
},
@@ -94,7 +97,10 @@ export const StartButton: FC<
9497
);
9598
};
9699

97-
exportconstStopButton:FC<WorkspaceAction>=({ handleAction, loading})=>{
100+
exportconstStopButton:FC<WorkspaceActionProps>=({
101+
handleAction,
102+
loading,
103+
})=>{
98104
return(
99105
<LoadingButton
100106
loading={loading}
@@ -109,7 +115,7 @@ export const StopButton: FC<WorkspaceAction> = ({ handleAction, loading }) => {
109115
};
110116

111117
exportconstRestartButton:FC<
112-
Omit<WorkspaceAction,"handleAction">&{
118+
Omit<WorkspaceActionProps,"handleAction">&{
113119
workspace:Workspace;
114120
handleAction:(buildParameters?:WorkspaceBuildParameter[])=>void;
115121
}
@@ -118,7 +124,7 @@ export const RestartButton: FC<
118124
<ButtonGroup
119125
variant="outlined"
120126
sx={{
121-
// Workaround to make the border transitionssmmothly on button groups
127+
// Workaround to make the border transitionssmoothly on button groups
122128
"& > button:hover + button":{
123129
borderLeft:"1px solid #FFF",
124130
},
@@ -150,7 +156,7 @@ export const RestartButton: FC<
150156
);
151157
};
152158

153-
exportconstCancelButton:FC<WorkspaceAction>=({ handleAction})=>{
159+
exportconstCancelButton:FC<WorkspaceActionProps>=({ handleAction})=>{
154160
return(
155161
<ButtonstartIcon={<BlockIcon/>}onClick={handleAction}>
156162
Cancel
@@ -164,7 +170,7 @@ interface DisabledProps {
164170

165171
exportconstDisabledButton:FC<DisabledProps>=({ label})=>{
166172
return(
167-
<ButtonstartIcon={<BlockOutlined/>}disabled>
173+
<ButtonstartIcon={<OutlinedBlockIcon/>}disabled>
168174
{label}
169175
</Button>
170176
);
@@ -181,3 +187,21 @@ export const ActionLoadingButton: FC<LoadingProps> = ({ label }) => {
181187
</LoadingButton>
182188
);
183189
};
190+
191+
typeDebugButtonProps=Omit<WorkspaceActionProps,"loading">&{
192+
debug?:boolean;
193+
};
194+
195+
exportconstRetryButton=({
196+
handleAction,
197+
debug=false,
198+
}:DebugButtonProps)=>{
199+
return(
200+
<Button
201+
startIcon={debug ?<RetryDebugIcon/> :<RetryIcon/>}
202+
onClick={handleAction}
203+
>
204+
Retry{debug&&" (Debug)"}
205+
</Button>
206+
);
207+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp