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 <stevenmasley@gmail.com>
This commit is contained in:
Jaayden Halko
2025-06-12 12:15:05 -04:00
committed by GitHub
co-authored by blink-so[bot] jaaydenh Steven Masley
parent 70723d3b51
commit f126931219
30 changed files with 144 additions and 198 deletions
+1 -1
View File
@@ -15,7 +15,7 @@
"template_allow_user_cancel_workspace_jobs": false, "template_allow_user_cancel_workspace_jobs": false,
"template_active_version_id": "============[version ID]============", "template_active_version_id": "============[version ID]============",
"template_require_active_version": false, "template_require_active_version": false,
"template_use_classic_parameter_flow": false, "template_use_classic_parameter_flow": true,
"latest_build": { "latest_build": {
"id": "========[workspace build ID]========", "id": "========[workspace build ID]========",
"created_at": "====[timestamp]=====", "created_at": "====[timestamp]=====",
-3
View File
@@ -12745,7 +12745,6 @@ const docTemplate = `{
"notifications", "notifications",
"workspace-usage", "workspace-usage",
"web-push", "web-push",
"dynamic-parameters",
"workspace-prebuilds", "workspace-prebuilds",
"agentic-chat", "agentic-chat",
"ai-tasks" "ai-tasks"
@@ -12754,7 +12753,6 @@ const docTemplate = `{
"ExperimentAITasks": "Enables the new AI tasks feature.", "ExperimentAITasks": "Enables the new AI tasks feature.",
"ExperimentAgenticChat": "Enables the new agentic AI chat feature.", "ExperimentAgenticChat": "Enables the new agentic AI chat feature.",
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the 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.", "ExperimentExample": "This isn't used for anything.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentWebPush": "Enables web push notifications through the browser.", "ExperimentWebPush": "Enables web push notifications through the browser.",
@@ -12767,7 +12765,6 @@ const docTemplate = `{
"ExperimentNotifications", "ExperimentNotifications",
"ExperimentWorkspaceUsage", "ExperimentWorkspaceUsage",
"ExperimentWebPush", "ExperimentWebPush",
"ExperimentDynamicParameters",
"ExperimentWorkspacePrebuilds", "ExperimentWorkspacePrebuilds",
"ExperimentAgenticChat", "ExperimentAgenticChat",
"ExperimentAITasks" "ExperimentAITasks"
-3
View File
@@ -11438,7 +11438,6 @@
"notifications", "notifications",
"workspace-usage", "workspace-usage",
"web-push", "web-push",
"dynamic-parameters",
"workspace-prebuilds", "workspace-prebuilds",
"agentic-chat", "agentic-chat",
"ai-tasks" "ai-tasks"
@@ -11447,7 +11446,6 @@
"ExperimentAITasks": "Enables the new AI tasks feature.", "ExperimentAITasks": "Enables the new AI tasks feature.",
"ExperimentAgenticChat": "Enables the new agentic AI chat feature.", "ExperimentAgenticChat": "Enables the new agentic AI chat feature.",
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the 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.", "ExperimentExample": "This isn't used for anything.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.", "ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentWebPush": "Enables web push notifications through the browser.", "ExperimentWebPush": "Enables web push notifications through the browser.",
@@ -11460,7 +11458,6 @@
"ExperimentNotifications", "ExperimentNotifications",
"ExperimentWorkspaceUsage", "ExperimentWorkspaceUsage",
"ExperimentWebPush", "ExperimentWebPush",
"ExperimentDynamicParameters",
"ExperimentWorkspacePrebuilds", "ExperimentWorkspacePrebuilds",
"ExperimentAgenticChat", "ExperimentAgenticChat",
"ExperimentAITasks" "ExperimentAITasks"
-3
View File
@@ -1153,9 +1153,6 @@ func New(options *Options) *API {
}) })
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
r.Use(
httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentDynamicParameters),
)
r.Route("/dynamic-parameters", func(r chi.Router) { r.Route("/dynamic-parameters", func(r chi.Router) {
r.Post("/evaluate", api.templateVersionDynamicParametersEvaluate) r.Post("/evaluate", api.templateVersionDynamicParametersEvaluate)
r.Get("/", api.templateVersionDynamicParametersWebsocket) r.Get("/", api.templateVersionDynamicParametersWebsocket)
+1
View File
@@ -9345,6 +9345,7 @@ func (q *FakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl
AllowUserAutostart: true, AllowUserAutostart: true,
AllowUserAutostop: true, AllowUserAutostop: true,
MaxPortSharingLevel: arg.MaxPortSharingLevel, MaxPortSharingLevel: arg.MaxPortSharingLevel,
UseClassicParameterFlow: true,
} }
q.templates = append(q.templates, template) q.templates = append(q.templates, template)
return nil return nil
+1 -1
View File
@@ -1626,7 +1626,7 @@ CREATE TABLE templates (
deprecated text DEFAULT ''::text NOT NULL, deprecated text DEFAULT ''::text NOT NULL,
activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL, activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL,
max_port_sharing_level app_sharing_level DEFAULT 'owner'::app_sharing_level 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.'; COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.';
@@ -0,0 +1,3 @@
ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false;
UPDATE templates SET use_classic_parameter_flow = false
@@ -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
+7 -6
View File
@@ -29,9 +29,7 @@ import (
func TestDynamicParametersOwnerSSHPublicKey(t *testing.T) { func TestDynamicParametersOwnerSSHPublicKey(t *testing.T) {
t.Parallel() t.Parallel()
cfg := coderdtest.DeploymentValues(t) ownerClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
cfg.Experiments = []string{string(codersdk.ExperimentDynamicParameters)}
ownerClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true, DeploymentValues: cfg})
owner := coderdtest.CreateFirstUser(t, ownerClient) owner := coderdtest.CreateFirstUser(t, ownerClient)
templateAdmin, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin()) templateAdmin, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin())
@@ -354,14 +352,11 @@ type dynamicParamsTest struct {
} }
func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dynamicParamsTest { 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{ ownerClient, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
Database: args.db, Database: args.db,
Pubsub: args.ps, Pubsub: args.ps,
IncludeProvisionerDaemon: true, IncludeProvisionerDaemon: true,
ProvisionerDaemonVersion: args.provisionerDaemonVersion, ProvisionerDaemonVersion: args.provisionerDaemonVersion,
DeploymentValues: cfg,
}) })
owner := coderdtest.CreateFirstUser(t, ownerClient) owner := coderdtest.CreateFirstUser(t, ownerClient)
@@ -384,6 +379,12 @@ func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dyn
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, version.ID) coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, version.ID)
tpl := coderdtest.CreateTemplate(t, templateAdmin, owner.OrganizationID, 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) ctx := testutil.Context(t, testutil.WaitShort)
stream, err := templateAdmin.TemplateVersionDynamicParameters(ctx, version.ID) stream, err := templateAdmin.TemplateVersionDynamicParameters(ctx, version.ID)
if args.expectWebsocketError { if args.expectWebsocketError {
+1 -1
View File
@@ -1548,7 +1548,7 @@ func TestPatchTemplateMeta(t *testing.T) {
user := coderdtest.CreateFirstUser(t, client) user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) 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 bTrue := true
bFalse := false bFalse := false
+2 -14
View File
@@ -384,20 +384,8 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
builder = builder.State(createBuild.ProvisionerState) builder = builder.State(createBuild.ProvisionerState)
} }
// Only defer to dynamic parameters if the experiment is enabled. if createBuild.EnableDynamicParameters != nil {
if api.Experiments.Enabled(codersdk.ExperimentDynamicParameters) { builder = builder.DynamicParameters(*createBuild.EnableDynamicParameters)
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)),
)
}
} }
workspaceBuild, provisionerJob, provisionerDaemons, err = builder.Build( workspaceBuild, provisionerJob, provisionerDaemons, err = builder.Build(
+1 -1
View File
@@ -717,7 +717,7 @@ func createWorkspace(
builder = builder.MarkPrebuiltWorkspaceClaim() builder = builder.MarkPrebuiltWorkspaceClaim()
} }
if req.EnableDynamicParameters && api.Experiments.Enabled(codersdk.ExperimentDynamicParameters) { if req.EnableDynamicParameters {
builder = builder.DynamicParameters(req.EnableDynamicParameters) builder = builder.DynamicParameters(req.EnableDynamicParameters)
} }
+10 -11
View File
@@ -1042,8 +1042,15 @@ func (b *Builder) checkRunningBuild() error {
} }
func (b *Builder) usingDynamicParameters() bool { func (b *Builder) usingDynamicParameters() bool {
if !b.experiments.Enabled(codersdk.ExperimentDynamicParameters) { if b.dynamicParametersEnabled != nil {
// Experiment required 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 return false
} }
@@ -1056,15 +1063,7 @@ func (b *Builder) usingDynamicParameters() bool {
return false return false
} }
if b.dynamicParametersEnabled != nil { return true
return *b.dynamicParametersEnabled
}
tpl, err := b.getTemplate()
if err != nil {
return false // Let another part of the code get this error
}
return !tpl.UseClassicParameterFlow
} }
func ProvisionerVersionSupportsDynamicParameters(version string) bool { func ProvisionerVersionSupportsDynamicParameters(version string) bool {
+5 -4
View File
@@ -894,10 +894,11 @@ func withTemplate(mTx *dbmock.MockStore) {
mTx.EXPECT().GetTemplateByID(gomock.Any(), templateID). mTx.EXPECT().GetTemplateByID(gomock.Any(), templateID).
Times(1). Times(1).
Return(database.Template{ Return(database.Template{
ID: templateID, ID: templateID,
OrganizationID: orgID, OrganizationID: orgID,
Provisioner: database.ProvisionerTypeTerraform, Provisioner: database.ProvisionerTypeTerraform,
ActiveVersionID: activeVersionID, ActiveVersionID: activeVersionID,
UseClassicParameterFlow: true,
}, nil) }, nil)
} }
-1
View File
@@ -3356,7 +3356,6 @@ const (
ExperimentNotifications Experiment = "notifications" // Sends notifications via SMTP and webhooks following certain events. ExperimentNotifications Experiment = "notifications" // Sends notifications via SMTP and webhooks following certain events.
ExperimentWorkspaceUsage Experiment = "workspace-usage" // Enables the new workspace usage tracking. ExperimentWorkspaceUsage Experiment = "workspace-usage" // Enables the new workspace usage tracking.
ExperimentWebPush Experiment = "web-push" // Enables web push notifications through the browser. 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. ExperimentWorkspacePrebuilds Experiment = "workspace-prebuilds" // Enables the new workspace prebuilds feature.
ExperimentAgenticChat Experiment = "agentic-chat" // Enables the new agentic AI chat feature. ExperimentAgenticChat Experiment = "agentic-chat" // Enables the new agentic AI chat feature.
ExperimentAITasks Experiment = "ai-tasks" // Enables the new AI tasks feature. ExperimentAITasks Experiment = "ai-tasks" // Enables the new AI tasks feature.
-1
View File
@@ -3512,7 +3512,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
| `notifications` | | `notifications` |
| `workspace-usage` | | `workspace-usage` |
| `web-push` | | `web-push` |
| `dynamic-parameters` |
| `workspace-prebuilds` | | `workspace-prebuilds` |
| `agentic-chat` | | `agentic-chat` |
| `ai-tasks` | | `ai-tasks` |
+1 -3
View File
@@ -21,8 +21,6 @@ import (
func TestDynamicParametersOwnerGroups(t *testing.T) { func TestDynamicParametersOwnerGroups(t *testing.T) {
t.Parallel() t.Parallel()
cfg := coderdtest.DeploymentValues(t)
cfg.Experiments = []string{string(codersdk.ExperimentDynamicParameters)}
ownerClient, owner := coderdenttest.New(t, ownerClient, owner := coderdenttest.New(t,
&coderdenttest.Options{ &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{ LicenseOptions: &coderdenttest.LicenseOptions{
@@ -30,7 +28,7 @@ func TestDynamicParametersOwnerGroups(t *testing.T) {
codersdk.FeatureTemplateRBAC: 1, 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()) templateAdmin, templateAdminUser := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin())
+7 -1
View File
@@ -1698,7 +1698,7 @@ func TestWorkspaceTemplateParamsChange(t *testing.T) {
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}) logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false})
dv := coderdtest.DeploymentValues(t) dv := coderdtest.DeploymentValues(t)
dv.Experiments = []string{string(codersdk.ExperimentDynamicParameters)}
client, owner := coderdenttest.New(t, &coderdenttest.Options{ client, owner := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{ Options: &coderdtest.Options{
Logger: &logger, Logger: &logger,
@@ -1736,6 +1736,12 @@ func TestWorkspaceTemplateParamsChange(t *testing.T) {
require.NoError(t, err, "failed to create template version") require.NoError(t, err, "failed to create template version")
coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, tv.ID) coderdtest.AwaitTemplateVersionJobCompleted(t, templateAdmin, tv.ID)
tpl := coderdtest.CreateTemplate(t, templateAdmin, owner.OrganizationID, 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") require.False(t, tpl.UseClassicParameterFlow, "template to use dynamic parameters")
// When: we create a workspace build using the above template but with // When: we create a workspace build using the above template but with
-1
View File
@@ -830,7 +830,6 @@ export type Experiment =
| "ai-tasks" | "ai-tasks"
| "agentic-chat" | "agentic-chat"
| "auto-fill-parameters" | "auto-fill-parameters"
| "dynamic-parameters"
| "example" | "example"
| "notifications" | "notifications"
| "web-push" | "web-push"
@@ -25,13 +25,8 @@ export const useDynamicParametersOptOut = ({
const localStorageKey = optOutKey(templateId); const localStorageKey = optOutKey(templateId);
const storedOptOutString = localStorage.getItem(localStorageKey); const storedOptOutString = localStorage.getItem(localStorageKey);
let optedOut: boolean; // Since the dynamic-parameters experiment was removed, always use classic parameters
const optedOut = true;
if (storedOptOutString !== null) {
optedOut = storedOptOutString === "true";
} else {
optedOut = Boolean(templateUsesClassicParameters);
}
return { return {
templateId, templateId,
@@ -21,7 +21,6 @@ import {
SettingsIcon, SettingsIcon,
TrashIcon, TrashIcon,
} from "lucide-react"; } from "lucide-react";
import { useDashboard } from "modules/dashboard/useDashboard";
import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut";
import { type FC, useEffect, useState } from "react"; import { type FC, useEffect, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "react-query"; import { useMutation, useQuery, useQueryClient } from "react-query";
@@ -43,14 +42,12 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
disabled, disabled,
}) => { }) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const optOutQuery = useDynamicParametersOptOut({ const optOutQuery = useDynamicParametersOptOut({
templateId: workspace.template_id, templateId: workspace.template_id,
templateUsesClassicParameters: templateUsesClassicParameters:
workspace.template_use_classic_parameter_flow, workspace.template_use_classic_parameter_flow,
enabled: isDynamicParametersEnabled, enabled: true,
}); });
// Permissions // Permissions
@@ -154,7 +151,7 @@ export const WorkspaceMoreActions: FC<WorkspaceMoreActionsProps> = ({
onClose={() => setIsDownloadDialogOpen(false)} onClose={() => setIsDownloadDialogOpen(false)}
/> />
{!isDynamicParametersEnabled || optOutQuery.data?.optedOut ? ( {optOutQuery.data?.optedOut ? (
<UpdateBuildParametersDialog <UpdateBuildParametersDialog
missedParameters={ missedParameters={
changeVersionMutation.error instanceof MissingBuildParameters changeVersionMutation.error instanceof MissingBuildParameters
@@ -10,7 +10,6 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Loader } from "components/Loader/Loader"; import { Loader } from "components/Loader/Loader";
import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; import { MemoizedInlineMarkdown } from "components/Markdown/Markdown";
import { useDashboard } from "modules/dashboard/useDashboard";
import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut";
import { UpdateBuildParametersDialog } from "modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialog"; import { UpdateBuildParametersDialog } from "modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialog";
import { UpdateBuildParametersDialogExperimental } from "modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental"; import { UpdateBuildParametersDialogExperimental } from "modules/workspaces/WorkspaceMoreActions/UpdateBuildParametersDialogExperimental";
@@ -56,14 +55,11 @@ export const useWorkspaceUpdate = ({
setIsConfirmingUpdate(true); setIsConfirmingUpdate(true);
}; };
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const optOutQuery = useDynamicParametersOptOut({ const optOutQuery = useDynamicParametersOptOut({
templateId: workspace.template_id, templateId: workspace.template_id,
templateUsesClassicParameters: templateUsesClassicParameters:
workspace.template_use_classic_parameter_flow, workspace.template_use_classic_parameter_flow,
enabled: isDynamicParametersEnabled, enabled: true,
}); });
const confirmUpdate = (buildParameters: WorkspaceBuildParameter[] = []) => { const confirmUpdate = (buildParameters: WorkspaceBuildParameter[] = []) => {
@@ -164,13 +160,11 @@ const MissingBuildParametersDialog: FC<MissingBuildParametersDialogProps> = ({
error, error,
...dialogProps ...dialogProps
}) => { }) => {
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const optOutQuery = useDynamicParametersOptOut({ const optOutQuery = useDynamicParametersOptOut({
templateId: workspace.template_id, templateId: workspace.template_id,
templateUsesClassicParameters: templateUsesClassicParameters:
workspace.template_use_classic_parameter_flow, workspace.template_use_classic_parameter_flow,
enabled: isDynamicParametersEnabled, enabled: true,
}); });
const missedParameters = const missedParameters =
@@ -182,13 +176,11 @@ const MissingBuildParametersDialog: FC<MissingBuildParametersDialogProps> = ({
if (optOutQuery.isError) { if (optOutQuery.isError) {
return <ErrorAlert error={optOutQuery.error} />; return <ErrorAlert error={optOutQuery.error} />;
} }
if (isDynamicParametersEnabled && !optOutQuery.data) { if (!optOutQuery.data) {
return <Loader />; return <Loader />;
} }
// If dynamic parameters experiment is not enabled, or if opted out, use classic dialog const shouldUseClassicDialog = optOutQuery.data?.optedOut;
const shouldUseClassicDialog =
!isDynamicParametersEnabled || optOutQuery.data?.optedOut;
return shouldUseClassicDialog ? ( return shouldUseClassicDialog ? (
<UpdateBuildParametersDialog <UpdateBuildParametersDialog
@@ -1,7 +1,6 @@
import { templateByName } from "api/queries/templates"; import { templateByName } from "api/queries/templates";
import { ErrorAlert } from "components/Alert/ErrorAlert"; import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Loader } from "components/Loader/Loader"; import { Loader } from "components/Loader/Loader";
import { useDashboard } from "modules/dashboard/useDashboard";
import { import {
optOutKey, optOutKey,
useDynamicParametersOptOut, useDynamicParametersOptOut,
@@ -14,15 +13,11 @@ import CreateWorkspacePageExperimental from "./CreateWorkspacePageExperimental";
import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExperimentalFormContext } from "./ExperimentalFormContext";
const CreateWorkspaceExperimentRouter: FC = () => { const CreateWorkspaceExperimentRouter: FC = () => {
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const { organization: organizationName = "default", template: templateName } = const { organization: organizationName = "default", template: templateName } =
useParams() as { organization?: string; template: string }; useParams() as { organization?: string; template: string };
const templateQuery = useQuery({ const templateQuery = useQuery(
...templateByName(organizationName, templateName), templateByName(organizationName, templateName),
enabled: isDynamicParametersEnabled, );
});
const optOutQuery = useDynamicParametersOptOut({ const optOutQuery = useDynamicParametersOptOut({
templateId: templateQuery.data?.id, templateId: templateQuery.data?.id,
@@ -31,40 +26,37 @@ const CreateWorkspaceExperimentRouter: FC = () => {
enabled: !!templateQuery.data, enabled: !!templateQuery.data,
}); });
if (isDynamicParametersEnabled) { if (templateQuery.isError) {
if (templateQuery.isError) { return <ErrorAlert error={templateQuery.error} />;
return <ErrorAlert error={templateQuery.error} />; }
} if (optOutQuery.isError) {
if (optOutQuery.isError) { return <ErrorAlert error={optOutQuery.error} />;
return <ErrorAlert error={optOutQuery.error} />; }
} if (!optOutQuery.data) {
if (!optOutQuery.data) { return <Loader />;
return <Loader />;
}
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 (
<ExperimentalFormContext.Provider value={{ toggleOptedOut }}>
{optOutQuery.data.optedOut ? (
<CreateWorkspacePage />
) : (
<CreateWorkspacePageExperimental />
)}
</ExperimentalFormContext.Provider>
);
} }
return <CreateWorkspacePage />; 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 (
<ExperimentalFormContext.Provider value={{ toggleOptedOut }}>
{optOutQuery.data.optedOut ? (
<CreateWorkspacePage />
) : (
<CreateWorkspacePageExperimental />
)}
</ExperimentalFormContext.Provider>
);
}; };
export default CreateWorkspaceExperimentRouter; export default CreateWorkspaceExperimentRouter;
@@ -63,7 +63,6 @@ export interface TemplateSettingsForm {
accessControlEnabled: boolean; accessControlEnabled: boolean;
advancedSchedulingEnabled: boolean; advancedSchedulingEnabled: boolean;
portSharingControlsEnabled: boolean; portSharingControlsEnabled: boolean;
isDynamicParametersEnabled: boolean;
} }
export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
@@ -76,7 +75,6 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
accessControlEnabled, accessControlEnabled,
advancedSchedulingEnabled, advancedSchedulingEnabled,
portSharingControlsEnabled, portSharingControlsEnabled,
isDynamicParametersEnabled,
}) => { }) => {
const form = useFormik<UpdateTemplateMeta>({ const form = useFormik<UpdateTemplateMeta>({
initialValues: { initialValues: {
@@ -226,37 +224,35 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
</StackLabel> </StackLabel>
} }
/> />
{isDynamicParametersEnabled && ( <FormControlLabel
<FormControlLabel control={
control={ <Checkbox
<Checkbox size="small"
size="small" id="use_classic_parameter_flow"
id="use_classic_parameter_flow" name="use_classic_parameter_flow"
name="use_classic_parameter_flow" checked={form.values.use_classic_parameter_flow}
checked={form.values.use_classic_parameter_flow} onChange={form.handleChange}
onChange={form.handleChange} disabled={false}
disabled={false} />
/> }
} label={
label={ <StackLabel>
<StackLabel> Use classic workspace creation form
Use classic workspace creation form <StackLabelHelperText>
<StackLabelHelperText> <span>
<span> Show the original workspace creation form and workspace
Show the original workspace creation form and workspace parameters settings form without dynamic parameters or live
parameters settings form without dynamic parameters or updates. Recommended if your provisioners aren't updated or
live updates. Recommended if your provisioners aren't the new form causes issues.{" "}
updated or the new form causes issues.{" "} <strong>
<strong> Users can always manually switch experiences in the
Users can always manually switch experiences in the workspace creation form.
workspace creation form. </strong>
</strong> </span>
</span> </StackLabelHelperText>
</StackLabelHelperText> </StackLabel>
</StackLabel> }
} />
/>
)}
</FormFields> </FormFields>
</FormSection> </FormSection>
@@ -54,7 +54,7 @@ const validFormValues: FormValues = {
require_active_version: false, require_active_version: false,
disable_everyone_group_access: false, disable_everyone_group_access: false,
max_port_share_level: "owner", max_port_share_level: "owner",
use_classic_parameter_flow: false, use_classic_parameter_flow: true,
}; };
const renderTemplateSettingsPage = async () => { const renderTemplateSettingsPage = async () => {
@@ -14,8 +14,6 @@ import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateSettingsPageView } from "./TemplateSettingsPageView"; import { TemplateSettingsPageView } from "./TemplateSettingsPageView";
const TemplateSettingsPage: FC = () => { const TemplateSettingsPage: FC = () => {
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const { template: templateName } = useParams() as { template: string }; const { template: templateName } = useParams() as { template: string };
const navigate = useNavigate(); const navigate = useNavigate();
const getLink = useLinks(); const getLink = useLinks();
@@ -81,7 +79,6 @@ const TemplateSettingsPage: FC = () => {
accessControlEnabled={accessControlEnabled} accessControlEnabled={accessControlEnabled}
advancedSchedulingEnabled={advancedSchedulingEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled}
sharedPortControlsEnabled={sharedPortControlsEnabled} sharedPortControlsEnabled={sharedPortControlsEnabled}
isDynamicParametersEnabled={isDynamicParametersEnabled}
/> />
</> </>
); );
@@ -15,7 +15,6 @@ interface TemplateSettingsPageViewProps {
accessControlEnabled: boolean; accessControlEnabled: boolean;
advancedSchedulingEnabled: boolean; advancedSchedulingEnabled: boolean;
sharedPortControlsEnabled: boolean; sharedPortControlsEnabled: boolean;
isDynamicParametersEnabled: boolean;
} }
export const TemplateSettingsPageView: FC<TemplateSettingsPageViewProps> = ({ export const TemplateSettingsPageView: FC<TemplateSettingsPageViewProps> = ({
@@ -28,7 +27,6 @@ export const TemplateSettingsPageView: FC<TemplateSettingsPageViewProps> = ({
accessControlEnabled, accessControlEnabled,
advancedSchedulingEnabled, advancedSchedulingEnabled,
sharedPortControlsEnabled, sharedPortControlsEnabled,
isDynamicParametersEnabled,
}) => { }) => {
return ( return (
<> <>
@@ -46,7 +44,6 @@ export const TemplateSettingsPageView: FC<TemplateSettingsPageViewProps> = ({
accessControlEnabled={accessControlEnabled} accessControlEnabled={accessControlEnabled}
advancedSchedulingEnabled={advancedSchedulingEnabled} advancedSchedulingEnabled={advancedSchedulingEnabled}
portSharingControlsEnabled={sharedPortControlsEnabled} portSharingControlsEnabled={sharedPortControlsEnabled}
isDynamicParametersEnabled={isDynamicParametersEnabled}
/> />
</> </>
); );
@@ -1,6 +1,5 @@
import { ErrorAlert } from "components/Alert/ErrorAlert"; import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Loader } from "components/Loader/Loader"; import { Loader } from "components/Loader/Loader";
import { useDashboard } from "modules/dashboard/useDashboard";
import { import {
optOutKey, optOutKey,
useDynamicParametersOptOut, useDynamicParametersOptOut,
@@ -12,49 +11,43 @@ import WorkspaceParametersPage from "./WorkspaceParametersPage";
import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperimental"; import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperimental";
const WorkspaceParametersExperimentRouter: FC = () => { const WorkspaceParametersExperimentRouter: FC = () => {
const { experiments } = useDashboard();
const workspace = useWorkspaceSettings(); const workspace = useWorkspaceSettings();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const optOutQuery = useDynamicParametersOptOut({ const optOutQuery = useDynamicParametersOptOut({
templateId: workspace.template_id, templateId: workspace.template_id,
templateUsesClassicParameters: templateUsesClassicParameters:
workspace.template_use_classic_parameter_flow, workspace.template_use_classic_parameter_flow,
enabled: isDynamicParametersEnabled, enabled: true,
}); });
if (isDynamicParametersEnabled) { if (optOutQuery.isError) {
if (optOutQuery.isError) { return <ErrorAlert error={optOutQuery.error} />;
return <ErrorAlert error={optOutQuery.error} />; }
} if (!optOutQuery.data) {
if (!optOutQuery.data) { return <Loader />;
return <Loader />;
}
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 (
<ExperimentalFormContext.Provider value={{ toggleOptedOut }}>
{optOutQuery.data.optedOut ? (
<WorkspaceParametersPage />
) : (
<WorkspaceParametersPageExperimental />
)}
</ExperimentalFormContext.Provider>
);
} }
return <WorkspaceParametersPage />; 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 (
<ExperimentalFormContext.Provider value={{ toggleOptedOut }}>
{optOutQuery.data.optedOut ? (
<WorkspaceParametersPage />
) : (
<WorkspaceParametersPageExperimental />
)}
</ExperimentalFormContext.Provider>
);
}; };
export default WorkspaceParametersExperimentRouter; export default WorkspaceParametersExperimentRouter;
@@ -37,8 +37,6 @@ function useSafeSearchParams() {
} }
const WorkspacesPage: FC = () => { const WorkspacesPage: FC = () => {
const { experiments } = useDashboard();
const isDynamicParametersEnabled = experiments.includes("dynamic-parameters");
const queryClient = useQueryClient(); const queryClient = useQueryClient();
// If we use a useSearchParams for each hook, the values will not be in sync. // 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 // So we have to use a single one, centralizing the values, and pass it to
@@ -166,7 +164,7 @@ const WorkspacesPage: FC = () => {
onConfirm={async () => { onConfirm={async () => {
await batchActions.updateAll({ await batchActions.updateAll({
workspaces: checkedWorkspaces, workspaces: checkedWorkspaces,
isDynamicParametersEnabled, isDynamicParametersEnabled: false,
}); });
setConfirmingBatchAction(null); setConfirmingBatchAction(null);
}} }}
+2 -2
View File
@@ -824,7 +824,7 @@ export const MockTemplate: TypesGen.Template = {
deprecated: false, deprecated: false,
deprecation_message: "", deprecation_message: "",
max_port_share_level: "public", max_port_share_level: "public",
use_classic_parameter_flow: false, use_classic_parameter_flow: true,
}; };
const MockTemplateVersionFiles: TemplateVersionFiles = { const MockTemplateVersionFiles: TemplateVersionFiles = {
@@ -1410,7 +1410,7 @@ export const MockWorkspace: TypesGen.Workspace = {
MockTemplate.allow_user_cancel_workspace_jobs, MockTemplate.allow_user_cancel_workspace_jobs,
template_active_version_id: MockTemplate.active_version_id, template_active_version_id: MockTemplate.active_version_id,
template_require_active_version: MockTemplate.require_active_version, template_require_active_version: MockTemplate.require_active_version,
template_use_classic_parameter_flow: false, template_use_classic_parameter_flow: true,
outdated: false, outdated: false,
owner_id: MockUserOwner.id, owner_id: MockUserOwner.id,
organization_id: MockOrganization.id, organization_id: MockOrganization.id,