Skip to content

feat: make dynamic parameters opt-in by default for new templates #19006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Jul 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
532218e
feat: make dynamic parameters opt-in by default for new templates
jaaydenh Jul 22, 2025
2ec5806
fix: format
jaaydenh Jul 22, 2025
b933efe
fix: fix stories
jaaydenh Jul 22, 2025
7144f4f
chore: update warning content
jaaydenh Jul 24, 2025
170c5c6
chore: cleanup
jaaydenh Jul 28, 2025
9bbd2b2
flip golden default value
Emyrk Jul 28, 2025
f25a9f8
chore: echo provisioner reponses to include terraform to match
Emyrk Jul 28, 2025
b10945c
fixup! chore: echo provisioner reponses to include terraform to match
Emyrk Jul 28, 2025
67dc627
fixup! fixup! chore: echo provisioner reponses to include terraform t…
Emyrk Jul 28, 2025
9eeb11b
fix: use classic parameter flow for MockWorkspace
jaaydenh Jul 28, 2025
7aa393c
sane defaultS
Emyrk Jul 28, 2025
238df67
sane defaultS
Emyrk Jul 28, 2025
ee116fb
fixup! sane defaultS
Emyrk Jul 28, 2025
d6a2262
fixup! fixup! sane defaultS
Emyrk Jul 28, 2025
cf8deb0
restart and ephemeral parameters resolved
Emyrk Jul 28, 2025
fc7b5d7
fixup! restart and ephemeral parameters resolved
Emyrk Jul 28, 2025
adce52e
add todo to fix this later
Emyrk Jul 28, 2025
a2358bf
fix: fix storybook tests
jaaydenh Jul 28, 2025
273411a
add todo to fix this later
Emyrk Jul 28, 2025
0501cff
add todo to fix this later
Emyrk Jul 28, 2025
b7064c0
default orphaned template versions to dynamic params
Emyrk Jul 28, 2025
fdbf0eb
add migration to make data schema consistent
Emyrk Jul 28, 2025
326d2bf
fixup! add migration to make data schema consistent
Emyrk Jul 28, 2025
83e643d
make fmt
Emyrk Jul 28, 2025
ccb76a4
fixup tag tests
Emyrk Jul 28, 2025
c4f4fe5
parameters require names
Emyrk Jul 28, 2025
95f53fd
fix(e2e): disable dynamic parameters for updateWorkspace tests
blink-so[bot] Jul 28, 2025
9ba0b67
fix: use classic parameters for workspace tests
jaaydenh Jul 28, 2025
5cd3e0b
fix: fix e2e tests
jaaydenh Jul 28, 2025
53b9ec6
fix: fix format
jaaydenh Jul 28, 2025
8fb0043
fix form type
Emyrk Jul 28, 2025
f88a934
fix test race
Emyrk Jul 29, 2025
1aad58e
test fixes
Emyrk Jul 29, 2025
5f1320c
formatting
Emyrk Jul 29, 2025
9c4aa40
remove unused file
Emyrk Jul 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cli/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ephemeral parameters do not carry across
// builds.
RichParameterValues: stopParamValues,
}
if bflags.provisionerLogDebug {
wbr.LogLevel = codersdk.ProvisionerLogLevelDebug
Expand Down
33 changes: 27 additions & 6 deletions cli/restart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -70,8 +71,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 prompt 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, "--prompt-ephemeral-parameters")
Expand Down Expand Up @@ -125,7 +132,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,
Expand Down Expand Up @@ -178,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")
Expand Down Expand Up @@ -233,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,
Expand Down
24 changes: 20 additions & 4 deletions cli/start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,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")
Expand Down Expand Up @@ -167,10 +175,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,
Expand Down
1 change: 1 addition & 0 deletions cli/templatepush_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ func TestTemplatePush(t *testing.T) {
default = "1"
}
data "coder_parameter" "b" {
name = "b"
type = string
default = "2"
}
Expand Down
2 changes: 1 addition & 1 deletion cli/testdata/coder_list_--output_json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -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]=====",
Expand Down
6 changes: 4 additions & 2 deletions cli/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
})
}

Expand Down Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion coderd/database/dbgen/dbgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
2 changes: 1 addition & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT true;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE templates ALTER COLUMN use_classic_parameter_flow SET DEFAULT false;
18 changes: 10 additions & 8 deletions coderd/insights_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, // Required for testing classic parameter flow behavior
GroupACL: database.TemplateACL{
firstUser.OrganizationID.String(): db2sdk.TemplateRoleActions(codersdk.TemplateRoleUse),
},
Expand Down Expand Up @@ -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),
},
Expand Down
37 changes: 34 additions & 3 deletions coderd/parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package coderd_test
import (
"context"
"os"
"sync"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/require"
"go.uber.org/atomic"
"golang.org/x/xerrors"

"github.com/coder/coder/v2/coderd"
Expand Down Expand Up @@ -199,8 +201,15 @@ func TestDynamicParametersWithTerraformValues(t *testing.T) {
modulesArchive, err := terraform.GetModulesArchive(os.DirFS("testdata/parameters/modules"))
require.NoError(t, err)

c := atomic.NewInt32(0)
reject := &dbRejectGitSSHKey{Store: db, hook: func(d *dbRejectGitSSHKey) {
if c.Add(1) > 1 {
// Second call forward, reject
d.SetReject(true)
}
}}
setup := setupDynamicParamsTest(t, setupDynamicParamsTestParams{
db: &dbRejectGitSSHKey{Store: db},
db: reject,
ps: ps,
provisionerDaemonVersion: provProto.CurrentVersion.String(),
mainTF: dynamicParametersTerraformSource,
Expand Down Expand Up @@ -444,8 +453,30 @@ func setupDynamicParamsTest(t *testing.T, args setupDynamicParamsTestParams) dyn
// that is generally impossible to force an error.
type dbRejectGitSSHKey struct {
database.Store
rejectMu sync.RWMutex
reject bool
hook func(d *dbRejectGitSSHKey)
}

// SetReject toggles whether GetGitSSHKey should return an error or passthrough to the underlying store.
func (d *dbRejectGitSSHKey) SetReject(reject bool) {
d.rejectMu.Lock()
defer d.rejectMu.Unlock()
d.reject = reject
}

func (*dbRejectGitSSHKey) GetGitSSHKey(_ context.Context, _ uuid.UUID) (database.GitSSHKey, error) {
return database.GitSSHKey{}, xerrors.New("forcing a fake error")
func (d *dbRejectGitSSHKey) GetGitSSHKey(ctx context.Context, userID uuid.UUID) (database.GitSSHKey, error) {
if d.hook != nil {
d.hook(d)
}

d.rejectMu.RLock()
reject := d.reject
d.rejectMu.RUnlock()

if reject {
return database.GitSSHKey{}, xerrors.New("forcing a fake error")
}

return d.Store.GetGitSSHKey(ctx, userID)
}
4 changes: 2 additions & 2 deletions coderd/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions coderd/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion coderd/templateversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading
Loading
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