From f1269312198cbee8f5a4a996a5bdec5ccf0dcaff Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 12 Jun 2025 17:15:05 +0100 Subject: [PATCH 1/3] chore: remove dynamic-parameters experiment (#18290) Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: jaaydenh <1858163+jaaydenh@users.noreply.github.com> Co-authored-by: Steven Masley --- cli/testdata/coder_list_--output_json.golden | 2 +- coderd/apidoc/docs.go | 3 - coderd/apidoc/swagger.json | 3 - coderd/coderd.go | 3 - coderd/database/dbmem/dbmem.go | 1 + coderd/database/dump.sql | 2 +- ...000334_dynamic_parameters_opt_out.down.sql | 3 + .../000334_dynamic_parameters_opt_out.up.sql | 4 ++ coderd/parameters_test.go | 13 ++-- coderd/templates_test.go | 2 +- coderd/workspacebuilds.go | 16 +---- coderd/workspaces.go | 2 +- coderd/wsbuilder/wsbuilder.go | 21 +++--- coderd/wsbuilder/wsbuilder_test.go | 9 +-- codersdk/deployment.go | 1 - docs/reference/api/schemas.md | 1 - enterprise/coderd/parameters_test.go | 4 +- enterprise/coderd/workspaces_test.go | 8 ++- site/src/api/typesGenerated.ts | 1 - .../useDynamicParametersOptOut.ts | 9 +-- .../WorkspaceMoreActions.tsx | 7 +- .../workspaces/WorkspaceUpdateDialogs.tsx | 16 ++--- .../CreateWorkspaceExperimentRouter.tsx | 72 +++++++++---------- .../TemplateSettingsForm.tsx | 62 ++++++++-------- .../TemplateSettingsPage.test.tsx | 2 +- .../TemplateSettingsPage.tsx | 3 - .../TemplateSettingsPageView.tsx | 3 - .../WorkspaceParametersExperimentRouter.tsx | 61 +++++++--------- .../pages/WorkspacesPage/WorkspacesPage.tsx | 4 +- site/src/testHelpers/entities.ts | 4 +- 30 files changed, 144 insertions(+), 198 deletions(-) create mode 100644 coderd/database/migrations/000334_dynamic_parameters_opt_out.down.sql create mode 100644 coderd/database/migrations/000334_dynamic_parameters_opt_out.up.sql diff --git a/cli/testdata/coder_list_--output_json.golden b/cli/testdata/coder_list_--output_json.golden index c37c89c4efe2a..5304f2ce262ee 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": false, + "template_use_classic_parameter_flow": true, "latest_build": { "id": "========[workspace build ID]========", "created_at": "====[timestamp]=====", diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index d11a0635d6f52..5dc293e2e706e 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -12745,7 +12745,6 @@ const docTemplate = `{ "notifications", "workspace-usage", "web-push", - "dynamic-parameters", "workspace-prebuilds", "agentic-chat", "ai-tasks" @@ -12754,7 +12753,6 @@ const docTemplate = `{ "ExperimentAITasks": "Enables the new AI tasks feature.", "ExperimentAgenticChat": "Enables the new agentic AI chat feature.", "ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.", - "ExperimentDynamicParameters": "Enables dynamic parameters when creating a workspace.", "ExperimentExample": "This isn't used for anything.", "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentWebPush": "Enables web push notifications through the browser.", @@ -12767,7 +12765,6 @@ const docTemplate = `{ "ExperimentNotifications", "ExperimentWorkspaceUsage", "ExperimentWebPush", - "ExperimentDynamicParameters", "ExperimentWorkspacePrebuilds", "ExperimentAgenticChat", "ExperimentAITasks" diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index aabe0b9b12672..ff48e99d393fc 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -11438,7 +11438,6 @@ "notifications", "workspace-usage", "web-push", - "dynamic-parameters", "workspace-prebuilds", "agentic-chat", "ai-tasks" @@ -11447,7 +11446,6 @@ "ExperimentAITasks": "Enables the new AI tasks feature.", "ExperimentAgenticChat": "Enables the new agentic AI chat feature.", "ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.", - "ExperimentDynamicParameters": "Enables dynamic parameters when creating a workspace.", "ExperimentExample": "This isn't used for anything.", "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentWebPush": "Enables web push notifications through the browser.", @@ -11460,7 +11458,6 @@ "ExperimentNotifications", "ExperimentWorkspaceUsage", "ExperimentWebPush", - "ExperimentDynamicParameters", "ExperimentWorkspacePrebuilds", "ExperimentAgenticChat", "ExperimentAITasks" diff --git a/coderd/coderd.go b/coderd/coderd.go index 0b8a13befde56..8cc5435542189 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1153,9 +1153,6 @@ func New(options *Options) *API { }) r.Group(func(r chi.Router) { - r.Use( - httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentDynamicParameters), - ) r.Route("/dynamic-parameters", func(r chi.Router) { r.Post("/evaluate", api.templateVersionDynamicParametersEvaluate) r.Get("/", api.templateVersionDynamicParametersWebsocket) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index f838a93d24c78..cc63844ce16a3 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -9345,6 +9345,7 @@ func (q *FakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl AllowUserAutostart: true, AllowUserAutostop: true, MaxPortSharingLevel: arg.MaxPortSharingLevel, + UseClassicParameterFlow: true, } q.templates = append(q.templates, template) return nil diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 22a0b3d5a8adc..e4cee2333efc4 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -1626,7 +1626,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 false NOT NULL + use_classic_parameter_flow boolean DEFAULT true 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/000334_dynamic_parameters_opt_out.down.sql b/coderd/database/migrations/000334_dynamic_parameters_opt_out.down.sql new file mode 100644 index 0000000000000..d18fcc87e87da --- /dev/null +++ b/coderd/database/migrations/000334_dynamic_parameters_opt_out.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false; + +UPDATE templates SET use_classic_parameter_flow = false diff --git a/coderd/database/migrations/000334_dynamic_parameters_opt_out.up.sql b/coderd/database/migrations/000334_dynamic_parameters_opt_out.up.sql new file mode 100644 index 0000000000000..342275f64ad9c --- /dev/null +++ b/coderd/database/migrations/000334_dynamic_parameters_opt_out.up.sql @@ -0,0 +1,4 @@ +-- All templates should opt out of dynamic parameters by default. +ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT true; + +UPDATE templates SET use_classic_parameter_flow = true diff --git a/coderd/parameters_test.go b/coderd/parameters_test.go index e2973dcbac138..da2c19ba20e3c 100644 --- a/coderd/parameters_test.go +++ b/coderd/parameters_test.go @@ -29,9 +29,7 @@ import ( func TestDynamicParametersOwnerSSHPublicKey(t *testing.T) { t.Parallel() - cfg := coderdtest.DeploymentValues(t) - cfg.Experiments = []string{string(codersdk.ExperimentDynamicParameters)} - ownerClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: cfg}) + ownerClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) owner := coderdtest.CreateFirstUser(t, ownerClient) templateAdmin, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin()) @@ -354,14 +352,11 @@ type dynamicParamsTest struct { } func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dynamicParamsTest { - cfg := coderdtest.DeploymentValues(t) - cfg.Experiments = []string{string(codersdk.ExperimentDynamicParameters)} ownerClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ Database: args.db, Pubsub: args.ps, IncludeProvisionerDaemon: true, ProvisionerDaemonVersion: args.provisionerDaemonVersion, - DeploymentValues: cfg, }) owner := coderdtest.CreateFirstUser(t, ownerClient) @@ -384,6 +379,12 @@ func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dyn coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, version.ID) tpl := coderdtest.CreateTemplate(t, templateAdmin, owner.OrganizationID, version.ID) + var err error + tpl, err = templateAdmin.UpdateTemplateMeta(t.Context(), tpl.ID, codersdk.UpdateTemplateMeta{ + UseClassicParameterFlow: ptr.Ref(false), + }) + require.NoError(t, err) + ctx := testutil.Context(t, testutil.WaitShort) stream, err := templateAdmin.TemplateVersionDynamicParameters(ctx, version.ID) if args.expectWebsocketError { diff --git a/coderd/templates_test.go b/coderd/templates_test.go index f5fbe49741838..f8f2b1372263c 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -1548,7 +1548,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.False(t, template.UseClassicParameterFlow, "default is false") + require.True(t, template.UseClassicParameterFlow, "default is true") bTrue := true bFalse := false diff --git a/coderd/workspacebuilds.go b/coderd/workspacebuilds.go index c01004653f86e..4d90948a8f9a1 100644 --- a/coderd/workspacebuilds.go +++ b/coderd/workspacebuilds.go @@ -384,20 +384,8 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) { builder = builder.State(createBuild.ProvisionerState) } - // Only defer to dynamic parameters if the experiment is enabled. - if api.Experiments.Enabled(codersdk.ExperimentDynamicParameters) { - if createBuild.EnableDynamicParameters != nil { - // Explicit opt-in - builder = builder.DynamicParameters(*createBuild.EnableDynamicParameters) - } - } else { - if createBuild.EnableDynamicParameters != nil { - api.Logger.Warn(ctx, "ignoring dynamic parameter field sent by request, the experiment is not enabled", - slog.F("field", *createBuild.EnableDynamicParameters), - slog.F("user", apiKey.UserID.String()), - slog.F("transition", string(createBuild.Transition)), - ) - } + if createBuild.EnableDynamicParameters != nil { + builder = builder.DynamicParameters(*createBuild.EnableDynamicParameters) } workspaceBuild, provisionerJob, provisionerDaemons, err = builder.Build( diff --git a/coderd/workspaces.go b/coderd/workspaces.go index fe0c2d3f609a2..d38de99e95eba 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -717,7 +717,7 @@ func createWorkspace( builder = builder.MarkPrebuiltWorkspaceClaim() } - if req.EnableDynamicParameters && api.Experiments.Enabled(codersdk.ExperimentDynamicParameters) { + if req.EnableDynamicParameters { builder = builder.DynamicParameters(req.EnableDynamicParameters) } diff --git a/coderd/wsbuilder/wsbuilder.go b/coderd/wsbuilder/wsbuilder.go index bcc2cef40ebdc..201ef0c53a307 100644 --- a/coderd/wsbuilder/wsbuilder.go +++ b/coderd/wsbuilder/wsbuilder.go @@ -1042,8 +1042,15 @@ func (b *Builder) checkRunningBuild() error { } func (b *Builder) usingDynamicParameters() bool { - if !b.experiments.Enabled(codersdk.ExperimentDynamicParameters) { - // Experiment required + if b.dynamicParametersEnabled != nil { + return *b.dynamicParametersEnabled + } + + tpl, err := b.getTemplate() + if err != nil { + return false // Let another part of the code get this error + } + if tpl.UseClassicParameterFlow { return false } @@ -1056,15 +1063,7 @@ func (b *Builder) usingDynamicParameters() bool { return false } - if b.dynamicParametersEnabled != nil { - return *b.dynamicParametersEnabled - } - - tpl, err := b.getTemplate() - if err != nil { - return false // Let another part of the code get this error - } - return !tpl.UseClassicParameterFlow + return true } func ProvisionerVersionSupportsDynamicParameters(version string) bool { diff --git a/coderd/wsbuilder/wsbuilder_test.go b/coderd/wsbuilder/wsbuilder_test.go index abe5e3fe9b8b7..58999a33e6e5e 100644 --- a/coderd/wsbuilder/wsbuilder_test.go +++ b/coderd/wsbuilder/wsbuilder_test.go @@ -894,10 +894,11 @@ func withTemplate(mTx *dbmock.MockStore) { mTx.EXPECT().GetTemplateByID(gomock.Any(), templateID). Times(1). Return(database.Template{ - ID: templateID, - OrganizationID: orgID, - Provisioner: database.ProvisionerTypeTerraform, - ActiveVersionID: activeVersionID, + ID: templateID, + OrganizationID: orgID, + Provisioner: database.ProvisionerTypeTerraform, + ActiveVersionID: activeVersionID, + UseClassicParameterFlow: true, }, nil) } diff --git a/codersdk/deployment.go b/codersdk/deployment.go index ac72ed2fc1ec1..23715e50a8aba 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -3356,7 +3356,6 @@ const ( ExperimentNotifications Experiment = "notifications" // Sends notifications via SMTP and webhooks following certain events. ExperimentWorkspaceUsage Experiment = "workspace-usage" // Enables the new workspace usage tracking. ExperimentWebPush Experiment = "web-push" // Enables web push notifications through the browser. - ExperimentDynamicParameters Experiment = "dynamic-parameters" // Enables dynamic parameters when creating a workspace. ExperimentWorkspacePrebuilds Experiment = "workspace-prebuilds" // Enables the new workspace prebuilds feature. ExperimentAgenticChat Experiment = "agentic-chat" // Enables the new agentic AI chat feature. ExperimentAITasks Experiment = "ai-tasks" // Enables the new AI tasks feature. diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 4191ab8970e92..a5b759e5dfb0c 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -3512,7 +3512,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | `notifications` | | `workspace-usage` | | `web-push` | -| `dynamic-parameters` | | `workspace-prebuilds` | | `agentic-chat` | | `ai-tasks` | diff --git a/enterprise/coderd/parameters_test.go b/enterprise/coderd/parameters_test.go index 605385430e779..5fc0eaa4aa369 100644 --- a/enterprise/coderd/parameters_test.go +++ b/enterprise/coderd/parameters_test.go @@ -21,8 +21,6 @@ import ( func TestDynamicParametersOwnerGroups(t *testing.T) { t.Parallel() - cfg := coderdtest.DeploymentValues(t) - cfg.Experiments = []string{string(codersdk.ExperimentDynamicParameters)} ownerClient, owner := coderdenttest.New(t, &coderdenttest.Options{ LicenseOptions: &coderdenttest.LicenseOptions{ @@ -30,7 +28,7 @@ func TestDynamicParametersOwnerGroups(t *testing.T) { codersdk.FeatureTemplateRBAC: 1, }, }, - Options: &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: cfg}, + Options: &coderdtest.Options{IncludeProvisionerDaemon: true}, }, ) templateAdmin, templateAdminUser := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin()) diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index 226232f37bf7f..ce86151f9b883 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -1698,7 +1698,7 @@ func TestWorkspaceTemplateParamsChange(t *testing.T) { logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}) dv := coderdtest.DeploymentValues(t) - dv.Experiments = []string{string(codersdk.ExperimentDynamicParameters)} + client, owner := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ Logger: &logger, @@ -1736,6 +1736,12 @@ func TestWorkspaceTemplateParamsChange(t *testing.T) { require.NoError(t, err, "failed to create template version") coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, tv.ID) tpl := coderdtest.CreateTemplate(t, templateAdmin, owner.OrganizationID, tv.ID) + + // Set to dynamic params + tpl, err = client.UpdateTemplateMeta(ctx, tpl.ID, codersdk.UpdateTemplateMeta{ + UseClassicParameterFlow: ptr.Ref(false), + }) + require.NoError(t, err, "failed to update template meta") require.False(t, tpl.UseClassicParameterFlow, "template to use dynamic parameters") // When: we create a workspace build using the above template but with diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index c662b27386401..a512305c489d3 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -830,7 +830,6 @@ export type Experiment = | "ai-tasks" | "agentic-chat" | "auto-fill-parameters" - | "dynamic-parameters" | "example" | "notifications" | "web-push" diff --git a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts b/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts index 6401f5f7f3564..22364edb0c70f 100644 --- a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts +++ b/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts @@ -25,13 +25,8 @@ export const useDynamicParametersOptOut = ({ const localStorageKey = optOutKey(templateId); const storedOptOutString = localStorage.getItem(localStorageKey); - let optedOut: boolean; - - if (storedOptOutString !== null) { - optedOut = storedOptOutString === "true"; - } else { - optedOut = Boolean(templateUsesClassicParameters); - } + // Since the dynamic-parameters experiment was removed, always use classic parameters + const optedOut = true; return { templateId, diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx index 8cdbafad435a3..ff20aea807bf4 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx @@ -21,7 +21,6 @@ import { SettingsIcon, TrashIcon, } from "lucide-react"; -import { useDashboard } from "modules/dashboard/useDashboard"; import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import { type FC, useEffect, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; @@ -43,14 +42,12 @@ export const WorkspaceMoreActions: FC = ({ disabled, }) => { const queryClient = useQueryClient(); - const { experiments } = useDashboard(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); const optOutQuery = useDynamicParametersOptOut({ templateId: workspace.template_id, templateUsesClassicParameters: workspace.template_use_classic_parameter_flow, - enabled: isDynamicParametersEnabled, + enabled: true, }); // Permissions @@ -154,7 +151,7 @@ export const WorkspaceMoreActions: FC = ({ onClose={() => setIsDownloadDialogOpen(false)} /> - {!isDynamicParametersEnabled || optOutQuery.data?.optedOut ? ( + {optOutQuery.data?.optedOut ? ( { @@ -164,13 +160,11 @@ const MissingBuildParametersDialog: FC = ({ error, ...dialogProps }) => { - const { experiments } = useDashboard(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); const optOutQuery = useDynamicParametersOptOut({ templateId: workspace.template_id, templateUsesClassicParameters: workspace.template_use_classic_parameter_flow, - enabled: isDynamicParametersEnabled, + enabled: true, }); const missedParameters = @@ -182,13 +176,11 @@ const MissingBuildParametersDialog: FC = ({ if (optOutQuery.isError) { return ; } - if (isDynamicParametersEnabled && !optOutQuery.data) { + if (!optOutQuery.data) { return ; } - // If dynamic parameters experiment is not enabled, or if opted out, use classic dialog - const shouldUseClassicDialog = - !isDynamicParametersEnabled || optOutQuery.data?.optedOut; + const shouldUseClassicDialog = optOutQuery.data?.optedOut; return shouldUseClassicDialog ? ( { - const { experiments } = useDashboard(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); - const { organization: organizationName = "default", template: templateName } = useParams() as { organization?: string; template: string }; - const templateQuery = useQuery({ - ...templateByName(organizationName, templateName), - enabled: isDynamicParametersEnabled, - }); + const templateQuery = useQuery( + templateByName(organizationName, templateName), + ); const optOutQuery = useDynamicParametersOptOut({ templateId: templateQuery.data?.id, @@ -31,40 +26,37 @@ const CreateWorkspaceExperimentRouter: FC = () => { enabled: !!templateQuery.data, }); - if (isDynamicParametersEnabled) { - if (templateQuery.isError) { - return ; - } - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data?.templateId ?? ""); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(templateQuery.data?.use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - return ( - - {optOutQuery.data.optedOut ? ( - - ) : ( - - )} - - ); + if (templateQuery.isError) { + return ; + } + if (optOutQuery.isError) { + return ; + } + if (!optOutQuery.data) { + return ; } - return ; + const toggleOptedOut = () => { + const key = optOutKey(optOutQuery.data?.templateId ?? ""); + const storedValue = localStorage.getItem(key); + + const current = storedValue + ? storedValue === "true" + : Boolean(templateQuery.data?.use_classic_parameter_flow); + + localStorage.setItem(key, (!current).toString()); + optOutQuery.refetch(); + }; + + return ( + + {optOutQuery.data.optedOut ? ( + + ) : ( + + )} + + ); }; export default CreateWorkspaceExperimentRouter; diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx index 8ba0e7b948b8c..8dbe4dcab0290 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsForm.tsx @@ -63,7 +63,6 @@ export interface TemplateSettingsForm { accessControlEnabled: boolean; advancedSchedulingEnabled: boolean; portSharingControlsEnabled: boolean; - isDynamicParametersEnabled: boolean; } export const TemplateSettingsForm: FC = ({ @@ -76,7 +75,6 @@ export const TemplateSettingsForm: FC = ({ accessControlEnabled, advancedSchedulingEnabled, portSharingControlsEnabled, - isDynamicParametersEnabled, }) => { const form = useFormik({ initialValues: { @@ -226,37 +224,35 @@ export const TemplateSettingsForm: FC = ({ } /> - {isDynamicParametersEnabled && ( - - } - label={ - - Use classic workspace creation form - - - Show the original workspace creation form and workspace - parameters settings form without dynamic parameters or - live updates. Recommended if your provisioners aren't - updated or the new form causes issues.{" "} - - Users can always manually switch experiences in the - workspace creation form. - - - - - } - /> - )} + + } + label={ + + Use classic workspace creation form + + + Show the original workspace creation form and workspace + parameters settings form without dynamic parameters or live + updates. Recommended if your provisioners aren't updated or + the new form causes issues.{" "} + + Users can always manually switch experiences in the + workspace creation form. + + + + + } + /> diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.test.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.test.tsx index 78114589691f8..1703ed5fea1d7 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.test.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.test.tsx @@ -54,7 +54,7 @@ const validFormValues: FormValues = { require_active_version: false, disable_everyone_group_access: false, max_port_share_level: "owner", - use_classic_parameter_flow: false, + use_classic_parameter_flow: true, }; const renderTemplateSettingsPage = async () => { diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx index e27f0b75c81e4..be5af252aec31 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx @@ -14,8 +14,6 @@ import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplateSettingsPageView } from "./TemplateSettingsPageView"; const TemplateSettingsPage: FC = () => { - const { experiments } = useDashboard(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); const { template: templateName } = useParams() as { template: string }; const navigate = useNavigate(); const getLink = useLinks(); @@ -81,7 +79,6 @@ const TemplateSettingsPage: FC = () => { accessControlEnabled={accessControlEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled} sharedPortControlsEnabled={sharedPortControlsEnabled} - isDynamicParametersEnabled={isDynamicParametersEnabled} /> ); diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx index 059999d27bb74..e267d25ce572e 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPageView.tsx @@ -15,7 +15,6 @@ interface TemplateSettingsPageViewProps { accessControlEnabled: boolean; advancedSchedulingEnabled: boolean; sharedPortControlsEnabled: boolean; - isDynamicParametersEnabled: boolean; } export const TemplateSettingsPageView: FC = ({ @@ -28,7 +27,6 @@ export const TemplateSettingsPageView: FC = ({ accessControlEnabled, advancedSchedulingEnabled, sharedPortControlsEnabled, - isDynamicParametersEnabled, }) => { return ( <> @@ -46,7 +44,6 @@ export const TemplateSettingsPageView: FC = ({ accessControlEnabled={accessControlEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled} portSharingControlsEnabled={sharedPortControlsEnabled} - isDynamicParametersEnabled={isDynamicParametersEnabled} /> ); diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx index 476a764ac9204..8e47b0105664d 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx @@ -1,6 +1,5 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { useDashboard } from "modules/dashboard/useDashboard"; import { optOutKey, useDynamicParametersOptOut, @@ -12,49 +11,43 @@ import WorkspaceParametersPage from "./WorkspaceParametersPage"; import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperimental"; const WorkspaceParametersExperimentRouter: FC = () => { - const { experiments } = useDashboard(); const workspace = useWorkspaceSettings(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); const optOutQuery = useDynamicParametersOptOut({ templateId: workspace.template_id, templateUsesClassicParameters: workspace.template_use_classic_parameter_flow, - enabled: isDynamicParametersEnabled, + enabled: true, }); - if (isDynamicParametersEnabled) { - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data.templateId); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(workspace.template_use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - - return ( - - {optOutQuery.data.optedOut ? ( - - ) : ( - - )} - - ); + if (optOutQuery.isError) { + return ; + } + if (!optOutQuery.data) { + return ; } - return ; + const toggleOptedOut = () => { + const key = optOutKey(optOutQuery.data.templateId); + const storedValue = localStorage.getItem(key); + + const current = storedValue + ? storedValue === "true" + : Boolean(workspace.template_use_classic_parameter_flow); + + localStorage.setItem(key, (!current).toString()); + optOutQuery.refetch(); + }; + + return ( + + {optOutQuery.data.optedOut ? ( + + ) : ( + + )} + + ); }; export default WorkspaceParametersExperimentRouter; diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index acdded15d4bc9..22ba0d15f1f9a 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -37,8 +37,6 @@ function useSafeSearchParams() { } const WorkspacesPage: FC = () => { - const { experiments } = useDashboard(); - const isDynamicParametersEnabled = experiments.includes("dynamic-parameters"); const queryClient = useQueryClient(); // If we use a useSearchParams for each hook, the values will not be in sync. // So we have to use a single one, centralizing the values, and pass it to @@ -166,7 +164,7 @@ const WorkspacesPage: FC = () => { onConfirm={async () => { await batchActions.updateAll({ workspaces: checkedWorkspaces, - isDynamicParametersEnabled, + isDynamicParametersEnabled: false, }); setConfirmingBatchAction(null); }} diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 72ad6fa508a02..0201e4b563efc 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -824,7 +824,7 @@ export const MockTemplate: TypesGen.Template = { deprecated: false, deprecation_message: "", max_port_share_level: "public", - use_classic_parameter_flow: false, + use_classic_parameter_flow: true, }; const MockTemplateVersionFiles: TemplateVersionFiles = { @@ -1410,7 +1410,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 4ff6c5ef42b60902eaa0222cee16006d335555e1 Mon Sep 17 00:00:00 2001 From: "blink-so[bot]" <211532188+blink-so[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 22:19:45 +0500 Subject: [PATCH 2/3] docs: update Kubernetes install docs with current release versions (#18347) Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: matifali <10648092+matifali@users.noreply.github.com> --- docs/install/kubernetes.md | 4 ++-- docs/install/releases/index.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/install/kubernetes.md b/docs/install/kubernetes.md index 92e97e3cf902c..1a920f96e1bca 100644 --- a/docs/install/kubernetes.md +++ b/docs/install/kubernetes.md @@ -133,7 +133,7 @@ We support two release channels: mainline and stable - read the helm install coder coder-v2/coder \ --namespace coder \ --values values.yaml \ - --version 2.22.1 + --version 2.23.1 ``` - **Stable** Coder release: @@ -144,7 +144,7 @@ We support two release channels: mainline and stable - read the helm install coder coder-v2/coder \ --namespace coder \ --values values.yaml \ - --version 2.19.0 + --version 2.22.1 ``` You can watch Coder start up by running `kubectl get pods -n coder`. Once Coder diff --git a/docs/install/releases/index.md b/docs/install/releases/index.md index 96c6c4f03120b..c23bbc25367ab 100644 --- a/docs/install/releases/index.md +++ b/docs/install/releases/index.md @@ -57,13 +57,13 @@ pages. | Release name | Release Date | Status | Latest Release | |------------------------------------------------|-------------------|------------------|----------------------------------------------------------------| -| [2.17](https://coder.com/changelog/coder-2-17) | November 04, 2024 | Not Supported | [v2.17.3](https://github.com/coder/coder/releases/tag/v2.17.3) | | [2.18](https://coder.com/changelog/coder-2-18) | December 03, 2024 | Not Supported | [v2.18.5](https://github.com/coder/coder/releases/tag/v2.18.5) | | [2.19](https://coder.com/changelog/coder-2-19) | February 04, 2025 | Not Supported | [v2.19.3](https://github.com/coder/coder/releases/tag/v2.19.3) | -| [2.20](https://coder.com/changelog/coder-2-20) | March 04, 2025 | Security Support | [v2.20.3](https://github.com/coder/coder/releases/tag/v2.20.3) | -| [2.21](https://coder.com/changelog/coder-2-21) | April 02, 2025 | Stable | [v2.21.3](https://github.com/coder/coder/releases/tag/v2.21.3) | -| [2.22](https://coder.com/changelog/coder-2-22) | May 16, 2025 | Mainline | [v2.22.0](https://github.com/coder/coder/releases/tag/v2.22.0) | -| 2.23 | | Not Released | N/A | +| [2.20](https://coder.com/changelog/coder-2-20) | March 04, 2025 | Not Supported | [v2.20.3](https://github.com/coder/coder/releases/tag/v2.20.3) | +| [2.21](https://coder.com/changelog/coder-2-21) | April 02, 2025 | Security Support | [v2.21.3](https://github.com/coder/coder/releases/tag/v2.21.3) | +| [2.22](https://coder.com/changelog/coder-2-22) | May 16, 2025 | Stable | [v2.22.1](https://github.com/coder/coder/releases/tag/v2.22.1) | +| [2.23](https://coder.com/changelog/coder-2-23) | June 03, 2025 | Mainline | [v2.23.1](https://github.com/coder/coder/releases/tag/v2.23.1) | +| 2.24 | | Not Released | N/A | > [!TIP] From 5944b1c595778ecbc830b197be126a17d353a29f Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 12 Jun 2025 18:37:07 +0100 Subject: [PATCH 3/3] chore: remove local storage based optin/optout (#18344) This removes the opt-in and opt-out buttons for dynamic parameters on the create workspace page and the workspace parameters settings page. --------- Co-authored-by: Steven Masley --- coderd/parameters_test.go | 1 + site/e2e/helpers.ts | 2 + .../useDynamicParametersOptOut.ts | 37 ------------------ .../WorkspaceMoreActions.tsx | 16 +++----- .../workspaces/WorkspaceUpdateDialogs.tsx | 31 ++------------- .../CreateWorkspaceExperimentRouter.tsx | 35 ++--------------- .../CreateWorkspacePageView.tsx | 28 ++----------- .../CreateWorkspacePageViewExperimental.tsx | 15 +------ .../ExperimentalFormContext.tsx | 5 --- .../WorkspacePage/WorkspacePage.test.tsx | 2 +- .../WorkspaceParametersExperimentRouter.tsx | 39 ++----------------- .../WorkspaceParametersPage.tsx | 14 +------ .../WorkspaceParametersPageExperimental.tsx | 17 +------- 13 files changed, 28 insertions(+), 214 deletions(-) delete mode 100644 site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts delete mode 100644 site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx diff --git a/coderd/parameters_test.go b/coderd/parameters_test.go index da2c19ba20e3c..640dc3ad22e55 100644 --- a/coderd/parameters_test.go +++ b/coderd/parameters_test.go @@ -249,6 +249,7 @@ func TestDynamicParametersWithTerraformValues(t *testing.T) { Value: "GO", }, } + request.EnableDynamicParameters = true }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, setup.client, wrk.LatestBuild.ID) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 52e9f5e820f23..0d6c10df500b0 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -1011,6 +1011,8 @@ export const updateWorkspace = async ( await page.getByTestId("workspace-update-button").click(); await page.getByTestId("confirm-button").click(); + await page.waitForSelector('[data-testid="dialog"]', { state: "visible" }); + await fillParameters(page, richParameters, buildParameters); await page.getByRole("button", { name: /update parameters/i }).click(); diff --git a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts b/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts deleted file mode 100644 index 22364edb0c70f..0000000000000 --- a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useQuery } from "react-query"; - -export const optOutKey = (id: string): string => `parameters.${id}.optOut`; - -interface UseDynamicParametersOptOutOptions { - templateId: string | undefined; - templateUsesClassicParameters: boolean | undefined; - enabled: boolean; -} - -export const useDynamicParametersOptOut = ({ - templateId, - templateUsesClassicParameters, - enabled, -}: UseDynamicParametersOptOutOptions) => { - return useQuery({ - enabled: !!templateId && enabled, - queryKey: ["dynamicParametersOptOut", templateId], - queryFn: () => { - if (!templateId) { - // This should not happen if enabled is working correctly, - // but as a type guard and sanity check. - throw new Error("templateId is required"); - } - const localStorageKey = optOutKey(templateId); - const storedOptOutString = localStorage.getItem(localStorageKey); - - // Since the dynamic-parameters experiment was removed, always use classic parameters - const optedOut = true; - - return { - templateId, - optedOut, - }; - }, - }); -}; diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx index ff20aea807bf4..d2d916f71e9e8 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx @@ -21,7 +21,6 @@ import { SettingsIcon, TrashIcon, } from "lucide-react"; -import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import { type FC, useEffect, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { Link as RouterLink } from "react-router-dom"; @@ -43,13 +42,6 @@ export const WorkspaceMoreActions: FC = ({ }) => { const queryClient = useQueryClient(); - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - // Permissions const { data: permissions } = useQuery(workspacePermissions(workspace)); @@ -59,7 +51,11 @@ export const WorkspaceMoreActions: FC = ({ // Change version const [changeVersionDialogOpen, setChangeVersionDialogOpen] = useState(false); const changeVersionMutation = useMutation( - changeVersion(workspace, queryClient, optOutQuery.data?.optedOut === false), + changeVersion( + workspace, + queryClient, + !workspace.template_use_classic_parameter_flow, + ), ); // Delete @@ -151,7 +147,7 @@ export const WorkspaceMoreActions: FC = ({ onClose={() => setIsDownloadDialogOpen(false)} /> - {optOutQuery.data?.optedOut ? ( + {workspace.template_use_classic_parameter_flow ? ( { updateWorkspaceMutation.mutate({ buildParameters, - isDynamicParametersEnabled: optOutQuery.data?.optedOut === false, + isDynamicParametersEnabled: + !workspace.template_use_classic_parameter_flow, }); setIsConfirmingUpdate(false); }; @@ -160,29 +151,13 @@ const MissingBuildParametersDialog: FC = ({ error, ...dialogProps }) => { - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - const missedParameters = error instanceof MissingBuildParameters ? error.parameters : []; const versionId = error instanceof MissingBuildParameters ? error.versionId : undefined; const isOpen = error instanceof MissingBuildParameters; - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const shouldUseClassicDialog = optOutQuery.data?.optedOut; - - return shouldUseClassicDialog ? ( + return workspace.template_use_classic_parameter_flow ? ( { const { organization: organizationName = "default", template: templateName } = @@ -19,43 +14,21 @@ const CreateWorkspaceExperimentRouter: FC = () => { templateByName(organizationName, templateName), ); - const optOutQuery = useDynamicParametersOptOut({ - templateId: templateQuery.data?.id, - templateUsesClassicParameters: - templateQuery.data?.use_classic_parameter_flow, - enabled: !!templateQuery.data, - }); - if (templateQuery.isError) { return ; } - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { + if (!templateQuery.data) { return ; } - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data?.templateId ?? ""); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(templateQuery.data?.use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - return ( - - {optOutQuery.data.optedOut ? ( + <> + {templateQuery.data?.use_classic_parameter_flow ? ( ) : ( )} - + ); }; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 64ea110709cf4..d365a565afcdb 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -28,14 +28,7 @@ import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; -import { - type FC, - useCallback, - useContext, - useEffect, - useMemo, - useState, -} from "react"; +import { type FC, useCallback, useEffect, useMemo, useState } from "react"; import { getFormHelpers, nameValidator, @@ -51,7 +44,6 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; @@ -106,7 +98,6 @@ export const CreateWorkspacePageView: FC = ({ onSubmit, onCancel, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); const [owner, setOwner] = useState(defaultOwner); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), @@ -220,20 +211,9 @@ export const CreateWorkspacePageView: FC = ({ - {experimentalFormContext && ( - - )} - - + } > diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index c2b6807a5833f..4fff4db92e21d 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -26,7 +26,7 @@ import { } from "components/Tooltip/Tooltip"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; -import { ArrowLeft, CircleHelp, Undo2 } from "lucide-react"; +import { ArrowLeft, CircleHelp } from "lucide-react"; import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters"; import { Diagnostics } from "modules/workspaces/DynamicParameter/DynamicParameter"; import { @@ -38,7 +38,6 @@ import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName" import { type FC, useCallback, - useContext, useEffect, useId, useRef, @@ -52,7 +51,6 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; @@ -112,7 +110,6 @@ export const CreateWorkspacePageViewExperimental: FC< owner, setOwner, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), ); @@ -372,16 +369,6 @@ export const CreateWorkspacePageViewExperimental: FC< )} - {experimentalFormContext && ( - - )}

New workspace

diff --git a/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx b/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx deleted file mode 100644 index f79665a0e4a01..0000000000000 --- a/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -export const ExperimentalFormContext = createContext< - { toggleOptedOut: () => void } | undefined ->(undefined); diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index fb95d0c883627..67a1a460dcd45 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -305,7 +305,7 @@ describe("WorkspacePage", () => { // Check if the update was called using the values from the form await waitFor(() => { - expect(API.updateWorkspace).toBeCalledWith( + expect(API.updateWorkspace).toHaveBeenCalledWith( MockOutdatedWorkspace, [ { diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx index 8e47b0105664d..0a01c9907bd00 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx @@ -1,11 +1,4 @@ -import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Loader } from "components/Loader/Loader"; -import { - optOutKey, - useDynamicParametersOptOut, -} from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import type { FC } from "react"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import WorkspaceParametersPage from "./WorkspaceParametersPage"; import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperimental"; @@ -13,40 +6,14 @@ import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperi const WorkspaceParametersExperimentRouter: FC = () => { const workspace = useWorkspaceSettings(); - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data.templateId); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(workspace.template_use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - return ( - - {optOutQuery.data.optedOut ? ( + <> + {workspace.template_use_classic_parameter_flow ? ( ) : ( )} - + ); }; diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx index 56720292957ff..50f2eedaeec26 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx @@ -4,11 +4,10 @@ import { isApiValidationError } from "api/errors"; import { checkAuthorization } from "api/queries/authCheck"; import type { Workspace, WorkspaceBuildParameter } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Button as ShadcnButton } from "components/Button/Button"; import { EmptyState } from "components/EmptyState/EmptyState"; import { Loader } from "components/Loader/Loader"; import { ExternalLinkIcon } from "lucide-react"; -import { type FC, useContext } from "react"; +import type { FC } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery } from "react-query"; import { useNavigate } from "react-router-dom"; @@ -18,7 +17,6 @@ import { type WorkspacePermissions, workspaceChecks, } from "../../../modules/workspaces/permissions"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import { WorkspaceParametersForm, @@ -113,21 +111,11 @@ export const WorkspaceParametersPageView: FC< isSubmitting, onCancel, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); return (

Workspace parameters

- {experimentalFormContext && ( - - Try out the new workspace parameters ✨ - - )}
diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx index 5fa3033542782..755291ec28629 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx @@ -7,7 +7,6 @@ import type { WorkspaceBuildParameter, } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Button } from "components/Button/Button"; import { EmptyState } from "components/EmptyState/EmptyState"; import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge"; import { Link } from "components/Link/Link"; @@ -19,9 +18,9 @@ import { TooltipTrigger, } from "components/Tooltip/Tooltip"; import { useEffectEvent } from "hooks/hookPolyfills"; -import { CircleHelp, Undo2 } from "lucide-react"; +import { CircleHelp } from "lucide-react"; import type { FC } from "react"; -import { useContext, useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery } from "react-query"; import { useNavigate, useSearchParams } from "react-router-dom"; @@ -32,14 +31,12 @@ import { type WorkspacePermissions, workspaceChecks, } from "../../../modules/workspaces/permissions"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import { WorkspaceParametersPageViewExperimental } from "./WorkspaceParametersPageViewExperimental"; const WorkspaceParametersPageExperimental: FC = () => { const workspace = useWorkspaceSettings(); const navigate = useNavigate(); - const experimentalFormContext = useContext(ExperimentalFormContext); const [searchParams] = useSearchParams(); const templateVersionId = searchParams.get("templateVersionId") ?? undefined; @@ -236,16 +233,6 @@ const WorkspaceParametersPageExperimental: FC = () => { - {experimentalFormContext && ( - - )}