diff --git a/components/dashboard/src/projects/Prebuilds.tsx b/components/dashboard/src/projects/Prebuilds.tsx
index 193fc9728059a5..c1f763b0417b41 100644
--- a/components/dashboard/src/projects/Prebuilds.tsx
+++ b/components/dashboard/src/projects/Prebuilds.tsx
@@ -103,7 +103,7 @@ export default function (props: { project?: Project, isAdminDashboard?: boolean
}, [prebuilds])
const prebuildContextMenu = (p: PrebuildWithStatus) => {
- const isFailed = p.status === "aborted" || p.status === "timeout" || !!p.error;
+ const isFailed = p.status === "aborted" || p.status === "timeout" || p.status === "failed"|| !!p.error;
const isRunning = p.status === "building";
const entries: ContextMenuEntry[] = [];
if (isFailed) {
@@ -248,8 +248,10 @@ export function prebuildStatusLabel(prebuild?: PrebuildWithStatus) {
return (running);
case "aborted":
return (canceled);
+ case "failed":
+ return (system error);
case "timeout":
- return (failed);
+ return (timed out);
case "available":
if (prebuild?.error) {
return (failed);
@@ -267,6 +269,8 @@ export function prebuildStatusIcon(prebuild?: PrebuildWithStatus) {
return
;
case "aborted":
return
;
+ case "failed":
+ return
;
case "timeout":
return
;
case "available":
diff --git a/components/dashboard/src/projects/Project.tsx b/components/dashboard/src/projects/Project.tsx
index 030f0cd75817fb..0ae4e93588bdfe 100644
--- a/components/dashboard/src/projects/Project.tsx
+++ b/components/dashboard/src/projects/Project.tsx
@@ -250,7 +250,7 @@ export default function () {
- triggerPrebuild(branch),
diff --git a/components/gitpod-protocol/src/headless-workspace-log.ts b/components/gitpod-protocol/src/headless-workspace-log.ts
index 7cac2a0bc7b91c..0f00e5a5b06cfd 100644
--- a/components/gitpod-protocol/src/headless-workspace-log.ts
+++ b/components/gitpod-protocol/src/headless-workspace-log.ts
@@ -11,6 +11,7 @@ export enum HeadlessWorkspaceEventType {
FinishedButFailed = "finish-fail",
AbortedTimedOut = "aborted-timeout",
Aborted = "aborted",
+ Failed = "failed",
Started = "started"
}
export namespace HeadlessWorkspaceEventType {
diff --git a/components/gitpod-protocol/src/protocol.ts b/components/gitpod-protocol/src/protocol.ts
index 20a7b8360c2d14..8c42f139186c08 100644
--- a/components/gitpod-protocol/src/protocol.ts
+++ b/components/gitpod-protocol/src/protocol.ts
@@ -645,12 +645,14 @@ export type PrebuiltWorkspaceState
= "queued"
// the workspace prebuild is currently running (i.e. there's a workspace pod deployed)
| "building"
- // the prebuild failed due to some issue with the system (e.g. missed a message, could not start workspace)
+ // the prebuild was aborted
| "aborted"
// the prebuild timed out
| "timeout"
- // the prebuild has finished and a snapshot is available
- | "available";
+ // the prebuild has finished (even if a headless task failed) and a snapshot is available
+ | "available"
+ // the prebuild (headless workspace) failed due to some system error
+ | "failed";
export interface PrebuiltWorkspace {
id: string;
diff --git a/components/server/ee/src/prebuilds/prebuild-manager.ts b/components/server/ee/src/prebuilds/prebuild-manager.ts
index 2ef2b4a67c5831..e2ab2a9e62d77c 100644
--- a/components/server/ee/src/prebuilds/prebuild-manager.ts
+++ b/components/server/ee/src/prebuilds/prebuild-manager.ts
@@ -72,7 +72,7 @@ export class PrebuildManager {
}
const existingPB = await this.workspaceDB.trace({ span }).findPrebuiltWorkspaceByCommit(cloneURL, commit);
// If the existing prebuild is failed, we want to retrigger it.
- if (!!existingPB && existingPB.state !== 'aborted' && existingPB.state !== 'timeout' && !existingPB.error) {
+ if (!!existingPB && existingPB.state !== 'aborted' && existingPB.state !== 'failed' && existingPB.state !== 'timeout') {
// If the existing prebuild is based on an outdated project config, we also want to retrigger it.
const existingPBWS = await this.workspaceDB.trace({ span }).findById(existingPB.buildWorkspaceId);
const existingConfig = existingPBWS?.config;
diff --git a/components/server/ee/src/prebuilds/prebuilt-status-maintainer.ts b/components/server/ee/src/prebuilds/prebuilt-status-maintainer.ts
index 9024e359d70d64..fe6c5026a60845 100644
--- a/components/server/ee/src/prebuilds/prebuilt-status-maintainer.ts
+++ b/components/server/ee/src/prebuilds/prebuilt-status-maintainer.ts
@@ -102,16 +102,18 @@ export class PrebuildStatusMaintainer implements Disposable {
protected getConclusionFromPrebuildState(pws: PrebuiltWorkspace): "error" | "failure" | "pending" | "success" {
if (pws.state === "aborted") {
return "error";
- } else if (pws.state === "queued") {
- return "pending";
+ } else if (pws.state === "failed") {
+ return "error";
} else if (pws.state === "timeout") {
return "error";
+ } else if (pws.state === "queued") {
+ return "pending";
+ } else if (pws.state === "building") {
+ return "pending";
} else if (pws.state === "available" && !pws.error) {
return "success";
} else if (pws.state === "available" && !!pws.error) {
return "failure";
- } else if (pws.state === "building") {
- return "pending";
} else {
log.warn("Should have updated prebuilt workspace updatable, but don't know how. Resorting to error conclusion.", { pws });
return "error";
diff --git a/components/server/src/workspace/workspace-starter.ts b/components/server/src/workspace/workspace-starter.ts
index 56bb9d9155a262..3b3c72a42fb23f 100644
--- a/components/server/src/workspace/workspace-starter.ts
+++ b/components/server/src/workspace/workspace-starter.ts
@@ -292,13 +292,13 @@ export class WorkspaceStarter {
// If we just attempted to start a workspace for a prebuild - and that failed, we have to fail the prebuild itself.
if (workspace.type === 'prebuild') {
const prebuild = await this.workspaceDb.trace({ span }).findPrebuildByWorkspaceID(workspace.id);
- if (prebuild && prebuild.state !== 'aborted') {
- prebuild.state = "aborted";
+ if (prebuild && prebuild.state !== 'failed') {
+ prebuild.state = "failed";
prebuild.error = err.toString();
await this.workspaceDb.trace({ span }).storePrebuiltWorkspace(prebuild)
await this.messageBus.notifyHeadlessUpdate({ span }, workspace.ownerId, workspace.id, {
- type: HeadlessWorkspaceEventType.Aborted,
+ type: HeadlessWorkspaceEventType.Failed,
// TODO: `workspaceID: workspace.id` not needed here? (found in ee/src/prebuilds/prebuild-queue-maintainer.ts and ee/src/bridge.ts)
});
}
diff --git a/components/ws-manager-bridge/ee/src/bridge.ts b/components/ws-manager-bridge/ee/src/bridge.ts
index e4857252ec5c6c..1f8294447b96c7 100644
--- a/components/ws-manager-bridge/ee/src/bridge.ts
+++ b/components/ws-manager-bridge/ee/src/bridge.ts
@@ -77,18 +77,22 @@ export class WorkspaceManagerBridgeEE extends WorkspaceManagerBridge {
prebuild.error = status.conditions!.timeout;
headlessUpdateType = HeadlessWorkspaceEventType.AbortedTimedOut;
} else if (!!status.conditions!.failed) {
- prebuild.state = "aborted";
+ prebuild.state = "failed";
prebuild.error = status.conditions!.failed;
- headlessUpdateType = HeadlessWorkspaceEventType.Aborted;
+ headlessUpdateType = HeadlessWorkspaceEventType.Failed;
} else if (!!status.conditions!.stoppedByRequest) {
prebuild.state = "aborted";
prebuild.error = "Cancelled";
headlessUpdateType = HeadlessWorkspaceEventType.Aborted;
} else if (!!status.conditions!.headlessTaskFailed) {
prebuild.state = "available";
- prebuild.error = status.conditions!.headlessTaskFailed;
+ if (status.conditions!.headlessTaskFailed)
+ prebuild.error = status.conditions!.headlessTaskFailed;
prebuild.snapshot = status.conditions!.snapshot;
headlessUpdateType = HeadlessWorkspaceEventType.FinishedButFailed;
+ } else if (!status.conditions!.snapshot) {
+ prebuild.state = "failed";
+ headlessUpdateType = HeadlessWorkspaceEventType.Failed;
} else {
prebuild.state = "available";
prebuild.snapshot = status.conditions!.snapshot;