diff --git a/cli/server.go b/cli/server.go
index b12f5e0189..010e96d2fc 100644
--- a/cli/server.go
+++ b/cli/server.go
@@ -1476,6 +1476,7 @@ func newProvisionerDaemon(
Listener: terraformServer,
Logger: provisionerLogger,
WorkDirectory: workDir,
+ Experiments: coderAPI.Experiments,
},
CachePath: tfDir,
Tracer: tracer,
diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index a67b2cb7c7..67dc827927 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -14322,7 +14322,8 @@ const docTemplate = `{
"web-push",
"oauth2",
"mcp-server-http",
- "workspace-sharing"
+ "workspace-sharing",
+ "terraform-directory-reuse"
],
"x-enum-comments": {
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
@@ -14330,6 +14331,7 @@ const docTemplate = `{
"ExperimentMCPServerHTTP": "Enables the MCP HTTP server functionality.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentOAuth2": "Enables OAuth2 provider functionality.",
+ "ExperimentTerraformWorkspace": "Enables reuse of existing terraform directory for builds",
"ExperimentWebPush": "Enables web push notifications through the browser.",
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
@@ -14342,7 +14344,8 @@ const docTemplate = `{
"ExperimentWebPush",
"ExperimentOAuth2",
"ExperimentMCPServerHTTP",
- "ExperimentWorkspaceSharing"
+ "ExperimentWorkspaceSharing",
+ "ExperimentTerraformWorkspace"
]
},
"codersdk.ExternalAPIKeyScopes": {
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index 4e1bd64ebe..1577e55b86 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -12929,7 +12929,8 @@
"web-push",
"oauth2",
"mcp-server-http",
- "workspace-sharing"
+ "workspace-sharing",
+ "terraform-directory-reuse"
],
"x-enum-comments": {
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
@@ -12937,6 +12938,7 @@
"ExperimentMCPServerHTTP": "Enables the MCP HTTP server functionality.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentOAuth2": "Enables OAuth2 provider functionality.",
+ "ExperimentTerraformWorkspace": "Enables reuse of existing terraform directory for builds",
"ExperimentWebPush": "Enables web push notifications through the browser.",
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
@@ -12949,7 +12951,8 @@
"ExperimentWebPush",
"ExperimentOAuth2",
"ExperimentMCPServerHTTP",
- "ExperimentWorkspaceSharing"
+ "ExperimentWorkspaceSharing",
+ "ExperimentTerraformWorkspace"
]
},
"codersdk.ExternalAPIKeyScopes": {
diff --git a/coderd/coderd.go b/coderd/coderd.go
index fd361c1e0e..a9683ace20 100644
--- a/coderd/coderd.go
+++ b/coderd/coderd.go
@@ -1999,6 +1999,7 @@ func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, n
api.NotificationsEnqueuer,
&api.PrebuildsReconciler,
api.ProvisionerdServerMetrics,
+ api.Experiments,
)
if err != nil {
return nil, err
diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go
index dec8ab6d38..f5ffadb29f 100644
--- a/coderd/provisionerdserver/provisionerdserver.go
+++ b/coderd/provisionerdserver/provisionerdserver.go
@@ -121,6 +121,7 @@ type server struct {
NotificationsEnqueuer notifications.Enqueuer
PrebuildsOrchestrator *atomic.Pointer[prebuilds.ReconciliationOrchestrator]
UsageInserter *atomic.Pointer[usage.Inserter]
+ Experiments codersdk.Experiments
OIDCConfig promoauth.OAuth2Config
@@ -182,6 +183,7 @@ func NewServer(
enqueuer notifications.Enqueuer,
prebuildsOrchestrator *atomic.Pointer[prebuilds.ReconciliationOrchestrator],
metrics *Metrics,
+ experiments codersdk.Experiments,
) (proto.DRPCProvisionerDaemonServer, error) {
// Fail-fast if pointers are nil
if lifecycleCtx == nil {
@@ -253,6 +255,7 @@ func NewServer(
PrebuildsOrchestrator: prebuildsOrchestrator,
UsageInserter: usageInserter,
metrics: metrics,
+ Experiments: experiments,
}
if s.heartbeatFn == nil {
diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go
index d4597f6546..3d31251fcd 100644
--- a/coderd/provisionerdserver/provisionerdserver_test.go
+++ b/coderd/provisionerdserver/provisionerdserver_test.go
@@ -26,6 +26,7 @@ import (
"storj.io/drpc"
"cdr.dev/slog/sloggers/slogtest"
+ "github.com/coder/coder/v2/coderd"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/quartz"
"github.com/coder/serpent"
@@ -4162,7 +4163,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi
defOrg, err := db.GetDefaultOrganization(context.Background())
require.NoError(t, err, "default org not found")
- deploymentValues := &codersdk.DeploymentValues{}
+ deploymentValues := coderdtest.DeploymentValues(t)
var externalAuthConfigs []*externalauth.Config
tss := testTemplateScheduleStore()
uqhss := testUserQuietHoursScheduleStore()
@@ -4285,6 +4286,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi
notifEnq,
&op,
provisionerdserver.NewMetrics(logger),
+ coderd.ReadExperiments(logger, deploymentValues.Experiments),
)
require.NoError(t, err)
return srv, db, ps, daemon
diff --git a/codersdk/deployment.go b/codersdk/deployment.go
index 4d79058b68..073ab7faed 100644
--- a/codersdk/deployment.go
+++ b/codersdk/deployment.go
@@ -3646,6 +3646,8 @@ const (
ExperimentOAuth2 Experiment = "oauth2" // Enables OAuth2 provider functionality.
ExperimentMCPServerHTTP Experiment = "mcp-server-http" // Enables the MCP HTTP server functionality.
ExperimentWorkspaceSharing Experiment = "workspace-sharing" // Enables updating workspace ACLs for sharing with users and groups.
+ // ExperimentTerraformWorkspace uses the "Terraform Workspaces" feature, not to be confused with Coder Workspaces.
+ ExperimentTerraformWorkspace Experiment = "terraform-directory-reuse" // Enables reuse of existing terraform directory for builds
)
func (e Experiment) DisplayName() string {
@@ -3666,6 +3668,8 @@ func (e Experiment) DisplayName() string {
return "MCP HTTP Server Functionality"
case ExperimentWorkspaceSharing:
return "Workspace Sharing"
+ case ExperimentTerraformWorkspace:
+ return "Terraform Directory Reuse"
default:
// Split on hyphen and convert to title case
// e.g. "web-push" -> "Web Push", "mcp-server-http" -> "Mcp Server Http"
diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md
index f5ca96c98b..e466abaa6f 100644
--- a/docs/reference/api/schemas.md
+++ b/docs/reference/api/schemas.md
@@ -4057,16 +4057,17 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
#### Enumerated Values
-| Value |
-|------------------------|
-| `example` |
-| `auto-fill-parameters` |
-| `notifications` |
-| `workspace-usage` |
-| `web-push` |
-| `oauth2` |
-| `mcp-server-http` |
-| `workspace-sharing` |
+| Value |
+|-----------------------------|
+| `example` |
+| `auto-fill-parameters` |
+| `notifications` |
+| `workspace-usage` |
+| `web-push` |
+| `oauth2` |
+| `mcp-server-http` |
+| `workspace-sharing` |
+| `terraform-directory-reuse` |
## codersdk.ExternalAPIKeyScopes
diff --git a/docs/reference/cli/provisioner_start.md b/docs/reference/cli/provisioner_start.md
index 2a3c88ff93..f278bac310 100644
--- a/docs/reference/cli/provisioner_start.md
+++ b/docs/reference/cli/provisioner_start.md
@@ -144,6 +144,16 @@ Serve prometheus metrics on the address defined by prometheus address.
The bind address to serve prometheus metrics.
+### --experiments
+
+| | |
+|-------------|---------------------------------|
+| Type | string-array |
+| Environment | $CODER_EXPERIMENTS |
+| YAML | experiments |
+
+Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.
+
### -O, --org
| | |
diff --git a/enterprise/cli/provisionerdaemonstart.go b/enterprise/cli/provisionerdaemonstart.go
index 1869007a85..4c0ed003a1 100644
--- a/enterprise/cli/provisionerdaemonstart.go
+++ b/enterprise/cli/provisionerdaemonstart.go
@@ -23,6 +23,7 @@ import (
"github.com/coder/coder/v2/cli/clilog"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/cliutil"
+ "github.com/coder/coder/v2/coderd"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/drpcsdk"
@@ -48,6 +49,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command {
preSharedKey string
provisionerKey string
verbose bool
+ experiments []string
prometheusEnable bool
prometheusAddress string
@@ -186,6 +188,7 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command {
Listener: terraformServer,
Logger: logger.Named("terraform"),
WorkDirectory: tempDir,
+ Experiments: coderd.ReadExperiments(logger, experiments),
},
CachePath: cacheDir,
})
@@ -378,6 +381,14 @@ func (r *RootCmd) provisionerDaemonStart() *serpent.Command {
Value: serpent.StringOf(&prometheusAddress),
Default: "127.0.0.1:2112",
},
+ {
+ Name: "Experiments",
+ Description: "Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.",
+ Flag: "experiments",
+ Env: "CODER_EXPERIMENTS",
+ Value: serpent.StringArrayOf(&experiments),
+ YAML: "experiments",
+ },
}
orgContext.AttachOptions(cmd)
diff --git a/enterprise/cli/testdata/coder_provisioner_start_--help.golden b/enterprise/cli/testdata/coder_provisioner_start_--help.golden
index 439a2d68ba..e3d4c69a8c 100644
--- a/enterprise/cli/testdata/coder_provisioner_start_--help.golden
+++ b/enterprise/cli/testdata/coder_provisioner_start_--help.golden
@@ -6,6 +6,11 @@ USAGE:
Run a provisioner daemon
OPTIONS:
+ --experiments string-array, $CODER_EXPERIMENTS
+ Enable one or more experiments. These are not ready for production.
+ Separate multiple experiments with commas, or enter '*' to opt-in to
+ all available experiments.
+
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
diff --git a/enterprise/coderd/coderdenttest/coderdenttest.go b/enterprise/coderd/coderdenttest/coderdenttest.go
index a31d1d495b..29758c3dbf 100644
--- a/enterprise/coderd/coderdenttest/coderdenttest.go
+++ b/enterprise/coderd/coderdenttest/coderdenttest.go
@@ -414,6 +414,7 @@ func newExternalProvisionerDaemon(t testing.TB, client *codersdk.Client, org uui
ServeOptions: &provisionersdk.ServeOptions{
Listener: provisionerSrv,
WorkDirectory: t.TempDir(),
+ Experiments: codersdk.Experiments{},
},
}))
}()
diff --git a/enterprise/coderd/provisionerdaemons.go b/enterprise/coderd/provisionerdaemons.go
index be03af2929..0f6db2508a 100644
--- a/enterprise/coderd/provisionerdaemons.go
+++ b/enterprise/coderd/provisionerdaemons.go
@@ -362,6 +362,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
api.NotificationsEnqueuer,
&api.AGPL.PrebuildsReconciler,
api.ProvisionerdServerMetrics,
+ api.AGPL.Experiments,
)
if err != nil {
if !xerrors.Is(err, context.Canceled) {
diff --git a/provisionersdk/serve.go b/provisionersdk/serve.go
index c652cfa949..3bac226e58 100644
--- a/provisionersdk/serve.go
+++ b/provisionersdk/serve.go
@@ -15,6 +15,7 @@ import (
"storj.io/drpc/drpcserver"
"cdr.dev/slog"
+ "github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/drpcsdk"
"github.com/coder/coder/v2/coderd/tracing"
@@ -30,6 +31,7 @@ type ServeOptions struct {
Logger slog.Logger
WorkDirectory string
ExternalProvisioner bool
+ Experiments codersdk.Experiments
}
type Server interface {
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index 76a83e00c5..ea65957316 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -1895,6 +1895,7 @@ export type Experiment =
| "mcp-server-http"
| "notifications"
| "oauth2"
+ | "terraform-directory-reuse"
| "web-push"
| "workspace-sharing"
| "workspace-usage";
@@ -1905,6 +1906,7 @@ export const Experiments: Experiment[] = [
"mcp-server-http",
"notifications",
"oauth2",
+ "terraform-directory-reuse",
"web-push",
"workspace-sharing",
"workspace-usage",