From e3f1b21c5264414351631cdf3c609843dca12a8f Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Mon, 18 Aug 2025 20:22:45 +0000 Subject: [PATCH 1/5] feat: show workspace health error alert above agents in WorkspacePage --- .../pages/WorkspacePage/Workspace.stories.tsx | 7 ++++ site/src/pages/WorkspacePage/Workspace.tsx | 37 +++++++++++++++++++ .../WorkspaceNotifications.tsx | 2 +- site/src/testHelpers/entities.ts | 8 ++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacePage/Workspace.stories.tsx b/site/src/pages/WorkspacePage/Workspace.stories.tsx index 77ba7d67e94de..75081a669c14c 100644 --- a/site/src/pages/WorkspacePage/Workspace.stories.tsx +++ b/site/src/pages/WorkspacePage/Workspace.stories.tsx @@ -349,6 +349,13 @@ export const Stopping: Story = { }, }; +export const Unhealthy: Story = { + args: { + ...Running.args, + workspace: Mocks.MockUnhealthyWorkspace, + }, +}; + export const FailedWithLogs: Story = { args: { ...Running.args, diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 07c5ec26d0766..f5dc6e2ac7bc7 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -24,6 +24,8 @@ import { import { WorkspaceDeletedBanner } from "./WorkspaceDeletedBanner"; import { WorkspaceTopbar } from "./WorkspaceTopbar"; import { resourceOptionValue, useResourcesNav } from "./useResourcesNav"; +import { findTroubleshootingURL } from "./WorkspaceNotifications/WorkspaceNotifications"; +import { NotificationActionButton } from "./WorkspaceNotifications/Notifications"; interface WorkspaceProps { workspace: TypesGen.Workspace; @@ -98,6 +100,8 @@ export const Workspace: FC = ({ (workspace.latest_build.matched_provisioners?.available ?? 1) > 0; const shouldShowProvisionerAlert = workspacePending && !haveBuildLogs && !provisionersHealthy && !isRestarting; + const troubleshootingURL = findTroubleshootingURL(workspace.latest_build); + const hasActions = permissions.updateWorkspace || troubleshootingURL; return (
= ({ )} + {!workspace.health.healthy && ( + + Workspace is unhealthy + +

+ Your workspace is running but{" "} + {workspace.health.failing_agents.length > 1 + ? `${workspace.health.failing_agents.length} agents are unhealthy` + : "1 agent is unhealthy"} + . +

+ {hasActions && ( +
+ {permissions.updateWorkspace && ( + handleRestart()}> + Restart + + )} + {troubleshootingURL && ( + + window.open(troubleshootingURL, "_blank") + } + > + Troubleshooting + + )} +
+ )} +
+
+ )} + {transitionStats !== undefined && ( >; -const findTroubleshootingURL = ( +export const findTroubleshootingURL = ( workspaceBuild: WorkspaceBuild, ): string | undefined => { for (const resource of workspaceBuild.resources) { diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 8aac9f6233615..d91774645e887 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1443,6 +1443,14 @@ export const MockStoppingWorkspace: TypesGen.Workspace = { status: "stopping", }, }; +export const MockUnhealthyWorkspace: TypesGen.Workspace = { + ...MockWorkspace, + id: "test-unhealthy-workspace", + health: { + healthy: false, + failing_agents: ["test-workspace-agent"], + }, +}; export const MockStartingWorkspace: TypesGen.Workspace = { ...MockWorkspace, id: "test-starting-workspace", From 2d5b7913229684e2d8ac3bfe87c64b7c605fcf71 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Tue, 19 Aug 2025 01:00:25 +0000 Subject: [PATCH 2/5] style: fix import order --- site/src/pages/WorkspacePage/Workspace.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index a67e75d4c017f..53dd01741ffe6 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -21,9 +21,9 @@ import { WorkspaceBuildProgress, } from "./WorkspaceBuildProgress"; import { WorkspaceDeletedBanner } from "./WorkspaceDeletedBanner"; -import { WorkspaceTopbar } from "./WorkspaceTopbar"; -import { findTroubleshootingURL } from "./WorkspaceNotifications/WorkspaceNotifications"; import { NotificationActionButton } from "./WorkspaceNotifications/Notifications"; +import { findTroubleshootingURL } from "./WorkspaceNotifications/WorkspaceNotifications"; +import { WorkspaceTopbar } from "./WorkspaceTopbar"; interface WorkspaceProps { workspace: TypesGen.Workspace; From b6cfffced92dd8f38313ed26826a5cfa9a0f4627 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 21 Aug 2025 22:46:10 +0000 Subject: [PATCH 3/5] test: set MockUnhealthyWorkspace's agent to be in error state --- site/src/testHelpers/entities.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 71fcab75ec0c5..e29c9e9f43fd1 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -992,6 +992,15 @@ export const MockWorkspaceSubAgent: TypesGen.WorkspaceAgent = { ], }; +export const MockWorkspaceUnhealthyAgent: TypesGen.WorkspaceAgent = { + ...MockWorkspaceAgent, + id: "test-workspace-unhealthy-agent", + name: "a-workspace-unhealthy-agent", + status: "timeout", + lifecycle_state: "start_error", + health: { healthy: false }, +}; + export const MockWorkspaceAppStatus: TypesGen.WorkspaceAppStatus = { id: "test-app-status", created_at: "2022-05-17T17:39:01.382927298Z", @@ -1448,7 +1457,13 @@ export const MockUnhealthyWorkspace: TypesGen.Workspace = { id: "test-unhealthy-workspace", health: { healthy: false, - failing_agents: ["test-workspace-agent"], + failing_agents: [MockWorkspaceUnhealthyAgent.id], + }, + latest_build: { + ...MockWorkspace.latest_build, + resources: [ + { ...MockWorkspaceResource, agents: [MockWorkspaceUnhealthyAgent] }, + ], }, }; export const MockStartingWorkspace: TypesGen.Workspace = { From 988c3d3176948ed4b5e17ca1f1b169479c1b32f4 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 21 Aug 2025 22:50:08 +0000 Subject: [PATCH 4/5] test: add UnhealthyWithoutUpdatePermission Workspace story --- site/src/pages/WorkspacePage/Workspace.stories.tsx | 11 +++++++++++ .../WorkspaceNotifications.stories.tsx | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacePage/Workspace.stories.tsx b/site/src/pages/WorkspacePage/Workspace.stories.tsx index 69690a5bdc1fa..5a49e0fa57091 100644 --- a/site/src/pages/WorkspacePage/Workspace.stories.tsx +++ b/site/src/pages/WorkspacePage/Workspace.stories.tsx @@ -9,6 +9,7 @@ import type { ProvisionerJobLog } from "api/typesGenerated"; import { action } from "storybook/actions"; import type { WorkspacePermissions } from "../../modules/workspaces/permissions"; import { Workspace } from "./Workspace"; +import { defaultPermissions } from "./WorkspaceNotifications/WorkspaceNotifications.stories"; // Helper function to create timestamps easily - Copied from AppStatuses.stories.tsx const createTimestamp = ( @@ -356,6 +357,16 @@ export const Unhealthy: Story = { }, }; +export const UnhealthyWithoutUpdatePermission: Story = { + args: { + ...Unhealthy.args, + permissions: { + ...defaultPermissions, + updateWorkspace: false, + }, + }, +}; + export const FailedWithLogs: Story = { args: { ...Running.args, diff --git a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.stories.tsx b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.stories.tsx index 073a5090f2e42..bcff8c53cca59 100644 --- a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.stories.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.stories.tsx @@ -12,7 +12,7 @@ import type { WorkspacePermissions } from "modules/workspaces/permissions"; import { expect, userEvent, waitFor, within } from "storybook/test"; import { WorkspaceNotifications } from "./WorkspaceNotifications"; -const defaultPermissions: WorkspacePermissions = { +export const defaultPermissions: WorkspacePermissions = { readWorkspace: true, updateWorkspaceVersion: true, updateWorkspace: true, From eb0711fd4ee1b24336ff736f59cf67e90226a3a1 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 21 Aug 2025 22:56:47 +0000 Subject: [PATCH 5/5] refactor: remove unused export --- site/src/testHelpers/entities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index e29c9e9f43fd1..634c8f45886de 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -992,7 +992,7 @@ export const MockWorkspaceSubAgent: TypesGen.WorkspaceAgent = { ], }; -export const MockWorkspaceUnhealthyAgent: TypesGen.WorkspaceAgent = { +const MockWorkspaceUnhealthyAgent: TypesGen.WorkspaceAgent = { ...MockWorkspaceAgent, id: "test-workspace-unhealthy-agent", name: "a-workspace-unhealthy-agent", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy