Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .changes/unreleased/Changes-20260521-151222.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Changes
body: Allow new Fusion release tracks (`fusion-stable`, `fusion-extended`, `fusion-nightly`, `fusion-fallback`) as `dbt_version` on `dbtcloud_environment` and `dbtcloud_job`, alongside `latest-fusion`. The `force_node_selection` validator now treats any Fusion release track the same as `latest-fusion` (#684).
time: 2026-05-21T15:12:22.000000+00:00
4 changes: 2 additions & 2 deletions docs/resources/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Resource to manage dbt Cloud environments for the different dbt Cloud projects.

```terraform
resource "dbtcloud_environment" "ci_environment" {
// the dbt_version is major.minor.0-latest , major.minor.0-pre, compatible, extended, versionless, latest or latest-fusion (by default, it is set to latest if not configured)
// the dbt_version is major.minor.0-latest, major.minor.0-pre, compatible, extended, versionless, latest, or one of the Fusion release tracks: latest-fusion, fusion-stable, fusion-extended, fusion-nightly, fusion-fallback (by default, it is set to latest if not configured)
dbt_version = "latest"
name = "CI"
project_id = dbtcloud_project.dbt_project.id
Expand Down Expand Up @@ -72,7 +72,7 @@ resource "dbtcloud_environment" "profiled_environment" {
- `connection_id` (Number) A connection ID (used with Global Connections)
- `credential_id` (Number) The Credential ID for this environment. A credential is not actionable for development environments, as users have to set their own development credentials in dbt Cloud.
- `custom_branch` (String) The custom branch name to use
- `dbt_version` (String) Version number of dbt to use in this environment. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`. While `versionless` is still supported, using `latest` is recommended. Defaults to `latest` if no version is provided
- `dbt_version` (String) Version number of dbt to use in this environment. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, or one of the Fusion release tracks (`latest-fusion`, `fusion-stable`, `fusion-extended`, `fusion-nightly`, `fusion-fallback`). While `versionless` is still supported, using `latest` is recommended. Defaults to `latest` if no version is provided
- `deployment_type` (String) The type of environment. Only valid for environments of type 'deployment' and for now can only be 'production', 'staging' or left empty for generic environments
- `enable_model_query_history` (Boolean) Whether to enable model query history in this environment. As of Oct 2024, works only for Snowflake and BigQuery.
- `extended_attributes_id` (Number) The ID of the extended attributes applied
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/job.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,13 @@ An example can be found [in this GitHub issue](https://github.com/dbt-labs/terra
### Optional

- `compare_changes_flags` (String) The model selector for checking changes in the compare changes Advanced CI feature
- `dbt_version` (String) Version number of dbt to use in this job. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`. While `versionless` is still supported, using `latest` is recommended. If not set, the `dbt_version` configured on the environment is used.
- `dbt_version` (String) Version number of dbt to use in this job. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, or one of the Fusion release tracks (`latest-fusion`, `fusion-stable`, `fusion-extended`, `fusion-nightly`, `fusion-fallback`). While `versionless` is still supported, using `latest` is recommended. If not set, the `dbt_version` configured on the environment is used.
- `deferring_environment_id` (Number) Environment identifier that this job defers to (new deferring approach)
- `deferring_job_id` (Number) Job identifier that this job defers to (legacy deferring approach)
- `description` (String) Description for the job
- `errors_on_lint_failure` (Boolean) Whether the CI job should fail when a lint error is found. Only used when `run_lint` is set to `true`. Defaults to `true`.
- `execution` (Attributes) Execution settings for the job (see [below for nested schema](#nestedatt--execution))
- `force_node_selection` (Boolean) Whether to force node selection (SAO - Select All Optimizations) for the job. If `dbt_version` is not set to `latest-fusion`, this must be set to `true` when specified.
- `force_node_selection` (Boolean) Whether to force node selection (SAO - Select All Optimizations) for the job. If `dbt_version` is not set to a Fusion release track (e.g. `latest-fusion`), this must be set to `true` when specified.
- `generate_docs` (Boolean) Flag for whether the job should generate documentation
- `is_active` (Boolean) Should always be set to true as setting it to false is the same as creating a job in a deleted state. To create/keep a job in a 'deactivated' state, check the `triggers` config. Setting it to false essentially deletes the job. On resource creation, this field is enforced to be true.
- `job_completion_trigger_condition` (Block List) Which other job should trigger this job when it finishes, and on which conditions (sometimes referred as 'job chaining'). (see [below for nested schema](#nestedblock--job_completion_trigger_condition))
Expand Down
2 changes: 1 addition & 1 deletion examples/resources/dbtcloud_environment/resource.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
resource "dbtcloud_environment" "ci_environment" {
// the dbt_version is major.minor.0-latest , major.minor.0-pre, compatible, extended, versionless, latest or latest-fusion (by default, it is set to latest if not configured)
// the dbt_version is major.minor.0-latest, major.minor.0-pre, compatible, extended, versionless, latest, or one of the Fusion release tracks: latest-fusion, fusion-stable, fusion-extended, fusion-nightly, fusion-fallback (by default, it is set to latest if not configured)
dbt_version = "latest"
name = "CI"
project_id = dbtcloud_project.dbt_project.id
Expand Down
2 changes: 1 addition & 1 deletion pkg/framework/objects/environment/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (r *environmentResource) Schema(
Computed: true,
Optional: true,
Default: stringdefault.StaticString("latest"),
Description: "Version number of dbt to use in this environment. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`. While `versionless` is still supported, using `latest` is recommended. Defaults to `latest` if no version is provided",
Description: "Version number of dbt to use in this environment. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, or one of the Fusion release tracks (`latest-fusion`, `fusion-stable`, `fusion-extended`, `fusion-nightly`, `fusion-fallback`). While `versionless` is still supported, using `latest` is recommended. Defaults to `latest` if no version is provided",
Validators: []validator.String{
helper.DbtVersionValidator{}, // Custom validator to check the dbt version format
},
Expand Down
4 changes: 2 additions & 2 deletions pkg/framework/objects/job/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,12 @@ func (j *jobResource) Schema(
},
"dbt_version": resource_schema.StringAttribute{
Optional: true,
Description: "Version number of dbt to use in this job. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`. While `versionless` is still supported, using `latest` is recommended. If not set, the `dbt_version` configured on the environment is used.",
Description: "Version number of dbt to use in this job. It needs to be in the format `major.minor.0-latest` (e.g. `1.5.0-latest`), `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, or one of the Fusion release tracks (`latest-fusion`, `fusion-stable`, `fusion-extended`, `fusion-nightly`, `fusion-fallback`). While `versionless` is still supported, using `latest` is recommended. If not set, the `dbt_version` configured on the environment is used.",
},
"force_node_selection": resource_schema.BoolAttribute{
Optional: true,
Computed: true,
Description: "Whether to force node selection (SAO - Select All Optimizations) for the job. If `dbt_version` is not set to `latest-fusion`, this must be set to `true` when specified.",
Description: "Whether to force node selection (SAO - Select All Optimizations) for the job. If `dbt_version` is not set to a Fusion release track (e.g. `latest-fusion`), this must be set to `true` when specified.",
Validators: []validator.Bool{
job_validators.ForceNodeSelectionValidator(),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/helper"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand All @@ -15,12 +16,12 @@ type forceNodeSelectionValidator struct{}

// Description returns a plain text description of the validator's behavior, suitable for a practitioner to understand its impact.
func (v forceNodeSelectionValidator) Description(ctx context.Context) string {
return "When dbt_version is not 'latest-fusion', force_node_selection must be set to true"
return "When dbt_version is not a Fusion release track (e.g. 'latest-fusion'), force_node_selection must be set to true"
}

// MarkdownDescription returns a markdown formatted description of the validator's behavior, suitable for a practitioner to understand its impact.
func (v forceNodeSelectionValidator) MarkdownDescription(ctx context.Context) string {
return "When `dbt_version` is not `latest-fusion`, `force_node_selection` must be set to `true`"
return "When `dbt_version` is not a Fusion release track (e.g. `latest-fusion`), `force_node_selection` must be set to `true`"
}

// ValidateBool performs the validation.
Expand All @@ -46,22 +47,22 @@ func (v forceNodeSelectionValidator) ValidateBool(ctx context.Context, req valid
return
}

// Validation: if dbt_version is not "latest-fusion", force_node_selection must be true
if dbtVersion.ValueString() != "latest-fusion" && !forceNodeSelection {
// Validation: if dbt_version is not a Fusion release track, force_node_selection must be true
if !helper.IsFusionVersion(dbtVersion.ValueString()) && !forceNodeSelection {
resp.Diagnostics.AddAttributeError(
req.Path,
"Invalid force_node_selection Configuration",
fmt.Sprintf(
"When dbt_version is '%s' (not 'latest-fusion'), force_node_selection must be set to true. "+
"Set force_node_selection = true or change dbt_version to 'latest-fusion'.",
"When dbt_version is '%s' (not a Fusion release track such as 'latest-fusion'), force_node_selection must be set to true. "+
"Set force_node_selection = true or change dbt_version to a Fusion release track.",
dbtVersion.ValueString(),
),
)
}
}

// ForceNodeSelectionValidator returns a validator that ensures force_node_selection is true
// when dbt_version is not "latest-fusion".
// when dbt_version is not a Fusion release track.
func ForceNodeSelectionValidator() validator.Bool {
return forceNodeSelectionValidator{}
}
20 changes: 16 additions & 4 deletions pkg/helper/dbt_version_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import (

type DbtVersionValidator struct{}

const validDbtVersionsDescription = "`major.minor.0-latest`, `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, `latest-fusion`, `fusion-stable`, `fusion-extended`, `fusion-nightly` or `fusion-fallback`"

func (v DbtVersionValidator) Description(ctx context.Context) string {
return "Validates that the dbt_version is in the format `major.minor.0-latest`, `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest`, or `latest-fusion`."
return "Validates that the dbt_version is in the format " + validDbtVersionsDescription + "."
}

func (v DbtVersionValidator) MarkdownDescription(ctx context.Context) string {
return "Validates that the `dbt_version` is in the format `major.minor.0-latest`, `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`."
return "Validates that the `dbt_version` is in the format " + validDbtVersionsDescription + "."
}

func (v DbtVersionValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
Expand All @@ -28,7 +30,7 @@ func (v DbtVersionValidator) ValidateString(ctx context.Context, req validator.S
dbtVersion := req.ConfigValue.ValueString()

// Define the regex pattern for valid dbt_version formats
validVersionPattern := `^(compatible|extended|latest|versionless|latest-fusion|[0-9]+\.[0-9]+\.0-(latest|pre))$`
validVersionPattern := `^(compatible|extended|latest|versionless|latest-fusion|fusion-stable|fusion-extended|fusion-nightly|fusion-fallback|[0-9]+\.[0-9]+\.0-(latest|pre))$`
matched, err := regexp.MatchString(validVersionPattern, dbtVersion)
if err != nil {
resp.Diagnostics.AddError(
Expand All @@ -42,7 +44,17 @@ func (v DbtVersionValidator) ValidateString(ctx context.Context, req validator.S
if !matched {
resp.Diagnostics.AddError(
"Invalid dbt_version Format",
fmt.Sprintf("The `dbt_version` must be in the format `major.minor.0-latest`, `major.minor.0-pre`, `compatible`, `extended`, `versionless`, `latest` or `latest-fusion`. Got: %s", dbtVersion),
fmt.Sprintf("The `dbt_version` must be in the format "+validDbtVersionsDescription+". Got: %s", dbtVersion),
)
}
}

// IsFusionVersion reports whether the supplied dbt_version string is one of
// the Fusion release tracks.
func IsFusionVersion(dbtVersion string) bool {
switch dbtVersion {
case "latest-fusion", "fusion-stable", "fusion-extended", "fusion-nightly", "fusion-fallback":
return true
}
return false
}
Loading