这是indexloc提供的服务,不要输入任何密码
Skip to content

Support On-Demand Build Concurrency on vercel_project resource #309

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
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
env:
TF_ACC: "true"
VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }}
VERCEL_TERRAFORM_TESTING_TEAM: "team_RvxIb1z0pi9RSsQ13p3ES4cK"
VERCEL_TERRAFORM_TESTING_TEAM: "team_GwBFaTRF7juuJfO2jZzzKRgc"
VERCEL_TERRAFORM_TESTING_GITHUB_REPO: "dglsparsons/test"
VERCEL_TERRAFORM_TESTING_GITLAB_REPO: "dglsparsons/test"
VERCEL_TERRAFORM_TESTING_BITBUCKET_REPO: "dglsparsons-test/test"
Expand Down
2 changes: 2 additions & 0 deletions client/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,14 @@ type ResourceConfigResponse struct {
FunctionDefaultMemoryType *string `json:"functionDefaultMemoryType"`
FunctionDefaultTimeout *int64 `json:"functionDefaultTimeout"`
Fluid bool `json:"fluid"`
ElasticConcurrencyEnabled bool `json:"elasticConcurrencyEnabled"`
}

type ResourceConfig struct {
FunctionDefaultMemoryType *string `json:"functionDefaultMemoryType,omitempty"`
FunctionDefaultTimeout *int64 `json:"functionDefaultTimeout,omitempty"`
Fluid *bool `json:"fluid,omitempty"`
ElasticConcurrencyEnabled *bool `json:"elasticConcurrencyEnabled,omitempty"`
}

// GetProject retrieves information about an existing project from Vercel.
Expand Down
1 change: 1 addition & 0 deletions docs/data-sources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ data "vercel_project" "example" {

### Optional

- `on_demand_concurrent_builds` (Boolean) Instantly scale build capacity to skip the queue, even if all build slots are in use. You can also choose a larger build machine; charges apply per minute if it exceeds your team's default.
- `team_id` (String) The team ID the project exists beneath. Required when configuring a team resource if a default team has not been set in the provider.

### Read-Only
Expand Down
1 change: 1 addition & 0 deletions docs/resources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ resource "vercel_project" "example" {
- `install_command` (String) The install command for this project. If omitted, this value will be automatically detected.
- `node_version` (String) The version of Node.js that is used in the Build Step and for Serverless Functions. A new Deployment is required for your changes to take effect.
- `oidc_token_config` (Attributes) Configuration for OpenID Connect (OIDC) tokens. (see [below for nested schema](#nestedatt--oidc_token_config))
- `on_demand_concurrent_builds` (Boolean) Instantly scale build capacity to skip the queue, even if all build slots are in use. You can also choose a larger build machine; charges apply per minute if it exceeds your team's default.
- `options_allowlist` (Attributes) Disable Deployment Protection for CORS preflight `OPTIONS` requests for a list of paths. (see [below for nested schema](#nestedatt--options_allowlist))
- `output_directory` (String) The output directory of the project. If omitted, this value will be automatically detected.
- `password_protection` (Attributes) Ensures visitors of your Preview Deployments must enter a password in order to gain access. (see [below for nested schema](#nestedatt--password_protection))
Expand Down
7 changes: 7 additions & 0 deletions vercel/data_source_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,11 @@ For more detailed information, please see the [Vercel documentation](https://ver
},
},
},
"on_demand_concurrent_builds": schema.BoolAttribute{
Description: "Instantly scale build capacity to skip the queue, even if all build slots are in use. You can also choose a larger build machine; charges apply per minute if it exceeds your team's default.",
Optional: true,
Computed: true,
},
},
}
}
Expand Down Expand Up @@ -431,6 +436,7 @@ type ProjectDataSource struct {
SkewProtection types.String `tfsdk:"skew_protection"`
ResourceConfig types.Object `tfsdk:"resource_config"`
NodeVersion types.String `tfsdk:"node_version"`
OnDemandConcurrentBuilds types.Bool `tfsdk:"on_demand_concurrent_builds"`
}

func convertResponseToProjectDataSource(ctx context.Context, response client.ProjectResponse, plan Project, environmentVariables []client.EnvironmentVariable) (ProjectDataSource, error) {
Expand Down Expand Up @@ -496,6 +502,7 @@ func convertResponseToProjectDataSource(ctx context.Context, response client.Pro
SkewProtection: project.SkewProtection,
ResourceConfig: project.ResourceConfig,
NodeVersion: project.NodeVersion,
OnDemandConcurrentBuilds: project.OnDemandConcurrentBuilds,
}, nil
}

Expand Down
2 changes: 2 additions & 0 deletions vercel/data_source_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func TestAcc_ProjectDataSource(t *testing.T) {
resource.TestCheckResourceAttr("data.vercel_project.test", "resource_config.function_default_timeout", "30"),
resource.TestCheckResourceAttr("data.vercel_project.test", "oidc_token_config.enabled", "true"),
resource.TestCheckResourceAttr("data.vercel_project.test", "oidc_token_config.issuer_mode", "team"),
resource.TestCheckResourceAttr("data.vercel_project.test", "on_demand_concurrent_builds", "true"),
),
},
},
Expand Down Expand Up @@ -140,6 +141,7 @@ resource "vercel_project" "test" {
enabled = true
issuer_mode = "team"
}
on_demand_concurrent_builds = true
}

data "vercel_project" "test" {
Expand Down
2 changes: 1 addition & 1 deletion vercel/data_source_team_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestAcc_TeamConfigDataSource(t *testing.T) {
func testAccVercelTeamConfigDataSource(teamID string) string {
return fmt.Sprintf(`
data "vercel_team_config" "test" {
id = "%s" // Replace with a valid team ID
id = "%s"
}
`, teamID)
}
21 changes: 18 additions & 3 deletions vercel/data_source_team_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vercel
import (
"context"
"fmt"
"time"

"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
Expand Down Expand Up @@ -124,9 +125,23 @@ func (d *teamMemberDataSource) Read(ctx context.Context, req datasource.ReadRequ
return
}

response, err := d.client.GetTeamMember(ctx, client.GetTeamMemberRequest{
TeamID: config.TeamID.ValueString(),
UserID: config.UserID.ValueString(),
var response client.TeamMember
getRetry := Retry{
Base: 200 * time.Millisecond,
Attempts: 7,
}
err := getRetry.Do(func(attempt int) (shouldRetry bool, err error) {
response, err = d.client.GetTeamMember(ctx, client.GetTeamMemberRequest{
TeamID: config.TeamID.ValueString(),
UserID: config.UserID.ValueString(),
})
if client.NotFound(err) {
return true, err
}
if err != nil {
return true, fmt.Errorf("unexpected error: %w", err)
}
return false, err
})
if err != nil {
resp.Diagnostics.AddError(
Expand Down
2 changes: 1 addition & 1 deletion vercel/data_source_team_member_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func testAccTeamMemberDataSourceConfig(teamIDConfig string, user string) string
return fmt.Sprintf(`
resource "vercel_team_member" "test" {
%[1]s
user_id = "%s"
user_id = "%[2]s"
role = "MEMBER"
}

Expand Down
17 changes: 14 additions & 3 deletions vercel/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,12 @@ At this time you cannot use a Vercel Project resource with in-line ` + "`environ
},
},
},
"on_demand_concurrent_builds": schema.BoolAttribute{
Description: "Instantly scale build capacity to skip the queue, even if all build slots are in use. You can also choose a larger build machine; charges apply per minute if it exceeds your team's default.",
Optional: true,
Computed: true,
PlanModifiers: []planmodifier.Bool{boolplanmodifier.UseStateForUnknown()},
},
},
}
}
Expand Down Expand Up @@ -624,6 +630,7 @@ type Project struct {
EnableAffectedProjectsDeployments types.Bool `tfsdk:"enable_affected_projects_deployments"`
SkewProtection types.String `tfsdk:"skew_protection"`
ResourceConfig types.Object `tfsdk:"resource_config"`
OnDemandConcurrentBuilds types.Bool `tfsdk:"on_demand_concurrent_builds"`
}

type GitComments struct {
Expand Down Expand Up @@ -743,7 +750,7 @@ func (p *Project) toCreateProjectRequest(ctx context.Context, envs []Environment
PublicSource: p.PublicSource.ValueBoolPointer(),
RootDirectory: p.RootDirectory.ValueStringPointer(),
ServerlessFunctionRegion: p.ServerlessFunctionRegion.ValueString(),
ResourceConfig: resourceConfig.toClientResourceConfig(),
ResourceConfig: resourceConfig.toClientResourceConfig(p.OnDemandConcurrentBuilds),
EnablePreviewFeedback: oneBoolPointer(p.EnablePreviewFeedback, p.PreviewComments),
EnableProductionFeedback: p.EnableProductionFeedback.ValueBoolPointer(),
}, diags
Expand Down Expand Up @@ -824,7 +831,7 @@ func (p *Project) toUpdateProjectRequest(ctx context.Context, oldName string) (r
DirectoryListing: p.DirectoryListing.ValueBool(),
SkewProtectionMaxAge: toSkewProtectionAge(p.SkewProtection),
GitComments: gc.toUpdateProjectRequest(),
ResourceConfig: resourceConfig.toClientResourceConfig(),
ResourceConfig: resourceConfig.toClientResourceConfig(p.OnDemandConcurrentBuilds),
NodeVersion: p.NodeVersion.ValueString(),
}, nil
}
Expand Down Expand Up @@ -1076,7 +1083,7 @@ func (p *Project) resourceConfig(ctx context.Context) (rc *ResourceConfig, diags
return rc, diags
}

func (r *ResourceConfig) toClientResourceConfig() *client.ResourceConfig {
func (r *ResourceConfig) toClientResourceConfig(onDemandConcurrentBuilds types.Bool) *client.ResourceConfig {
if r == nil {
return nil
}
Expand All @@ -1091,6 +1098,9 @@ func (r *ResourceConfig) toClientResourceConfig() *client.ResourceConfig {
if !r.Fluid.IsUnknown() {
resourceConfig.Fluid = r.Fluid.ValueBoolPointer()
}
if !onDemandConcurrentBuilds.IsUnknown() {
resourceConfig.ElasticConcurrencyEnabled = onDemandConcurrentBuilds.ValueBoolPointer()
}
return resourceConfig
}

Expand Down Expand Up @@ -1461,6 +1471,7 @@ func convertResponseToProject(ctx context.Context, response client.ProjectRespon
GitComments: gitComments,
ResourceConfig: resourceConfig,
NodeVersion: types.StringValue(response.NodeVersion),
OnDemandConcurrentBuilds: types.BoolValue(response.ResourceConfig.ElasticConcurrencyEnabled),
}, nil
}

Expand Down
12 changes: 8 additions & 4 deletions vercel/resource_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func TestAcc_Project(t *testing.T) {
resource.TestCheckResourceAttr("vercel_project.test", "oidc_token_config.issuer_mode", "team"),
resource.TestCheckResourceAttr("vercel_project.test", "resource_config.function_default_cpu_type", "standard"),
resource.TestCheckResourceAttr("vercel_project.test", "resource_config.function_default_timeout", "60"),
resource.TestCheckResourceAttr("vercel_project.test", "on_demand_concurrent_builds", "true"),
),
},
// Update testing
Expand All @@ -98,6 +99,7 @@ func TestAcc_Project(t *testing.T) {
resource.TestCheckResourceAttr("vercel_project.test", "preview_comments", "false"),
resource.TestCheckResourceAttr("vercel_project.test", "enable_preview_feedback", "false"),
resource.TestCheckResourceAttr("vercel_project.test", "enable_production_feedback", "true"),
resource.TestCheckResourceAttr("vercel_project.test", "on_demand_concurrent_builds", "false"),
),
},
// Test mutual exclusivity validation
Expand Down Expand Up @@ -353,7 +355,7 @@ func TestAcc_ProjectWithVercelAuthAndPasswordProtectionAndTrustedIps(t *testing.
"note": "notey note",
}),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "trusted_ips.deployment_type", "all_deployments"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "trusted_ips.protection_mode", "trusted_ip_optional"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "trusted_ips.protection_mode", "trusted_ip_required"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "options_allowlist.paths.#", "1"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "options_allowlist.paths.0.value", "/foo"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_start", "protection_bypass_for_automation", "true"),
Expand Down Expand Up @@ -414,7 +416,7 @@ func TestAcc_ProjectWithVercelAuthAndPasswordProtectionAndTrustedIps(t *testing.
"note": "notey notey",
}),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "trusted_ips.deployment_type", "all_deployments"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "trusted_ips.protection_mode", "trusted_ip_optional"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "trusted_ips.protection_mode", "trusted_ip_required"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "protection_bypass_for_automation", "false"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "options_allowlist.paths.#", "1"),
resource.TestCheckResourceAttr("vercel_project.enabled_to_update", "options_allowlist.paths.0.value", "/bar"),
Expand Down Expand Up @@ -651,6 +653,7 @@ resource "vercel_project" "test" {
sensitive = true
}
]
on_demand_concurrent_builds = false
enable_preview_feedback = false
enable_production_feedback = true
}
Expand Down Expand Up @@ -708,7 +711,7 @@ resource "vercel_project" "enabled_to_start" {
}
]
deployment_type = "all_deployments"
protection_mode = "trusted_ip_optional"
protection_mode = "trusted_ip_required"
}
options_allowlist = {
paths = [
Expand Down Expand Up @@ -814,7 +817,7 @@ resource "vercel_project" "enabled_to_update" {
}
]
deployment_type = "all_deployments"
protection_mode = "trusted_ip_optional"
protection_mode = "trusted_ip_required"
}
options_allowlist = {
paths = [
Expand Down Expand Up @@ -1097,6 +1100,7 @@ resource "vercel_project" "test" {
sensitive = true
}
]
on_demand_concurrent_builds = true
}
`, projectSuffix, teamID)
}
20 changes: 8 additions & 12 deletions vercel/resource_team_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,18 @@ func TestAcc_TeamConfig(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccVercelTeamConfigBasic(testTeam(t)),
// Added since vercel_team_config schema version upgraded
ExpectNonEmptyPlan: true,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "vercel-terraform-test"),
resource.TestCheckResourceAttr(resourceName, "slug", "vercel-terraform-test-ci"),
resource.TestCheckResourceAttr(resourceName, "name", "Vercel Terraform Testing"),
resource.TestCheckResourceAttr(resourceName, "slug", "terraform-testing-vtest314"),
resource.TestCheckResourceAttrSet(resourceName, "id"),
),
},
{
Config: testAccVercelTeamConfigUpdated(testTeam(t)),
// Added since vercel_team_config schema version upgraded
ExpectNonEmptyPlan: true,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "id"),
resource.TestCheckResourceAttr(resourceName, "name", "vercel-terraform-test-ci"),
resource.TestCheckResourceAttr(resourceName, "slug", "vercel-terraform-test-ci"),
resource.TestCheckResourceAttr(resourceName, "name", "Vercel Terraform Testing o_o"),
resource.TestCheckResourceAttr(resourceName, "slug", "terraform-testing-vtest314"),
resource.TestCheckResourceAttr(resourceName, "description", "Vercel Terraform Testing"),
resource.TestCheckResourceAttr(resourceName, "sensitive_environment_variable_policy", "off"),
resource.TestCheckResourceAttr(resourceName, "remote_caching.enabled", "true"),
Expand All @@ -47,8 +43,8 @@ func TestAcc_TeamConfig(t *testing.T) {
func testAccVercelTeamConfigBasic(teamID string) string {
return fmt.Sprintf(`
resource "vercel_team_config" "test" {
id = "%s" // Replace with a valid team ID
name = "vercel-terraform-test"
id = "%s"
name = "Vercel Terraform Testing"
}
`, teamID)
}
Expand All @@ -62,8 +58,8 @@ data "vercel_file" "test" {
resource "vercel_team_config" "test" {
id = "%s"
avatar = data.vercel_file.test.file
name = "vercel-terraform-test-ci"
slug = "vercel-terraform-test-ci"
name = "Vercel Terraform Testing o_o"
slug = "terraform-testing-vtest314"
description = "Vercel Terraform Testing"
sensitive_environment_variable_policy = "off"
remote_caching = {
Expand Down
3 changes: 3 additions & 0 deletions vercel/resource_team_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ func (r *teamMemberResource) Create(ctx context.Context, req resource.CreateRequ
if client.NotFound(err) {
return true, err
}
if err != nil {
return true, fmt.Errorf("unexpected error: %w", err)
}
teamMember := convertResponseToTeamMember(response, plan)
if teamMember.Role != plan.Role {
tflog.Error(ctx, "Role has not yet propagated", map[string]any{})
Expand Down