From c530f5d3e4ebd1e708ad9cc5f6b1545af216e2f2 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Thu, 17 Jul 2025 23:58:50 +0000 Subject: [PATCH 1/5] something like this --- site/src/api/api.ts | 43 ++++++++++++++----- ...pdateBuildParametersDialogExperimental.tsx | 10 ++--- .../WorkspaceMoreActions.tsx | 12 +++--- .../workspaces/WorkspaceUpdateDialogs.tsx | 15 +++++-- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 013c018d5c656..333583e19ffef 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -24,6 +24,7 @@ import type dayjs from "dayjs"; import userAgentParser from "ua-parser-js"; import { OneWayWebSocket } from "../utils/OneWayWebSocket"; import { delay } from "../utils/delay"; +import { type FieldError, isApiError } from "./errors"; import type { DynamicParametersRequest, PostWorkspaceUsageRequest, @@ -390,6 +391,14 @@ export class MissingBuildParameters extends Error { } } +export class ParameterValidationError extends Error { + constructor( + public readonly versionId: string, + public readonly validations: FieldError[], + ) { + super("Parameters are not valid for new template version"); + } +} export type GetProvisionerJobsParams = { status?: string; limit?: number; @@ -1239,7 +1248,6 @@ class ApiMethods { `/api/v2/workspaces/${workspaceId}/builds`, data, ); - return response.data; }; @@ -2268,19 +2276,32 @@ class ApiMethods { const activeVersionId = template.active_version_id; - let templateParameters: TypesGen.TemplateVersionParameter[] = []; - if (isDynamicParametersEnabled) { - templateParameters = await this.getDynamicParameters( - activeVersionId, - workspace.owner_id, - oldBuildParameters, - ); - } else { - templateParameters = - await this.getTemplateVersionRichParameters(activeVersionId); + try { + return this.postWorkspaceBuild(workspace.id, { + transition: "start", + template_version_id: activeVersionId, + rich_parameter_values: newBuildParameters, + }); + } catch (error) { + if ( + isApiError(error) && + error.response.status === 400 && + error.response.data.validations && + error.response.data.validations.length > 0 + ) { + throw new ParameterValidationError( + activeVersionId, + error.response.data.validations, + ); + } + throw error; + } } + const templateParameters = + await this.getTemplateVersionRichParameters(activeVersionId); + const missingParameters = getMissingParameters( oldBuildParameters, newBuildParameters, diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental.tsx index 04bb92a5e79b2..850f31185af2c 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental.tsx @@ -1,4 +1,4 @@ -import type { TemplateVersionParameter } from "api/typesGenerated"; +import type { FieldError } from "api/errors"; import { Button } from "components/Button/Button"; import { Dialog, @@ -14,7 +14,7 @@ import { useNavigate } from "react-router-dom"; type UpdateBuildParametersDialogExperimentalProps = { open: boolean; onClose: () => void; - missedParameters: TemplateVersionParameter[]; + validations: FieldError[]; workspaceOwnerName: string; workspaceName: string; templateVersionId: string | undefined; @@ -23,7 +23,7 @@ type UpdateBuildParametersDialogExperimentalProps = { export const UpdateBuildParametersDialogExperimental: FC< UpdateBuildParametersDialogExperimentalProps > = ({ - missedParameters, + validations, open, onClose, workspaceOwnerName, @@ -47,8 +47,8 @@ export const UpdateBuildParametersDialogExperimental: FC< This template has{" "} - {missedParameters.length} new parameter - {missedParameters.length === 1 ? "" : "s"} + {validations.length} parameter + {validations.length === 1 ? "" : "s"} {" "} that must be configured to complete the update. diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx index 3853af67d394f..19d12ab2a394e 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx @@ -1,4 +1,4 @@ -import { MissingBuildParameters } from "api/api"; +import { MissingBuildParameters, ParameterValidationError } from "api/api"; import { isApiError } from "api/errors"; import { type ApiError, getErrorMessage } from "api/errors"; import { @@ -192,19 +192,19 @@ export const WorkspaceMoreActions: FC = ({ /> ) : ( { changeVersionMutation.reset(); }} workspaceOwnerName={workspace.owner_name} workspaceName={workspace.name} templateVersionId={ - changeVersionMutation.error instanceof MissingBuildParameters + changeVersionMutation.error instanceof ParameterValidationError ? changeVersionMutation.error?.versionId : undefined } diff --git a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx index bdad9e405bd48..435802e3c10ee 100644 --- a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx +++ b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx @@ -1,4 +1,4 @@ -import { MissingBuildParameters } from "api/api"; +import { MissingBuildParameters, ParameterValidationError } from "api/api"; import { updateWorkspace } from "api/queries/workspaces"; import type { TemplateVersion, @@ -78,7 +78,10 @@ export const useWorkspaceUpdate = ({ updateWorkspaceMutation.reset(); }, onUpdate: (buildParameters: WorkspaceBuildParameter[]) => { - if (updateWorkspaceMutation.error instanceof MissingBuildParameters) { + if ( + updateWorkspaceMutation.error instanceof MissingBuildParameters || + updateWorkspaceMutation.error instanceof ParameterValidationError + ) { confirmUpdate(buildParameters); } }, @@ -155,7 +158,9 @@ const MissingBuildParametersDialog: FC = ({ error instanceof MissingBuildParameters ? error.parameters : []; const versionId = error instanceof MissingBuildParameters ? error.versionId : undefined; - const isOpen = error instanceof MissingBuildParameters; + const isOpen = + error instanceof MissingBuildParameters || + error instanceof ParameterValidationError; return workspace.template_use_classic_parameter_flow ? ( = ({ /> ) : ( Date: Fri, 18 Jul 2025 00:03:07 +0000 Subject: [PATCH 2/5] `await` --- site/src/api/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 333583e19ffef..83f54e1933e87 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -2278,7 +2278,7 @@ class ApiMethods { if (isDynamicParametersEnabled) { try { - return this.postWorkspaceBuild(workspace.id, { + return await this.postWorkspaceBuild(workspace.id, { transition: "start", template_version_id: activeVersionId, rich_parameter_values: newBuildParameters, From 31ed5ea25071708f0a5b3f088859eae025a0fc2d Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 18 Jul 2025 00:08:03 +0000 Subject: [PATCH 3/5] fix version check --- site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx index 435802e3c10ee..8985165ca1394 100644 --- a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx +++ b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx @@ -177,7 +177,9 @@ const MissingBuildParametersDialog: FC = ({ onClose={dialogProps.onClose} workspaceOwnerName={workspace.owner_name} workspaceName={workspace.name} - templateVersionId={versionId} + templateVersionId={ + error instanceof ParameterValidationError ? error.versionId : undefined + } /> ); }; From 68043536d9b4a9328b57641c014e05a7fc216873 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 18 Jul 2025 00:25:42 +0000 Subject: [PATCH 4/5] lil cleanup --- site/src/api/api.ts | 11 +++++++---- .../src/modules/workspaces/WorkspaceUpdateDialogs.tsx | 6 ++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 83f54e1933e87..d70965b61f2e3 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -399,6 +399,7 @@ export class ParameterValidationError extends Error { super("Parameters are not valid for new template version"); } } + export type GetProvisionerJobsParams = { status?: string; limit?: number; @@ -2199,9 +2200,9 @@ class ApiMethods { default_value: p.default_value?.valid ? p.default_value.value : "", options: p.options ? p.options.map((opt) => ({ - ...opt, - value: opt.value?.valid ? opt.value.value : "", - })) + ...opt, + value: opt.value?.valid ? opt.value.value : "", + })) : [], })); }; @@ -2284,6 +2285,8 @@ class ApiMethods { rich_parameter_values: newBuildParameters, }); } catch (error) { + // If the build failed because of a parameter validation error, then we + // throw a special sentinel error that can be caught by the caller. if ( isApiError(error) && error.response.status === 400 && @@ -2625,7 +2628,7 @@ class ApiMethods { // All methods must be defined with arrow function syntax. See the docstring // above the ApiMethods class for a full explanation. class ExperimentalApiMethods { - constructor(protected readonly axios: AxiosInstance) {} + constructor(protected readonly axios: AxiosInstance) { } getAITasksPrompts = async ( buildIds: TypesGen.WorkspaceBuild["id"][], diff --git a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx index 8985165ca1394..2fad94de2da73 100644 --- a/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx +++ b/site/src/modules/workspaces/WorkspaceUpdateDialogs.tsx @@ -157,7 +157,7 @@ const MissingBuildParametersDialog: FC = ({ const missedParameters = error instanceof MissingBuildParameters ? error.parameters : []; const versionId = - error instanceof MissingBuildParameters ? error.versionId : undefined; + error instanceof ParameterValidationError ? error.versionId : undefined; const isOpen = error instanceof MissingBuildParameters || error instanceof ParameterValidationError; @@ -177,9 +177,7 @@ const MissingBuildParametersDialog: FC = ({ onClose={dialogProps.onClose} workspaceOwnerName={workspace.owner_name} workspaceName={workspace.name} - templateVersionId={ - error instanceof ParameterValidationError ? error.versionId : undefined - } + templateVersionId={versionId} /> ); }; From 975a2e6e66a449f2a0d611570dddd24fa579087a Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Fri, 18 Jul 2025 00:28:42 +0000 Subject: [PATCH 5/5] annoyed --- site/src/api/api.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index d70965b61f2e3..6b38515a74f1a 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -2200,9 +2200,9 @@ class ApiMethods { default_value: p.default_value?.valid ? p.default_value.value : "", options: p.options ? p.options.map((opt) => ({ - ...opt, - value: opt.value?.valid ? opt.value.value : "", - })) + ...opt, + value: opt.value?.valid ? opt.value.value : "", + })) : [], })); }; @@ -2628,7 +2628,7 @@ class ApiMethods { // All methods must be defined with arrow function syntax. See the docstring // above the ApiMethods class for a full explanation. class ExperimentalApiMethods { - constructor(protected readonly axios: AxiosInstance) { } + constructor(protected readonly axios: AxiosInstance) {} getAITasksPrompts = async ( buildIds: TypesGen.WorkspaceBuild["id"][], 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