diff --git a/client/project.go b/client/project.go index f16d0cf2..3b897410 100644 --- a/client/project.go +++ b/client/project.go @@ -44,20 +44,21 @@ type DeploymentExpiration struct { // CreateProjectRequest defines the information necessary to create a project. type CreateProjectRequest struct { - BuildCommand *string `json:"buildCommand"` - CommandForIgnoringBuildStep *string `json:"commandForIgnoringBuildStep,omitempty"` - DevCommand *string `json:"devCommand"` - EnvironmentVariables []EnvironmentVariable `json:"environmentVariables,omitempty"` - Framework *string `json:"framework"` - GitRepository *GitRepository `json:"gitRepository,omitempty"` - InstallCommand *string `json:"installCommand"` - Name string `json:"name"` - OIDCTokenConfig *OIDCTokenConfig `json:"oidcTokenConfig,omitempty"` - OutputDirectory *string `json:"outputDirectory"` - PublicSource *bool `json:"publicSource"` - RootDirectory *string `json:"rootDirectory"` - ServerlessFunctionRegion string `json:"serverlessFunctionRegion,omitempty"` - ResourceConfig *ResourceConfig `json:"resourceConfig,omitempty"` + BuildCommand *string `json:"buildCommand"` + CommandForIgnoringBuildStep *string `json:"commandForIgnoringBuildStep,omitempty"` + DevCommand *string `json:"devCommand"` + EnableAffectedProjectsDeployments *bool `json:"enableAffectedProjectsDeployments,omitempty"` + EnvironmentVariables []EnvironmentVariable `json:"environmentVariables,omitempty"` + Framework *string `json:"framework"` + GitRepository *GitRepository `json:"gitRepository,omitempty"` + InstallCommand *string `json:"installCommand"` + Name string `json:"name"` + OIDCTokenConfig *OIDCTokenConfig `json:"oidcTokenConfig,omitempty"` + OutputDirectory *string `json:"outputDirectory"` + PublicSource *bool `json:"publicSource"` + RootDirectory *string `json:"rootDirectory"` + ServerlessFunctionRegion string `json:"serverlessFunctionRegion,omitempty"` + ResourceConfig *ResourceConfig `json:"resourceConfig,omitempty"` } // CreateProject will create a project within Vercel. @@ -191,6 +192,7 @@ type ProjectResponse struct { ProtectionBypass map[string]ProtectionBypass `json:"protectionBypass"` AutoExposeSystemEnvVars *bool `json:"autoExposeSystemEnvs"` EnablePreviewFeedback *bool `json:"enablePreviewFeedback"` + EnableAffectedProjectsDeployments *bool `json:"enableAffectedProjectsDeployments"` AutoAssignCustomDomains bool `json:"autoAssignCustomDomains"` GitLFS bool `json:"gitLFS"` ServerlessFunctionZeroConfigFailover bool `json:"serverlessFunctionZeroConfigFailover"` @@ -291,6 +293,7 @@ type UpdateProjectRequest struct { OptionsAllowlist *OptionsAllowlist `json:"optionsAllowlist"` AutoExposeSystemEnvVars bool `json:"autoExposeSystemEnvs"` EnablePreviewFeedback *bool `json:"enablePreviewFeedback"` + EnableAffectedProjectsDeployments *bool `json:"enableAffectedProjectsDeployments,omitempty"` AutoAssignCustomDomains bool `json:"autoAssignCustomDomains"` GitLFS bool `json:"gitLFS"` ServerlessFunctionZeroConfigFailover bool `json:"serverlessFunctionZeroConfigFailover"` diff --git a/docs/data-sources/project.md b/docs/data-sources/project.md index cc53fed9..38dc3a21 100644 --- a/docs/data-sources/project.md +++ b/docs/data-sources/project.md @@ -43,6 +43,7 @@ data "vercel_project" "example" { - `customer_success_code_visibility` (Boolean) Allows Vercel Customer Support to inspect all Deployments' source code in this project to assist with debugging. - `dev_command` (String) The dev command for this project. If omitted, this value will be automatically detected. - `directory_listing` (Boolean) If no index file is present within a directory, the directory contents will be displayed. +- `enable_affected_projects_deployments` (Boolean) When enabled, Vercel will automatically deploy all projects that are affected by a change to this project. - `environment` (Attributes Set) A list of environment variables that should be configured for the project. (see [below for nested schema](#nestedatt--environment)) - `framework` (String) The framework that is being used for this project. If omitted, no framework is selected. - `function_failover` (Boolean) Automatically failover Serverless Functions to the nearest region. You can customize regions through vercel.json. A new Deployment is required for your changes to take effect. diff --git a/docs/resources/project.md b/docs/resources/project.md index e5c678bc..d443bdd6 100644 --- a/docs/resources/project.md +++ b/docs/resources/project.md @@ -61,6 +61,7 @@ resource "vercel_project" "example" { - `customer_success_code_visibility` (Boolean) Allows Vercel Customer Support to inspect all Deployments' source code in this project to assist with debugging. - `dev_command` (String) The dev command for this project. If omitted, this value will be automatically detected. - `directory_listing` (Boolean) If no index file is present within a directory, the directory contents will be displayed. +- `enable_affected_projects_deployments` (Boolean) When enabled, Vercel will automatically deploy all projects that are affected by a change to this project. - `environment` (Attributes Set) A set of Environment Variables that should be configured for the project. (see [below for nested schema](#nestedatt--environment)) - `framework` (String) The framework that is being used for this project. If omitted, no framework is selected. - `function_failover` (Boolean) Automatically failover Serverless Functions to the nearest region. You can customize regions through vercel.json. A new Deployment is required for your changes to take effect. diff --git a/vercel/data_source_project.go b/vercel/data_source_project.go index 3be3b0cf..2f5ebda9 100644 --- a/vercel/data_source_project.go +++ b/vercel/data_source_project.go @@ -278,6 +278,10 @@ For more detailed information, please see the [Vercel documentation](https://ver Computed: true, Description: "Specifies whether the source code and logs of the deployments for this project should be public or not.", }, + "enable_affected_projects_deployments": schema.BoolAttribute{ + Computed: true, + Description: "When enabled, Vercel will automatically deploy all projects that are affected by a change to this project.", + }, "root_directory": schema.StringAttribute{ Computed: true, Description: "The name of a directory or relative path to the source code of your project. When null is used it will default to the project root.", @@ -404,6 +408,7 @@ type ProjectDataSource struct { GitForkProtection types.Bool `tfsdk:"git_fork_protection"` PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"` DirectoryListing types.Bool `tfsdk:"directory_listing"` + EnableAffectedProjectsDeployments types.Bool `tfsdk:"enable_affected_projects_deployments"` SkewProtection types.String `tfsdk:"skew_protection"` ResourceConfig *ResourceConfig `tfsdk:"resource_config"` } @@ -472,6 +477,7 @@ func convertResponseToProjectDataSource(ctx context.Context, response client.Pro GitForkProtection: project.GitForkProtection, PrioritiseProductionBuilds: project.PrioritiseProductionBuilds, DirectoryListing: project.DirectoryListing, + EnableAffectedProjectsDeployments: project.EnableAffectedProjectsDeployments, SkewProtection: project.SkewProtection, ResourceConfig: project.ResourceConfig, }, nil diff --git a/vercel/resource_project.go b/vercel/resource_project.go index 944ae3c4..ba107348 100644 --- a/vercel/resource_project.go +++ b/vercel/resource_project.go @@ -432,6 +432,10 @@ At this time you cannot use a Vercel Project resource with in-line ` + "`environ PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()}, Description: "Vercel provides a set of Environment Variables that are automatically populated by the System, such as the URL of the Deployment or the name of the Git branch deployed. To expose them to your Deployments, enable this field", }, + "enable_affected_projects_deployments": schema.BoolAttribute{ + Optional: true, + Description: "When enabled, Vercel will automatically deploy all projects that are affected by a change to this project.", + }, "git_comments": schema.SingleNestedAttribute{ Description: "Configuration for Git Comments.", Optional: true, @@ -604,6 +608,7 @@ type Project struct { GitForkProtection types.Bool `tfsdk:"git_fork_protection"` PrioritiseProductionBuilds types.Bool `tfsdk:"prioritise_production_builds"` DirectoryListing types.Bool `tfsdk:"directory_listing"` + EnableAffectedProjectsDeployments types.Bool `tfsdk:"enable_affected_projects_deployments"` SkewProtection types.String `tfsdk:"skew_protection"` ResourceConfig *ResourceConfig `tfsdk:"resource_config"` } @@ -703,19 +708,20 @@ func parseEnvironment(ctx context.Context, vars []EnvironmentItem) (out []client func (p *Project) toCreateProjectRequest(ctx context.Context, envs []EnvironmentItem) (req client.CreateProjectRequest, diags diag.Diagnostics) { clientEnvs, diags := parseEnvironment(ctx, envs) return client.CreateProjectRequest{ - BuildCommand: p.BuildCommand.ValueStringPointer(), - CommandForIgnoringBuildStep: p.IgnoreCommand.ValueStringPointer(), - DevCommand: p.DevCommand.ValueStringPointer(), - EnvironmentVariables: clientEnvs, - Framework: p.Framework.ValueStringPointer(), - GitRepository: p.GitRepository.toCreateProjectRequest(), - InstallCommand: p.InstallCommand.ValueStringPointer(), - Name: p.Name.ValueString(), - OIDCTokenConfig: p.OIDCTokenConfig.toCreateProjectRequest(), - OutputDirectory: p.OutputDirectory.ValueStringPointer(), - PublicSource: p.PublicSource.ValueBoolPointer(), - RootDirectory: p.RootDirectory.ValueStringPointer(), - ServerlessFunctionRegion: p.ServerlessFunctionRegion.ValueString(), + BuildCommand: p.BuildCommand.ValueStringPointer(), + CommandForIgnoringBuildStep: p.IgnoreCommand.ValueStringPointer(), + DevCommand: p.DevCommand.ValueStringPointer(), + EnableAffectedProjectsDeployments: p.EnableAffectedProjectsDeployments.ValueBoolPointer(), + EnvironmentVariables: clientEnvs, + Framework: p.Framework.ValueStringPointer(), + GitRepository: p.GitRepository.toCreateProjectRequest(), + InstallCommand: p.InstallCommand.ValueStringPointer(), + Name: p.Name.ValueString(), + OIDCTokenConfig: p.OIDCTokenConfig.toCreateProjectRequest(), + OutputDirectory: p.OutputDirectory.ValueStringPointer(), + PublicSource: p.PublicSource.ValueBoolPointer(), + RootDirectory: p.RootDirectory.ValueStringPointer(), + ServerlessFunctionRegion: p.ServerlessFunctionRegion.ValueString(), }, diags } @@ -764,6 +770,7 @@ func (p *Project) toUpdateProjectRequest(ctx context.Context, oldName string) (r OptionsAllowlist: p.OptionsAllowlist.toUpdateProjectRequest(), AutoExposeSystemEnvVars: p.AutoExposeSystemEnvVars.ValueBool(), EnablePreviewFeedback: p.PreviewComments.ValueBoolPointer(), + EnableAffectedProjectsDeployments: p.EnableAffectedProjectsDeployments.ValueBoolPointer(), AutoAssignCustomDomains: p.AutoAssignCustomDomains.ValueBool(), GitLFS: p.GitLFS.ValueBool(), ServerlessFunctionZeroConfigFailover: p.FunctionFailover.ValueBool(), @@ -1042,20 +1049,22 @@ func (t *OptionsAllowlist) toUpdateProjectRequest() *client.OptionsAllowlist { * This is implemented in the below uncoerceString and uncoerceBool functions. */ type projectCoercedFields struct { - BuildCommand types.String - DevCommand types.String - InstallCommand types.String - OutputDirectory types.String - PublicSource types.Bool + BuildCommand types.String + DevCommand types.String + InstallCommand types.String + OutputDirectory types.String + PublicSource types.Bool + EnableAffectedProjectsDeployments types.Bool } func (p *Project) coercedFields() projectCoercedFields { return projectCoercedFields{ - BuildCommand: p.BuildCommand, - DevCommand: p.DevCommand, - InstallCommand: p.InstallCommand, - OutputDirectory: p.OutputDirectory, - PublicSource: p.PublicSource, + BuildCommand: p.BuildCommand, + DevCommand: p.DevCommand, + InstallCommand: p.InstallCommand, + OutputDirectory: p.OutputDirectory, + PublicSource: p.PublicSource, + EnableAffectedProjectsDeployments: p.EnableAffectedProjectsDeployments, } } @@ -1361,6 +1370,7 @@ func convertResponseToProject(ctx context.Context, response client.ProjectRespon ProtectionBypassForAutomationSecret: protectionBypassSecret, AutoExposeSystemEnvVars: types.BoolPointerValue(response.AutoExposeSystemEnvVars), PreviewComments: types.BoolPointerValue(response.EnablePreviewFeedback), + EnableAffectedProjectsDeployments: uncoerceBool(fields.EnableAffectedProjectsDeployments, types.BoolPointerValue(response.EnableAffectedProjectsDeployments)), AutoAssignCustomDomains: types.BoolValue(response.AutoAssignCustomDomains), GitLFS: types.BoolValue(response.GitLFS), FunctionFailover: types.BoolValue(response.ServerlessFunctionZeroConfigFailover), diff --git a/vercel/resource_project_test.go b/vercel/resource_project_test.go index b135bd3a..0523a29d 100644 --- a/vercel/resource_project_test.go +++ b/vercel/resource_project_test.go @@ -411,6 +411,35 @@ func TestAcc_ProjectImport(t *testing.T) { }) } +func TestAcc_ProjectEnablingAffectedProjectDeployments(t *testing.T) { + projectSuffix := acctest.RandString(16) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + CheckDestroy: testAccProjectDestroy("vercel_project.test", testTeam()), + Steps: []resource.TestStep{ + { + Config: testAccProjectConfigWithoutEnableAffectedSet(projectSuffix, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckNoResourceAttr("vercel_project.test", "enable_affected_projects_deployments"), + ), + }, + { + Config: testAccProjectConfigWithEnableAffectedTrue(projectSuffix, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("vercel_project.test", "enable_affected_projects_deployments", "true"), + ), + }, + { + Config: testAccProjectConfigWithEnableAffectedFalse(projectSuffix, teamIDConfig()), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("vercel_project.test", "enable_affected_projects_deployments", "false"), + ), + }, + }, + }) +} + func testAccProjectExists(n, teamID string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -833,6 +862,35 @@ resource "vercel_project" "test" { `, projectSuffix, teamID) } +func testAccProjectConfigWithoutEnableAffectedSet(projectSuffix, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "test" { + name = "test-acc-project-%s" + %s +} +`, projectSuffix, teamID) +} + +func testAccProjectConfigWithEnableAffectedFalse(projectSuffix, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "test" { + name = "test-acc-project-%s" + %s + enable_affected_projects_deployments = false +} +`, projectSuffix, teamID) +} + +func testAccProjectConfigWithEnableAffectedTrue(projectSuffix, teamID string) string { + return fmt.Sprintf(` +resource "vercel_project" "test" { + name = "test-acc-project-%s" + %s + enable_affected_projects_deployments = true +} +`, projectSuffix, teamID) +} + func testAccProjectConfig(projectSuffix, teamID string) string { return fmt.Sprintf(` resource "vercel_project" "test" {