Skip to content

Commit 6dcafb8

Browse files
committed
[prebuilds] Introduce 'failed' state for prebuilds
Distinguish between failed tasks but finished prebuilds and fully failed prebuilds (no snapshot) fixes #8592
1 parent 2863582 commit 6dcafb8

File tree

8 files changed

+30
-16
lines changed

8 files changed

+30
-16
lines changed

components/dashboard/src/projects/Prebuilds.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ export function prebuildStatusLabel(prebuild?: PrebuildWithStatus) {
248248
return (<span className="font-medium text-blue-500 uppercase">running</span>);
249249
case "aborted":
250250
return (<span className="font-medium text-gray-500 uppercase">canceled</span>);
251+
case "failed":
252+
return (<span className="font-medium text-red-500 uppercase">failed</span>);
251253
case "timeout":
252254
return (<span className="font-medium text-red-500 uppercase">failed</span>);
253255
case "available":
@@ -267,6 +269,8 @@ export function prebuildStatusIcon(prebuild?: PrebuildWithStatus) {
267269
return <img alt="" className="h-4 w-4" src={StatusRunning} />;
268270
case "aborted":
269271
return <img alt="" className="h-4 w-4" src={StatusCanceled} />;
272+
case "failed":
273+
return <img alt="" className="h-4 w-4" src={StatusFailed} />;
270274
case "timeout":
271275
return <img alt="" className="h-4 w-4" src={StatusFailed} />;
272276
case "available":

components/dashboard/src/projects/Project.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ export default function () {
250250
<a href={gitpodHostUrl.withContext(`${branch.url}`).toString()}>
251251
<button className={`primary mr-2 py-2 opacity-0 group-hover:opacity-100`}>New Workspace</button>
252252
</a>
253-
<ItemFieldContextMenu className="py-0.5" menuEntries={(!prebuild || prebuild.status === 'aborted' || prebuild.status === 'timeout' || !!prebuild.error)
253+
<ItemFieldContextMenu className="py-0.5" menuEntries={(!prebuild || prebuild.status === 'aborted' || prebuild.status === 'failed' || prebuild.status === 'timeout' || !!prebuild.error)
254254
? [{
255255
title: `${prebuild ? 'Rerun' : 'Run'} Prebuild (${branch.name})`,
256256
onClick: () => triggerPrebuild(branch),

components/gitpod-protocol/src/headless-workspace-log.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export enum HeadlessWorkspaceEventType {
1111
FinishedButFailed = "finish-fail",
1212
AbortedTimedOut = "aborted-timeout",
1313
Aborted = "aborted",
14+
Failed = "failed",
1415
Started = "started"
1516
}
1617
export namespace HeadlessWorkspaceEventType {

components/gitpod-protocol/src/protocol.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,14 @@ export type PrebuiltWorkspaceState
645645
= "queued"
646646
// the workspace prebuild is currently running (i.e. there's a workspace pod deployed)
647647
| "building"
648-
// the prebuild failed due to some issue with the system (e.g. missed a message, could not start workspace)
648+
// the prebuild was aborted
649649
| "aborted"
650650
// the prebuild timed out
651651
| "timeout"
652-
// the prebuild has finished and a snapshot is available
653-
| "available";
652+
// the prebuild has finished (even if a headless task failed) and a snapshot is available
653+
| "available"
654+
// the prebuild (headless workspace) failed due to some system error
655+
| "failed";
654656

655657
export interface PrebuiltWorkspace {
656658
id: string;

components/server/ee/src/prebuilds/prebuild-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class PrebuildManager {
7272
}
7373
const existingPB = await this.workspaceDB.trace({ span }).findPrebuiltWorkspaceByCommit(cloneURL, commit);
7474
// If the existing prebuild is failed, we want to retrigger it.
75-
if (!!existingPB && existingPB.state !== 'aborted' && existingPB.state !== 'timeout' && !existingPB.error) {
75+
if (!!existingPB && existingPB.state !== 'aborted' && existingPB.state !== 'failed' && existingPB.state !== 'timeout') {
7676
// If the existing prebuild is based on an outdated project config, we also want to retrigger it.
7777
const existingPBWS = await this.workspaceDB.trace({ span }).findById(existingPB.buildWorkspaceId);
7878
const existingConfig = existingPBWS?.config;

components/server/ee/src/prebuilds/prebuilt-status-maintainer.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,18 @@ export class PrebuildStatusMaintainer implements Disposable {
102102
protected getConclusionFromPrebuildState(pws: PrebuiltWorkspace): "error" | "failure" | "pending" | "success" {
103103
if (pws.state === "aborted") {
104104
return "error";
105-
} else if (pws.state === "queued") {
106-
return "pending";
105+
} else if (pws.state === "failed") {
106+
return "error";
107107
} else if (pws.state === "timeout") {
108108
return "error";
109+
} else if (pws.state === "queued") {
110+
return "pending";
111+
} else if (pws.state === "building") {
112+
return "pending";
109113
} else if (pws.state === "available" && !pws.error) {
110114
return "success";
111115
} else if (pws.state === "available" && !!pws.error) {
112116
return "failure";
113-
} else if (pws.state === "building") {
114-
return "pending";
115117
} else {
116118
log.warn("Should have updated prebuilt workspace updatable, but don't know how. Resorting to error conclusion.", { pws });
117119
return "error";

components/server/src/workspace/workspace-starter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,13 @@ export class WorkspaceStarter {
292292
// If we just attempted to start a workspace for a prebuild - and that failed, we have to fail the prebuild itself.
293293
if (workspace.type === 'prebuild') {
294294
const prebuild = await this.workspaceDb.trace({ span }).findPrebuildByWorkspaceID(workspace.id);
295-
if (prebuild && prebuild.state !== 'aborted') {
296-
prebuild.state = "aborted";
295+
if (prebuild && prebuild.state !== 'failed') {
296+
prebuild.state = "failed";
297297
prebuild.error = err.toString();
298298

299299
await this.workspaceDb.trace({ span }).storePrebuiltWorkspace(prebuild)
300300
await this.messageBus.notifyHeadlessUpdate({ span }, workspace.ownerId, workspace.id, <HeadlessWorkspaceEvent>{
301-
type: HeadlessWorkspaceEventType.Aborted,
301+
type: HeadlessWorkspaceEventType.Failed,
302302
// TODO: `workspaceID: workspace.id` not needed here? (found in ee/src/prebuilds/prebuild-queue-maintainer.ts and ee/src/bridge.ts)
303303
});
304304
}

components/ws-manager-bridge/ee/src/bridge.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,23 @@ export class WorkspaceManagerBridgeEE extends WorkspaceManagerBridge {
7777
prebuild.error = status.conditions!.timeout;
7878
headlessUpdateType = HeadlessWorkspaceEventType.AbortedTimedOut;
7979
} else if (!!status.conditions!.failed) {
80-
prebuild.state = "aborted";
81-
prebuild.error = status.conditions!.failed;
82-
headlessUpdateType = HeadlessWorkspaceEventType.Aborted;
80+
prebuild.state = "failed";
81+
if (status.conditions!.failed)
82+
prebuild.error = status.conditions!.failed;
83+
headlessUpdateType = HeadlessWorkspaceEventType.Failed;
8384
} else if (!!status.conditions!.stoppedByRequest) {
8485
prebuild.state = "aborted";
8586
prebuild.error = "Cancelled";
8687
headlessUpdateType = HeadlessWorkspaceEventType.Aborted;
8788
} else if (!!status.conditions!.headlessTaskFailed) {
8889
prebuild.state = "available";
89-
prebuild.error = status.conditions!.headlessTaskFailed;
90+
if (status.conditions!.headlessTaskFailed)
91+
prebuild.error = status.conditions!.headlessTaskFailed;
9092
prebuild.snapshot = status.conditions!.snapshot;
9193
headlessUpdateType = HeadlessWorkspaceEventType.FinishedButFailed;
94+
} else if (!status.conditions!.snapshot) {
95+
prebuild.state = "failed";
96+
headlessUpdateType = HeadlessWorkspaceEventType.Failed;
9297
} else {
9398
prebuild.state = "available";
9499
prebuild.snapshot = status.conditions!.snapshot;

0 commit comments

Comments
 (0)