From 532218e2a1057452949b8541caf4ec6ee47ab3a1 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Tue, 22 Jul 2025 22:16:31 +0000 Subject: [PATCH 01/29] feat: make dynamic parameters opt-in by default for new templates --- coderd/database/dbgen/dbgen.go | 2 +- coderd/insights_test.go | 18 +++++---- coderd/templates.go | 4 +- coderd/templates_test.go | 4 +- ...icParameterFlowDeprecationWarning.test.tsx | 34 +++++++++++++++++ ...ClassicParameterFlowDeprecationWarning.tsx | 37 +++++++++++++++++++ .../CreateWorkspacePage.tsx | 19 +++++++++- .../CreateWorkspacePageView.tsx | 9 +++++ .../CreateWorkspacePageViewExperimental.tsx | 4 +- .../TemplateSettingsForm.tsx | 13 ++++--- .../WorkspaceParametersForm.tsx | 11 +++++- .../WorkspaceParametersPage.tsx | 21 +++++++++++ .../WorkspaceParametersPageExperimental.tsx | 4 +- ...orkspaceParametersPageViewExperimental.tsx | 2 +- site/src/testHelpers/entities.ts | 4 +- 15 files changed, 156 insertions(+), 30 deletions(-) create mode 100644 site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx create mode 100644 site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 812d2e2576650..0ccefff2c42a9 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -147,7 +147,7 @@ func Template(t testing.TB, db database.Store, seed database.Template) database. DisplayName: takeFirst(seed.DisplayName, testutil.GetRandomName(t)), AllowUserCancelWorkspaceJobs: seed.AllowUserCancelWorkspaceJobs, MaxPortSharingLevel: takeFirst(seed.MaxPortSharingLevel, database.AppSharingLevelOwner), - UseClassicParameterFlow: takeFirst(seed.UseClassicParameterFlow, true), + UseClassicParameterFlow: takeFirst(seed.UseClassicParameterFlow, false), }) require.NoError(t, err, "insert template") diff --git a/coderd/insights_test.go b/coderd/insights_test.go index ded030351a3b3..0a12c39caf695 100644 --- a/coderd/insights_test.go +++ b/coderd/insights_test.go @@ -665,10 +665,11 @@ func TestTemplateInsights_Golden(t *testing.T) { // where we can control the template ID. // createdTemplate := coderdtest.CreateTemplate(t, client, firstUser.OrganizationID, version.ID) createdTemplate := dbgen.Template(t, db, database.Template{ - ID: template.id, - ActiveVersionID: version.ID, - OrganizationID: firstUser.OrganizationID, - CreatedBy: firstUser.UserID, + ID: template.id, + ActiveVersionID: version.ID, + OrganizationID: firstUser.OrganizationID, + CreatedBy: firstUser.UserID, + UseClassicParameterFlow: true, GroupACL: database.TemplateACL{ firstUser.OrganizationID.String(): db2sdk.TemplateRoleActions(codersdk.TemplateRoleUse), }, @@ -1556,10 +1557,11 @@ func TestUserActivityInsights_Golden(t *testing.T) { // where we can control the template ID. // createdTemplate := coderdtest.CreateTemplate(t, client, firstUser.OrganizationID, version.ID) createdTemplate := dbgen.Template(t, db, database.Template{ - ID: template.id, - ActiveVersionID: version.ID, - OrganizationID: firstUser.OrganizationID, - CreatedBy: firstUser.UserID, + ID: template.id, + ActiveVersionID: version.ID, + OrganizationID: firstUser.OrganizationID, + CreatedBy: firstUser.UserID, + UseClassicParameterFlow: true, // Required for parameter usage tracking in this test GroupACL: database.TemplateACL{ firstUser.OrganizationID.String(): db2sdk.TemplateRoleActions(codersdk.TemplateRoleUse), }, diff --git a/coderd/templates.go b/coderd/templates.go index bba38bb033614..60f94e5cd29cc 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -197,8 +197,8 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque return } - // Default is true until dynamic parameters are promoted to stable. - useClassicParameterFlow := ptr.NilToDefault(createTemplate.UseClassicParameterFlow, true) + // Default is false as dynamic parameters are now the preferred approach. + useClassicParameterFlow := ptr.NilToDefault(createTemplate.UseClassicParameterFlow, false) // Make a temporary struct to represent the template. This is used for // auditing if any of the following checks fail. It will be overwritten when diff --git a/coderd/templates_test.go b/coderd/templates_test.go index 5e7fcea75609d..0858ce83325cc 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -77,7 +77,7 @@ func TestPostTemplateByOrganization(t *testing.T) { assert.Equal(t, expected.Name, got.Name) assert.Equal(t, expected.Description, got.Description) assert.Equal(t, expected.ActivityBumpMillis, got.ActivityBumpMillis) - assert.Equal(t, expected.UseClassicParameterFlow, true) // Current default is true + assert.Equal(t, expected.UseClassicParameterFlow, false) // Current default is false require.Len(t, auditor.AuditLogs(), 3) assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs()[0].Action) @@ -1551,7 +1551,7 @@ func TestPatchTemplateMeta(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - require.True(t, template.UseClassicParameterFlow, "default is true") + require.False(t, template.UseClassicParameterFlow, "default is false") bTrue := true bFalse := false diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx new file mode 100644 index 0000000000000..4db00defed369 --- /dev/null +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx @@ -0,0 +1,34 @@ +import { render, screen } from "@testing-library/react"; +import { ClassicParameterFlowDeprecationWarning } from "./ClassicParameterFlowDeprecationWarning"; + +jest.mock("modules/navigation", () => ({ + useLinks: () => () => "/mock-link", + linkToTemplate: () => "/mock-template-link", +})); + +describe("ClassicParameterFlowDeprecationWarning", () => { + const defaultProps = { + enabled: true, + organizationName: "test-org", + templateName: "test-template", + canUpdateTemplate: true, + }; + + it("renders warning when enabled and user has template update permissions", () => { + render(); + + expect(screen.getByText("deprecated")).toBeInTheDocument(); + expect(screen.getByText("Go to Template Settings")).toBeInTheDocument(); + }); + + it("does not render when enabled is false", () => { + const { container } = render( + + ); + + expect(container.firstChild).toBeNull(); + }); +}); diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx new file mode 100644 index 0000000000000..247e8b90c3cc7 --- /dev/null +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx @@ -0,0 +1,37 @@ +import { Alert } from "components/Alert/Alert"; +import { Link } from "components/Link/Link"; +import { linkToTemplate, useLinks } from "modules/navigation"; +import type { FC } from "react"; + +interface ClassicParameterFlowDeprecationWarningProps { + organizationName: string; + templateName: string; + isEnabled: boolean; +} + +export const ClassicParameterFlowDeprecationWarning: FC< + ClassicParameterFlowDeprecationWarningProps +> = ({ organizationName, templateName, isEnabled }) => { + const getLink = useLinks(); + + if (!isEnabled) { + return null; + } + + const templateSettingsLink = `${getLink( + linkToTemplate(organizationName, templateName), + )}/settings`; + + return ( + +
+ This template is using the classic parameter flow, which will be{" "} + deprecated in a future release. + Please migrate to dynamic improved functionality. +
+ + Go to Template Settings + +
+ ); +}; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index 6d057a73d1a50..01bb10dcdec47 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -72,6 +72,20 @@ const CreateWorkspacePage: FC = () => { }), enabled: !!templateQuery.data, }); + const templatePermissionsQuery = useQuery({ + ...checkAuthorization({ + checks: { + canUpdateTemplate: { + object: { + resource_type: "template", + resource_id: templateQuery.data?.id ?? "", + }, + action: "update", + }, + }, + }), + enabled: !!templateQuery.data, + }); const realizedVersionId = customVersionId ?? templateQuery.data?.active_version_id; const organizationId = templateQuery.data?.organization_id; @@ -93,9 +107,10 @@ const CreateWorkspacePage: FC = () => { const isLoadingFormData = templateQuery.isLoading || permissionsQuery.isLoading || + templatePermissionsQuery.isLoading || richParametersQuery.isLoading; const loadFormDataError = - templateQuery.error ?? permissionsQuery.error ?? richParametersQuery.error; + templateQuery.error ?? permissionsQuery.error ?? templatePermissionsQuery.error ?? richParametersQuery.error; const title = autoCreateWorkspaceMutation.isPending ? "Creating workspace..." @@ -211,7 +226,7 @@ const CreateWorkspacePage: FC = () => { startPollingExternalAuth={startPollingExternalAuth} hasAllRequiredExternalAuth={hasAllRequiredExternalAuth} permissions={permissionsQuery.data as CreateWorkspacePermissions} - canUpdateTemplate={permissionsQuery.data?.canUpdateTemplate} + templatePermissions={templatePermissionsQuery.data as { canUpdateTemplate: boolean }} parameters={realizedParameters as TemplateVersionParameter[]} presets={templateVersionPresetsQuery.data ?? []} creatingWorkspace={createWorkspaceMutation.isPending} diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index ceac49988c0a5..e0674cd73fa13 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -28,6 +28,7 @@ import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import type { ExternalAuthPollingState } from "hooks/useExternalAuth"; import { ExternalLinkIcon } from "lucide-react"; +import { ClassicParameterFlowDeprecationWarning } from "modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { type FC, useCallback, useEffect, useMemo, useState } from "react"; import { Link } from "react-router-dom"; @@ -68,6 +69,7 @@ interface CreateWorkspacePageViewProps { autofillParameters: AutofillBuildParameter[]; presets: TypesGen.Preset[]; permissions: CreateWorkspacePermissions; + templatePermissions: { canUpdateTemplate: boolean }; creatingWorkspace: boolean; canUpdateTemplate?: boolean; onCancel: () => void; @@ -94,6 +96,7 @@ export const CreateWorkspacePageView: FC = ({ autofillParameters, presets = [], permissions, + templatePermissions, creatingWorkspace, canUpdateTemplate, onSubmit, @@ -261,6 +264,12 @@ export const CreateWorkspacePageView: FC = ({ + + View docs @@ -555,7 +555,7 @@ export const CreateWorkspacePageViewExperimental: FC< parameters cannot be modified once the workspace is created. View docs diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx index 677984e5e9e5a..359058f78761a 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx @@ -245,19 +245,20 @@ export const TemplateSettingsForm: FC = ({ label={ - Enable dynamic parameters for workspace creation + Enable dynamic parameters for workspace creation (recommended)
- The new workspace form allows you to design your template - with new form types and identity-aware conditional - parameters. The form will only present options that are - compatible and available. + The dynamic workspace form allows you to design your + template with additional form types and identity-aware + conditional parameters. This is the default option for new + templates. The classic workspace creation flow will be + deprecated in a future release.
Learn more diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx index 00b8c2ae8464b..8d419d1bb3722 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx @@ -14,6 +14,7 @@ import { import { RichParameterInput } from "components/RichParameterInput/RichParameterInput"; import { Spinner } from "components/Spinner/Spinner"; import { useFormik } from "formik"; +import { ClassicParameterFlowDeprecationWarning } from "modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning"; import type { FC } from "react"; import { getFormHelpers } from "utils/formUtils"; import { @@ -33,6 +34,7 @@ interface WorkspaceParameterFormProps { autofillParams: AutofillBuildParameter[]; isSubmitting: boolean; canChangeVersions: boolean; + templatePermissions: { canUpdateTemplate: boolean } | undefined; error: unknown; onCancel: () => void; onSubmit: (values: WorkspaceParametersFormValues) => void; @@ -46,6 +48,7 @@ export const WorkspaceParametersForm: FC = ({ autofillParams, error, canChangeVersions, + templatePermissions, isSubmitting, }) => { const form = useFormik({ @@ -81,12 +84,16 @@ export const WorkspaceParametersForm: FC = ({ return ( <> {disabled && ( - + The template for this workspace requires automatic updates. Update the workspace to edit parameters. )} - + {hasNonEphemeralParameters && ( { const permissions = permissionsQuery.data as WorkspacePermissions | undefined; const canChangeVersions = Boolean(permissions?.updateWorkspaceVersion); + const templatePermissionsQuery = useQuery({ + ...checkAuthorization({ + checks: { + canUpdateTemplate: { + object: { + resource_type: "template", + resource_id: workspace.template_id, + }, + action: "update", + }, + }, + }), + enabled: workspace !== undefined, + }); + + const templatePermissions = templatePermissionsQuery.data as { canUpdateTemplate: boolean } | undefined; + return ( <> @@ -60,6 +77,7 @@ const WorkspaceParametersPage: FC = () => { { type WorkspaceParametersPageViewProps = { workspace: Workspace; canChangeVersions: boolean; + templatePermissions: { canUpdateTemplate: boolean } | undefined; data: Awaited> | undefined; submitError: unknown; isSubmitting: boolean; @@ -106,6 +125,7 @@ export const WorkspaceParametersPageView: FC< > = ({ workspace, canChangeVersions, + templatePermissions, data, submitError, onSubmit, @@ -129,6 +149,7 @@ export const WorkspaceParametersPageView: FC< ({ ...p, source: "active_build", diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx index 803dc4ff4fd48..dcb2fda09a17f 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx @@ -226,7 +226,7 @@ const WorkspaceParametersPageExperimental: FC = () => {
View docs @@ -261,7 +261,7 @@ const WorkspaceParametersPageExperimental: FC = () => { message="This workspace has no parameters" cta={ Learn more about parameters diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageViewExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageViewExperimental.tsx index 14253ad51f827..52228f19d9f40 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageViewExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageViewExperimental.tsx @@ -210,7 +210,7 @@ export const WorkspaceParametersPageViewExperimental: FC< parameters cannot be modified once the workspace is created. View docs diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index a80e3b623a211..f8661bc55c5f2 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -826,7 +826,7 @@ export const MockTemplate: TypesGen.Template = { deprecated: false, deprecation_message: "", max_port_share_level: "public", - use_classic_parameter_flow: true, + use_classic_parameter_flow: false, }; const MockTemplateVersionFiles: TemplateVersionFiles = { @@ -1389,7 +1389,7 @@ export const MockWorkspace: TypesGen.Workspace = { MockTemplate.allow_user_cancel_workspace_jobs, template_active_version_id: MockTemplate.active_version_id, template_require_active_version: MockTemplate.require_active_version, - template_use_classic_parameter_flow: true, + template_use_classic_parameter_flow: false, outdated: false, owner_id: MockUserOwner.id, organization_id: MockOrganization.id, From 2ec580665e62e711a29d6f4f53684e4621b620b1 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Tue, 22 Jul 2025 22:20:13 +0000 Subject: [PATCH 02/29] fix: format --- .../ClassicParameterFlowDeprecationWarning.test.tsx | 9 +++++++-- .../ClassicParameterFlowDeprecationWarning.tsx | 4 ++-- .../pages/CreateWorkspacePage/CreateWorkspacePage.tsx | 9 +++++++-- .../WorkspaceParametersPage/WorkspaceParametersPage.tsx | 4 +++- .../WorkspaceParametersPageExperimental.tsx | 4 +++- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx index 4db00defed369..79abc4f9ada5f 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx @@ -15,7 +15,12 @@ describe("ClassicParameterFlowDeprecationWarning", () => { }; it("renders warning when enabled and user has template update permissions", () => { - render(); + render( + , + ); expect(screen.getByText("deprecated")).toBeInTheDocument(); expect(screen.getByText("Go to Template Settings")).toBeInTheDocument(); @@ -26,7 +31,7 @@ describe("ClassicParameterFlowDeprecationWarning", () => { + />, ); expect(container.firstChild).toBeNull(); diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx index 247e8b90c3cc7..9786888000526 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx @@ -26,8 +26,8 @@ export const ClassicParameterFlowDeprecationWarning: FC<
This template is using the classic parameter flow, which will be{" "} - deprecated in a future release. - Please migrate to dynamic improved functionality. + deprecated in a future release. Please migrate to + dynamic improved functionality.
Go to Template Settings diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index 01bb10dcdec47..b4c4c281c1b0d 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -110,7 +110,10 @@ const CreateWorkspacePage: FC = () => { templatePermissionsQuery.isLoading || richParametersQuery.isLoading; const loadFormDataError = - templateQuery.error ?? permissionsQuery.error ?? templatePermissionsQuery.error ?? richParametersQuery.error; + templateQuery.error ?? + permissionsQuery.error ?? + templatePermissionsQuery.error ?? + richParametersQuery.error; const title = autoCreateWorkspaceMutation.isPending ? "Creating workspace..." @@ -226,7 +229,9 @@ const CreateWorkspacePage: FC = () => { startPollingExternalAuth={startPollingExternalAuth} hasAllRequiredExternalAuth={hasAllRequiredExternalAuth} permissions={permissionsQuery.data as CreateWorkspacePermissions} - templatePermissions={templatePermissionsQuery.data as { canUpdateTemplate: boolean }} + templatePermissions={ + templatePermissionsQuery.data as { canUpdateTemplate: boolean } + } parameters={realizedParameters as TemplateVersionParameter[]} presets={templateVersionPresetsQuery.data ?? []} creatingWorkspace={createWorkspaceMutation.isPending} diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx index 927c2ae38b69a..c0dca85aa471c 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx @@ -66,7 +66,9 @@ const WorkspaceParametersPage: FC = () => { enabled: workspace !== undefined, }); - const templatePermissions = templatePermissionsQuery.data as { canUpdateTemplate: boolean } | undefined; + const templatePermissions = templatePermissionsQuery.data as + | { canUpdateTemplate: boolean } + | undefined; return ( <> diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx index dcb2fda09a17f..1415b1b2bc5f1 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx @@ -261,7 +261,9 @@ const WorkspaceParametersPageExperimental: FC = () => { message="This workspace has no parameters" cta={ Learn more about parameters From b933efe687b07159dfa40e32aa0a5a0dea4e7d2c Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Tue, 22 Jul 2025 22:35:46 +0000 Subject: [PATCH 03/29] fix: fix stories --- .../CreateWorkspacePage/CreateWorkspacePageView.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index 907c5e6861f68..7e5fa3e777d1e 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -31,6 +31,7 @@ const meta: Meta = { canUpdateTemplate: false, }, onCancel: action("onCancel"), + templatePermissions: { canUpdateTemplate: true }, }, }; From 7144f4f0ba0f2755392a3bfb4c8a6154eb81e46a Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 24 Jul 2025 20:08:45 +0000 Subject: [PATCH 04/29] chore: update warning content --- .../ClassicParameterFlowDeprecationWarning.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx index 9786888000526..f46f4b5e81b36 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx @@ -2,6 +2,7 @@ import { Alert } from "components/Alert/Alert"; import { Link } from "components/Link/Link"; import { linkToTemplate, useLinks } from "modules/navigation"; import type { FC } from "react"; +import { docs } from "utils/docs"; interface ClassicParameterFlowDeprecationWarningProps { organizationName: string; @@ -26,9 +27,17 @@ export const ClassicParameterFlowDeprecationWarning: FC<
This template is using the classic parameter flow, which will be{" "} - deprecated in a future release. Please migrate to - dynamic improved functionality. + deprecated and removed in a future release. Please + migrate to{" "} + + dynamic parameters + {" "} + on template settings for improved functionality.
+ Go to Template Settings From 170c5c6827cc9dfe54e73ee252a881e673f2e504 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 28 Jul 2025 18:15:48 +0000 Subject: [PATCH 05/29] chore: cleanup --- coderd/insights_test.go | 2 +- .../ClassicParameterFlowDeprecationWarning.test.tsx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/coderd/insights_test.go b/coderd/insights_test.go index 0a12c39caf695..d916b20fea26e 100644 --- a/coderd/insights_test.go +++ b/coderd/insights_test.go @@ -669,7 +669,7 @@ func TestTemplateInsights_Golden(t *testing.T) { ActiveVersionID: version.ID, OrganizationID: firstUser.OrganizationID, CreatedBy: firstUser.UserID, - UseClassicParameterFlow: true, + UseClassicParameterFlow: true, // Required for testing classic parameter flow behavior GroupACL: database.TemplateACL{ firstUser.OrganizationID.String(): db2sdk.TemplateRoleActions(codersdk.TemplateRoleUse), }, diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx index 79abc4f9ada5f..388c273756ef7 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx @@ -8,10 +8,8 @@ jest.mock("modules/navigation", () => ({ describe("ClassicParameterFlowDeprecationWarning", () => { const defaultProps = { - enabled: true, organizationName: "test-org", templateName: "test-template", - canUpdateTemplate: true, }; it("renders warning when enabled and user has template update permissions", () => { From 9bbd2b22f127c1839db6681b77b39cb799187900 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 13:23:20 -0500 Subject: [PATCH 06/29] flip golden default value --- cli/testdata/coder_list_--output_json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/testdata/coder_list_--output_json.golden b/cli/testdata/coder_list_--output_json.golden index 51c2887cd1e4a..822998329be5b 100644 --- a/cli/testdata/coder_list_--output_json.golden +++ b/cli/testdata/coder_list_--output_json.golden @@ -15,7 +15,7 @@ "template_allow_user_cancel_workspace_jobs": false, "template_active_version_id": "============[version ID]============", "template_require_active_version": false, - "template_use_classic_parameter_flow": true, + "template_use_classic_parameter_flow": false, "latest_build": { "id": "========[workspace build ID]========", "created_at": "====[timestamp]=====", From f25a9f87612fbb1a9115b3aba3299afcfb727f71 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 13:52:45 -0500 Subject: [PATCH 07/29] chore: echo provisioner reponses to include terraform to match --- provisioner/echo/parameter.tpl | 0 provisioner/echo/serve.go | 99 ++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 provisioner/echo/parameter.tpl diff --git a/provisioner/echo/parameter.tpl b/provisioner/echo/parameter.tpl new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 031af97317aca..335e3f06431fa 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "strings" + "text/template" "github.com/google/uuid" "golang.org/x/xerrors" @@ -377,6 +378,45 @@ func TarWithOptions(ctx context.Context, logger slog.Logger, responses *Response logger.Debug(context.Background(), "extra file written", slog.F("name", name), slog.F("bytes_written", n)) } + + // Write a main.tf with the appropriate parameters. This is to write terraform + // that matches the parameters defined in the responses. Dynamic parameters + // parsed these, even in the echo provisioner. + var mainTF bytes.Buffer + for _, respPlan := range responses.ProvisionPlan { + plan := respPlan.GetPlan() + if plan == nil { + continue + } + + for _, param := range plan.Parameters { + paramTF, err := ParameterTerraform(param) + if err != nil { + return nil, xerrors.Errorf("parameter terraform: %w", err) + } + mainTF.WriteString(paramTF) + } + } + + if mainTF.Len() > 0 { + mainTFData := ` +terraform { + required_providers { + coder = { + source = "coder/coder" + } + } +} +` + mainTF.String() + + _ = writer.WriteHeader(&tar.Header{ + Name: `main.tf`, + Size: int64(len(mainTFData)), + Mode: 0o644, + }) + _, _ = writer.Write([]byte(mainTFData)) + } + // `writer.Close()` function flushes the writer buffer, and adds extra padding to create a legal tarball. err := writer.Close() if err != nil { @@ -385,6 +425,65 @@ func TarWithOptions(ctx context.Context, logger slog.Logger, responses *Response return buffer.Bytes(), nil } +// ParameterTerraform will create a Terraform data block for the provided parameter. +func ParameterTerraform(param *proto.RichParameter) (string, error) { + tmpl := template.Must(template.New("parameter").Funcs(map[string]any{ + "showValidation": func(v *proto.RichParameter) bool { + return v != nil && (v.ValidationMax != nil || v.ValidationMin != nil || + v.ValidationError != "" || v.ValidationRegex != "" || + v.ValidationMonotonic != "") + }, + }).Parse(` +data "coder_parameter" "{{ .Name }}" { + name = "{{ .Name }}" + display_name = "{{ .DisplayName }}" + description = "{{ .Description }}" + icon = "{{ .Icon }}" + mutable = {{ .Mutable }} + ephemeral = {{ .Ephemeral }} + order = {{ .Order }} +{{- if .DefaultValue }} + default = "{{ .DefaultValue }}" +{{- end }} +{{- if .Type }} + type = "{{ .Type }}" +{{- end }} +{{- if .FormType }} + form_type = "{{ .FormType }}" +{{- end }} +{{- range .Options }} + option { + name = "{{ .Name }}" + value = "{{ .Value }}" + } +{{- end }} +{{- if showValidation .}} + validation { + {{- if .ValidationRegex }} + regex = "{{ .ValidationRegex }}" + {{- end }} + {{- if .ValidationError }} + error = "{{ .ValidationError }}" + {{- end }} + {{- if .ValidationMin }} + min = {{ .ValidationMin }} + {{- end }} + {{- if .ValidationMax }} + max = {{ .ValidationMax }} + {{- end }} + {{- if .ValidationMonotonic }} + monotonic = {{ .ValidationMonotonic }} + {{- end }} + } +{{- end }} +} +`)) + + var buf bytes.Buffer + err := tmpl.Execute(&buf, param) + return buf.String(), err +} + func WithResources(resources []*proto.Resource) *Responses { return &Responses{ Parse: ParseComplete, From b10945c94ca6122e270a13350cfd80e18bc91f4f Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 13:56:00 -0500 Subject: [PATCH 08/29] fixup! chore: echo provisioner reponses to include terraform to match --- provisioner/echo/serve.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 335e3f06431fa..9aad81b3fb67d 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -394,7 +394,7 @@ func TarWithOptions(ctx context.Context, logger slog.Logger, responses *Response if err != nil { return nil, xerrors.Errorf("parameter terraform: %w", err) } - mainTF.WriteString(paramTF) + _, _ = mainTF.WriteString(paramTF) } } From 67dc627fa51d2556bb19d772073454154966041a Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:10:52 -0500 Subject: [PATCH 09/29] fixup! fixup! chore: echo provisioner reponses to include terraform to match --- provisioner/echo/serve.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 9aad81b3fb67d..d8b461d8eb3dd 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -443,7 +443,7 @@ data "coder_parameter" "{{ .Name }}" { ephemeral = {{ .Ephemeral }} order = {{ .Order }} {{- if .DefaultValue }} - default = "{{ .DefaultValue }}" + default = {{ .DefaultValue }} {{- end }} {{- if .Type }} type = "{{ .Type }}" From 9eeb11b243e9a28168464dc5226f78984cf5ecf1 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 28 Jul 2025 19:16:00 +0000 Subject: [PATCH 10/29] fix: use classic parameter flow for MockWorkspace --- 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 f8661bc55c5f2..44e729e7f4d4f 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1389,7 +1389,7 @@ export const MockWorkspace: TypesGen.Workspace = { MockTemplate.allow_user_cancel_workspace_jobs, template_active_version_id: MockTemplate.active_version_id, template_require_active_version: MockTemplate.require_active_version, - template_use_classic_parameter_flow: false, + template_use_classic_parameter_flow: true, outdated: false, owner_id: MockUserOwner.id, organization_id: MockOrganization.id, From 7aa393cdb6cebff37a62c9ff788e74b88faa5fc9 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:27:24 -0500 Subject: [PATCH 11/29] sane defaultS --- coderd/workspaces_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index 141c62ff3a4b3..cb2e331b739cd 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -431,9 +431,9 @@ func TestWorkspace(t *testing.T) { // Test Utility variables templateVersionParameters := []*proto.RichParameter{ - {Name: "param1", Type: "string", Required: false}, - {Name: "param2", Type: "string", Required: false}, - {Name: "param3", Type: "string", Required: false}, + {Name: "param1", Type: "string", Required: false, DefaultValue: "default1"}, + {Name: "param2", Type: "string", Required: false, DefaultValue: "default2"}, + {Name: "param3", Type: "string", Required: false, DefaultValue: "default3"}, } presetParameters := []*proto.PresetParameter{ {Name: "param1", Value: "value1"}, From 238df67af1b8d5b22ad75272c82e2871ee7bdd2b Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:29:57 -0500 Subject: [PATCH 12/29] sane defaultS --- cli/start_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cli/start_test.go b/cli/start_test.go index 85b7b88374f72..094234a02e3e4 100644 --- a/cli/start_test.go +++ b/cli/start_test.go @@ -90,10 +90,11 @@ func TestStart(t *testing.T) { Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { - Name: ephemeralParameterName, - Description: ephemeralParameterDescription, - Mutable: true, - Ephemeral: true, + Name: ephemeralParameterName, + Description: ephemeralParameterDescription, + Mutable: true, + Ephemeral: true, + DefaultValue: "foo", }, }, }, From ee116fbfa4b2c2cf4a8169a0fcd0df519c9d5d11 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:32:28 -0500 Subject: [PATCH 13/29] fixup! sane defaultS --- cli/start_test.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cli/start_test.go b/cli/start_test.go index 094234a02e3e4..fd4b6cfefe4f3 100644 --- a/cli/start_test.go +++ b/cli/start_test.go @@ -90,11 +90,10 @@ func TestStart(t *testing.T) { Plan: &proto.PlanComplete{ Parameters: []*proto.RichParameter{ { - Name: ephemeralParameterName, - Description: ephemeralParameterDescription, - Mutable: true, - Ephemeral: true, - DefaultValue: "foo", + Name: ephemeralParameterName, + Description: ephemeralParameterDescription, + Mutable: true, + Ephemeral: true, }, }, }, @@ -114,10 +113,18 @@ func TestStart(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, template.ID) + workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) // Stop the workspace - workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop) + workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop, func(request *codersdk.CreateWorkspaceBuildRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "foo"}, // Value is required, set it to something + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceBuild.ID) inv, root := clitest.New(t, "start", workspace.Name, "--prompt-ephemeral-parameters") From d6a22626861bf2c4a1908be7214833338c3ae2a1 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:43:15 -0500 Subject: [PATCH 14/29] fixup! fixup! sane defaultS --- cli/update_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/update_test.go b/cli/update_test.go index 7a7480353c01d..6a99c12c7418e 100644 --- a/cli/update_test.go +++ b/cli/update_test.go @@ -182,7 +182,7 @@ func TestUpdateWithRichParameters(t *testing.T) { {Name: firstParameterName, Description: firstParameterDescription, Mutable: true}, {Name: immutableParameterName, Description: immutableParameterDescription, Mutable: false}, {Name: secondParameterName, Description: secondParameterDescription, Mutable: true}, - {Name: ephemeralParameterName, Description: ephemeralParameterDescription, Mutable: true, Ephemeral: true}, + {Name: ephemeralParameterName, Description: ephemeralParameterDescription, Mutable: true, Ephemeral: true, DefaultValue: "unset"}, }) } From cf8deb0f3f77ca3410ae7c8ece72acd2d6e97d44 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:56:26 -0500 Subject: [PATCH 15/29] restart and ephemeral parameters resolved --- cli/restart.go | 9 +++++++++ cli/restart_test.go | 12 ++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/cli/restart.go b/cli/restart.go index 156f506105c5a..d5dff00661604 100644 --- a/cli/restart.go +++ b/cli/restart.go @@ -51,8 +51,17 @@ func (r *RootCmd) restart() *serpent.Command { return err } + stopParamValues, err := asWorkspaceBuildParameters(parameterFlags.ephemeralParameters) + if err != nil { + return xerrors.Errorf("parse ephemeral parameters: %w", err) + } wbr := codersdk.CreateWorkspaceBuildRequest{ Transition: codersdk.WorkspaceTransitionStop, + // Ephemeral parameters should be passed to both stop and start builds. + // TODO: maybe these values should be sourced from the previous build? + // It has to be manually sourced, as ephermeral parameters do not carry across + // builds. + RichParameterValues: stopParamValues, } if bflags.provisionerLogDebug { wbr.LogLevel = codersdk.ProvisionerLogLevelDebug diff --git a/cli/restart_test.go b/cli/restart_test.go index d69344435bf28..6e4000e69d23e 100644 --- a/cli/restart_test.go +++ b/cli/restart_test.go @@ -71,7 +71,11 @@ func TestRestart(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, template.ID) + workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "placeholder"}, + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, root := clitest.New(t, "restart", workspace.Name, "--prompt-ephemeral-parameters") @@ -125,7 +129,11 @@ func TestRestart(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, template.ID) + workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "placeholder"}, + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, root := clitest.New(t, "restart", workspace.Name, From fc7b5d702b30de43bb3b95f706c691f0f2bab673 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 14:59:22 -0500 Subject: [PATCH 16/29] fixup! restart and ephemeral parameters resolved --- cli/restart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/restart.go b/cli/restart.go index d5dff00661604..20ee0b9b9de9d 100644 --- a/cli/restart.go +++ b/cli/restart.go @@ -59,7 +59,7 @@ func (r *RootCmd) restart() *serpent.Command { Transition: codersdk.WorkspaceTransitionStop, // Ephemeral parameters should be passed to both stop and start builds. // TODO: maybe these values should be sourced from the previous build? - // It has to be manually sourced, as ephermeral parameters do not carry across + // It has to be manually sourced, as ephemeral parameters do not carry across // builds. RichParameterValues: stopParamValues, } From adce52e745cfb7ba6743e0f2fdfea36c2f693006 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:16:14 -0500 Subject: [PATCH 17/29] add todo to fix this later --- cli/restart_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/cli/restart_test.go b/cli/restart_test.go index 6e4000e69d23e..01be7e590cebf 100644 --- a/cli/restart_test.go +++ b/cli/restart_test.go @@ -10,6 +10,7 @@ import ( "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" + "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" @@ -70,7 +71,9 @@ func TestRestart(t *testing.T) { member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) + template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) { + request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove when dynamic parameters prompt missing ephemeral parameters. + }) workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ {Name: ephemeralParameterName, Value: "placeholder"}, @@ -186,8 +189,14 @@ func TestRestart(t *testing.T) { member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, template.ID) + template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) { + request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove when dynamic parameters prompts missing ephemeral parameters + }) + workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "placeholder"}, + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, root := clitest.New(t, "restart", workspace.Name, "--build-options") @@ -241,7 +250,11 @@ func TestRestart(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, echoResponses()) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, template.ID) + workspace := coderdtest.CreateWorkspace(t, member, template.ID, func(request *codersdk.CreateWorkspaceRequest) { + request.RichParameterValues = []codersdk.WorkspaceBuildParameter{ + {Name: ephemeralParameterName, Value: "placeholder"}, + } + }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, root := clitest.New(t, "restart", workspace.Name, From a2358bf2a931ab861ec520e8bafba8dd5e250bd3 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 28 Jul 2025 20:21:13 +0000 Subject: [PATCH 18/29] fix: fix storybook tests --- .../ClassicParameterFlowDeprecationWarning.test.tsx | 2 ++ .../ClassicParameterFlowDeprecationWarning.tsx | 12 ++---------- .../CreateWorkspacePageView.stories.tsx | 2 ++ .../CreateWorkspacePage/CreateWorkspacePageView.tsx | 7 +++++-- .../WorkspaceParametersForm.tsx | 3 +-- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx index 388c273756ef7..f68bb273f26a0 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.test.tsx @@ -15,6 +15,7 @@ describe("ClassicParameterFlowDeprecationWarning", () => { it("renders warning when enabled and user has template update permissions", () => { render( , @@ -27,6 +28,7 @@ describe("ClassicParameterFlowDeprecationWarning", () => { it("does not render when enabled is false", () => { const { container } = render( , diff --git a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx index f46f4b5e81b36..d6afd3be464bf 100644 --- a/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx +++ b/site/src/modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning.tsx @@ -1,28 +1,20 @@ import { Alert } from "components/Alert/Alert"; import { Link } from "components/Link/Link"; -import { linkToTemplate, useLinks } from "modules/navigation"; import type { FC } from "react"; import { docs } from "utils/docs"; interface ClassicParameterFlowDeprecationWarningProps { - organizationName: string; - templateName: string; + templateSettingsLink: string; isEnabled: boolean; } export const ClassicParameterFlowDeprecationWarning: FC< ClassicParameterFlowDeprecationWarningProps -> = ({ organizationName, templateName, isEnabled }) => { - const getLink = useLinks(); - +> = ({ templateSettingsLink, isEnabled }) => { if (!isEnabled) { return null; } - const templateSettingsLink = `${getLink( - linkToTemplate(organizationName, templateName), - )}/settings`; - return (
diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index 7e5fa3e777d1e..f2f9d60be2246 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { chromatic } from "testHelpers/chromatic"; +import { withDashboardProvider } from "testHelpers/storybook"; import { MockTemplate, MockTemplateVersionParameter1, @@ -33,6 +34,7 @@ const meta: Meta = { onCancel: action("onCancel"), templatePermissions: { canUpdateTemplate: true }, }, + decorators: [withDashboardProvider], }; export default meta; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index e0674cd73fa13..bc31e1db42742 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -28,6 +28,7 @@ import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import type { ExternalAuthPollingState } from "hooks/useExternalAuth"; import { ExternalLinkIcon } from "lucide-react"; +import { linkToTemplate, useLinks } from "modules/navigation"; import { ClassicParameterFlowDeprecationWarning } from "modules/workspaces/ClassicParameterFlowDeprecationWarning/ClassicParameterFlowDeprecationWarning"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; import { type FC, useCallback, useEffect, useMemo, useState } from "react"; @@ -102,6 +103,7 @@ export const CreateWorkspacePageView: FC = ({ onSubmit, onCancel, }) => { + const getLink = useLinks(); const [owner, setOwner] = useState(defaultOwner); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), @@ -265,8 +267,9 @@ export const CreateWorkspacePageView: FC = ({ diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx index 8d419d1bb3722..68dc6e65b7595 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersForm.tsx @@ -90,8 +90,7 @@ export const WorkspaceParametersForm: FC = ({ )} From 273411a4e151021e15c8f78a0c7959b6f392a101 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:27:28 -0500 Subject: [PATCH 19/29] add todo to fix this later --- cli/update_test.go | 4 +++- provisioner/echo/serve.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/update_test.go b/cli/update_test.go index 6a99c12c7418e..b80218f49ab45 100644 --- a/cli/update_test.go +++ b/cli/update_test.go @@ -811,7 +811,9 @@ func TestUpdateValidateRichParameters(t *testing.T) { } version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, prepareEchoResponses(templateParameters)) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) + template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) { + request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove when dynamic parameters can pass this test + }) // Create new workspace inv, root := clitest.New(t, "create", "my-workspace", "--yes", "--template", template.Name, "--parameter", fmt.Sprintf("%s=%s", numberParameterName, tempVal)) diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index d8b461d8eb3dd..cc2d05513a836 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -472,7 +472,7 @@ data "coder_parameter" "{{ .Name }}" { max = {{ .ValidationMax }} {{- end }} {{- if .ValidationMonotonic }} - monotonic = {{ .ValidationMonotonic }} + monotonic = "{{ .ValidationMonotonic }}" {{- end }} } {{- end }} From 0501cff814fdb9ea1e07dfc4f1993e2765647685 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:30:33 -0500 Subject: [PATCH 20/29] add todo to fix this later --- coderd/workspaces_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index cb2e331b739cd..9fe066aae6284 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -3842,7 +3842,9 @@ func TestWorkspaceWithEphemeralRichParameters(t *testing.T) { }}, }) coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(request *codersdk.CreateTemplateRequest) { + request.UseClassicParameterFlow = ptr.Ref(true) // TODO: Remove this when dynamic parameters handles this case + }) // Create workspace with default values workspace := coderdtest.CreateWorkspace(t, client, template.ID) From b7064c0a0f8d61fbc33aa7cc03c1ea79795d5a7c Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:32:56 -0500 Subject: [PATCH 21/29] default orphaned template versions to dynamic params --- coderd/templateversions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/templateversions.go b/coderd/templateversions.go index e787a6b813b18..cc106b390f73c 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -1471,7 +1471,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht return } - var dynamicTemplate bool + dynamicTemplate := true // Default to using dynamic templates if req.TemplateID != uuid.Nil { tpl, err := api.Database.GetTemplateByID(ctx, req.TemplateID) if httpapi.Is404Error(err) { From fdbf0eb0e00df18d5af278c1dbfb42a5bdbbcaf0 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:37:27 -0500 Subject: [PATCH 22/29] add migration to make data schema consistent --- .../migrations/000352_default_dynamic_templates.down.sql | 1 + .../database/migrations/000352_default_dynamic_templates.up.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 coderd/database/migrations/000352_default_dynamic_templates.down.sql create mode 100644 coderd/database/migrations/000352_default_dynamic_templates.up.sql diff --git a/coderd/database/migrations/000352_default_dynamic_templates.down.sql b/coderd/database/migrations/000352_default_dynamic_templates.down.sql new file mode 100644 index 0000000000000..51bcab9f099f8 --- /dev/null +++ b/coderd/database/migrations/000352_default_dynamic_templates.down.sql @@ -0,0 +1 @@ +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false; diff --git a/coderd/database/migrations/000352_default_dynamic_templates.up.sql b/coderd/database/migrations/000352_default_dynamic_templates.up.sql new file mode 100644 index 0000000000000..548cd7e2c30b2 --- /dev/null +++ b/coderd/database/migrations/000352_default_dynamic_templates.up.sql @@ -0,0 +1 @@ +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT true; From 326d2bfda9d4def02a4ee4e2d7f1de09002ac0ad Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:38:45 -0500 Subject: [PATCH 23/29] fixup! add migration to make data schema consistent --- coderd/database/dump.sql | 2 +- .../migrations/000352_default_dynamic_templates.down.sql | 2 +- .../database/migrations/000352_default_dynamic_templates.up.sql | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index bbd6ca3ce5736..67d58ad05c802 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -1750,7 +1750,7 @@ CREATE TABLE templates ( deprecated text DEFAULT ''::text NOT NULL, activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL, max_port_sharing_level app_sharing_level DEFAULT 'owner'::app_sharing_level NOT NULL, - use_classic_parameter_flow boolean DEFAULT true NOT NULL + use_classic_parameter_flow boolean DEFAULT false NOT NULL ); COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.'; diff --git a/coderd/database/migrations/000352_default_dynamic_templates.down.sql b/coderd/database/migrations/000352_default_dynamic_templates.down.sql index 51bcab9f099f8..548cd7e2c30b2 100644 --- a/coderd/database/migrations/000352_default_dynamic_templates.down.sql +++ b/coderd/database/migrations/000352_default_dynamic_templates.down.sql @@ -1 +1 @@ -ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false; +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT true; diff --git a/coderd/database/migrations/000352_default_dynamic_templates.up.sql b/coderd/database/migrations/000352_default_dynamic_templates.up.sql index 548cd7e2c30b2..51bcab9f099f8 100644 --- a/coderd/database/migrations/000352_default_dynamic_templates.up.sql +++ b/coderd/database/migrations/000352_default_dynamic_templates.up.sql @@ -1 +1 @@ -ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT true; +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false; From 83e643d66071f90386c3d22efc8344ae235f8290 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 15:39:21 -0500 Subject: [PATCH 24/29] make fmt --- .../CreateWorkspacePage/CreateWorkspacePageView.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index f2f9d60be2246..4d0e3ff81c95f 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -3,7 +3,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { chromatic } from "testHelpers/chromatic"; -import { withDashboardProvider } from "testHelpers/storybook"; import { MockTemplate, MockTemplateVersionParameter1, @@ -12,6 +11,7 @@ import { MockUserOwner, mockApiError, } from "testHelpers/entities"; +import { withDashboardProvider } from "testHelpers/storybook"; import { CreateWorkspacePageView } from "./CreateWorkspacePageView"; const meta: Meta = { From ccb76a495a46874e81acd1c05ea564b56545a3dd Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 16:00:11 -0500 Subject: [PATCH 25/29] fixup tag tests --- coderd/templateversions_test.go | 59 +++++++++++---------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 1ad06bae38aee..e08afe53b1dec 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -275,6 +275,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { files map[string]string reqTags map[string]string wantTags map[string]string + variables []codersdk.VariableValue expectError string }{ { @@ -290,6 +291,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -311,6 +313,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -335,6 +338,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -365,6 +369,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -395,6 +400,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -429,11 +435,12 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { } }`, }, - reqTags: map[string]string{"a": "b"}, - wantTags: map[string]string{"owner": "", "scope": "organization", "a": "b"}, + reqTags: map[string]string{"a": "b"}, + wantTags: map[string]string{"owner": "", "scope": "organization", "a": "b"}, + variables: []codersdk.VariableValue{{Name: "a", Value: "b"}}, }, { - name: "main.tf with disallowed workspace tag value", + name: "main.tf with resource reference", files: map[string]string{ `main.tf`: ` variable "a" { @@ -441,6 +448,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } @@ -461,38 +469,8 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { } }`, }, - expectError: `Unknown variable; There is no variable named "null_resource".`, - }, - { - name: "main.tf with disallowed function in tag value", - files: map[string]string{ - `main.tf`: ` - variable "a" { - type = string - default = "1" - } - data "coder_parameter" "b" { - type = string - default = "2" - } - data "coder_parameter" "unrelated" { - name = "unrelated" - type = "list(string)" - default = jsonencode(["a", "b"]) - } - resource "null_resource" "test" { - name = "foo" - } - data "coder_workspace_tags" "tags" { - tags = { - "foo": "bar", - "a": var.a, - "b": data.coder_parameter.b.value, - "test": pathexpand("~/file.txt"), - } - }`, - }, - expectError: `function "pathexpand" may not be used here`, + reqTags: map[string]string{"foo": "bar", "a": "1", "b": "2", "test": "foo"}, + wantTags: map[string]string{"owner": "", "scope": "organization", "foo": "bar", "a": "1", "b": "2", "test": "foo"}, }, // We will allow coder_workspace_tags to set the scope on a template version import job // BUT the user ID will be ultimately determined by the API key in the scope. @@ -618,11 +596,12 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) { // Create a template version from the archive tvName := testutil.GetRandomNameHyphenated(t) tv, err := templateAdmin.CreateTemplateVersion(ctx, owner.OrganizationID, codersdk.CreateTemplateVersionRequest{ - Name: tvName, - StorageMethod: codersdk.ProvisionerStorageMethodFile, - Provisioner: codersdk.ProvisionerTypeTerraform, - FileID: fi.ID, - ProvisionerTags: tt.reqTags, + Name: tvName, + StorageMethod: codersdk.ProvisionerStorageMethodFile, + Provisioner: codersdk.ProvisionerTypeTerraform, + FileID: fi.ID, + ProvisionerTags: tt.reqTags, + UserVariableValues: tt.variables, }) if tt.expectError == "" { From c4f4fe5623faf4b986b189832686611d78a4e4e7 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 28 Jul 2025 16:05:42 -0500 Subject: [PATCH 26/29] parameters require names --- cli/templatepush_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/templatepush_test.go b/cli/templatepush_test.go index f7a31d5e0c25f..732fdd5ee50b0 100644 --- a/cli/templatepush_test.go +++ b/cli/templatepush_test.go @@ -509,6 +509,7 @@ func TestTemplatePush(t *testing.T) { default = "1" } data "coder_parameter" "b" { + name = "b" type = string default = "2" } From 95f53fd02c2c723880a1c43c36ad3c245ea219a0 Mon Sep 17 00:00:00 2001 From: "blink-so[bot]" <211532188+blink-so[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 21:13:23 +0000 Subject: [PATCH 27/29] fix(e2e): disable dynamic parameters for updateWorkspace tests The updateWorkspace tests were written for the classic parameter flow. With dynamic parameters now being the default, these tests need to explicitly disable dynamic parameters via the template settings page to continue working as expected. This fix: 1. Adds a disableDynamicParameters helper function 2. Modifies all updateWorkspace tests to disable dynamic parameters after template creation 3. Ensures tests use the classic parameter flow they were designed for Fixes the failing e2e test 'update workspace with ephemeral parameter enabled'. --- site/e2e/helpers.ts | 33 +++++++++++++++++++ .../tests/workspaces/updateWorkspace.spec.ts | 10 ++++++ 2 files changed, 43 insertions(+) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index a738899b25f2c..0742bba924cfb 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -1203,3 +1203,36 @@ export async function addUserToOrganization( } await page.mouse.click(10, 10); // close the popover by clicking outside of it } + +/** + * disableDynamicParameters navigates to the template settings page and disables + * dynamic parameters by unchecking the "Enable dynamic parameters" checkbox. + */ +export const disableDynamicParameters = async ( + page: Page, + templateName: string, + orgName = defaultOrganizationName, +) => { + await page.goto(`/templates/${orgName}/${templateName}/settings`, { + waitUntil: "domcontentloaded", + }); + + // Find and uncheck the "Enable dynamic parameters" checkbox + const dynamicParamsCheckbox = page.getByRole("checkbox", { + name: /Enable dynamic parameters for workspace creation/, + }); + + // If the checkbox is checked, uncheck it + if (await dynamicParamsCheckbox.isChecked()) { + await dynamicParamsCheckbox.click(); + } + + // Save the changes + await page.getByRole("button", { name: /save/i }).click(); + + // Wait for the success message or page to update + await page.waitForSelector("text=Template updated successfully", { + state: "visible", + timeout: 10000, + }); +}; diff --git a/site/e2e/tests/workspaces/updateWorkspace.spec.ts b/site/e2e/tests/workspaces/updateWorkspace.spec.ts index 48c341eb63956..8a242a2dc7238 100644 --- a/site/e2e/tests/workspaces/updateWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/updateWorkspace.spec.ts @@ -3,6 +3,7 @@ import { users } from "../../constants"; import { createTemplate, createWorkspace, + disableDynamicParameters, echoResponsesWithParameters, updateTemplate, updateWorkspace, @@ -34,6 +35,9 @@ test("update workspace, new optional, immutable parameter added", async ({ echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); @@ -77,6 +81,9 @@ test("update workspace, new required, mutable parameter added", async ({ echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); @@ -122,6 +129,9 @@ test("update workspace with ephemeral parameter enabled", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); From 9ba0b67a7078b39694c93796b244f4ff2baa6f02 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 28 Jul 2025 21:33:11 +0000 Subject: [PATCH 28/29] fix: use classic parameters for workspace tests --- .../tests/workspaces/createWorkspace.spec.ts | 22 +++++++++++++++++++ .../tests/workspaces/restartWorkspace.spec.ts | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/site/e2e/tests/workspaces/createWorkspace.spec.ts b/site/e2e/tests/workspaces/createWorkspace.spec.ts index 452c6e9969f37..e9d2d5efcca6f 100644 --- a/site/e2e/tests/workspaces/createWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/createWorkspace.spec.ts @@ -4,6 +4,7 @@ import { StarterTemplates, createTemplate, createWorkspace, + disableDynamicParameters, echoResponsesWithParameters, login, openTerminalWindow, @@ -35,6 +36,9 @@ test("create workspace", async ({ page }) => { apply: [{ apply: { resources: [{ name: "example" }] } }], }); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); await createWorkspace(page, template); }); @@ -51,6 +55,9 @@ test("create workspace with default immutable parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); await verifyParameters(page, workspaceName, richParameters, [ @@ -68,6 +75,9 @@ test("create workspace with default mutable parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); await verifyParameters(page, workspaceName, richParameters, [ @@ -95,6 +105,9 @@ test("create workspace with default and required parameters", async ({ echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template, { richParameters, @@ -127,6 +140,9 @@ test("create workspace and overwrite default parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template, { richParameters, @@ -147,6 +163,9 @@ test("create workspace with disable_param search params", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, templateName); + await login(page, users.member); await page.goto( `/templates/${templateName}/workspace?disable_params=first_parameter,second_parameter`, @@ -165,6 +184,9 @@ test.skip("create docker workspace", async ({ context, page }) => { await login(page, users.templateAdmin); const template = await createTemplate(page, StarterTemplates.STARTER_DOCKER); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); diff --git a/site/e2e/tests/workspaces/restartWorkspace.spec.ts b/site/e2e/tests/workspaces/restartWorkspace.spec.ts index 444ff891f0fdc..413215eeb5880 100644 --- a/site/e2e/tests/workspaces/restartWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/restartWorkspace.spec.ts @@ -4,6 +4,7 @@ import { buildWorkspaceWithParameters, createTemplate, createWorkspace, + disableDynamicParameters, echoResponsesWithParameters, verifyParameters, } from "../../helpers"; @@ -12,6 +13,7 @@ import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; + test.beforeEach(async ({ page }) => { beforeCoderTest(page); }); @@ -24,6 +26,9 @@ test("restart workspace with ephemeral parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); From 5cd3e0bfe30879045d35523855e67b5763899c40 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 28 Jul 2025 21:38:42 +0000 Subject: [PATCH 29/29] fix: fix e2e tests --- site/e2e/tests/workspaces/restartWorkspace.spec.ts | 1 - site/e2e/tests/workspaces/startWorkspace.spec.ts | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/site/e2e/tests/workspaces/restartWorkspace.spec.ts b/site/e2e/tests/workspaces/restartWorkspace.spec.ts index 413215eeb5880..2ec24c6d251bf 100644 --- a/site/e2e/tests/workspaces/restartWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/restartWorkspace.spec.ts @@ -13,7 +13,6 @@ import { beforeCoderTest } from "../../hooks"; import { firstBuildOption, secondBuildOption } from "../../parameters"; import type { RichParameter } from "../../provisionerGenerated"; - test.beforeEach(async ({ page }) => { beforeCoderTest(page); }); diff --git a/site/e2e/tests/workspaces/startWorkspace.spec.ts b/site/e2e/tests/workspaces/startWorkspace.spec.ts index 90fac440046ea..ea8a5c21c88bd 100644 --- a/site/e2e/tests/workspaces/startWorkspace.spec.ts +++ b/site/e2e/tests/workspaces/startWorkspace.spec.ts @@ -4,6 +4,7 @@ import { buildWorkspaceWithParameters, createTemplate, createWorkspace, + disableDynamicParameters, echoResponsesWithParameters, stopWorkspace, verifyParameters, @@ -25,6 +26,9 @@ test("start workspace with ephemeral parameters", async ({ page }) => { echoResponsesWithParameters(richParameters), ); + // Disable dynamic parameters to use classic parameter flow for this test + await disableDynamicParameters(page, template); + await login(page, users.member); const workspaceName = await createWorkspace(page, template); 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