Skip to content

Commit 247b116

Browse files
authored
Add resource for project_environment_variables (#235)
1 parent 9966e1a commit 247b116

13 files changed

+918
-47
lines changed

client/environment_variable.go

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ func (c *Client) CreateEnvironmentVariable(ctx context.Context, request CreateEn
4646
if err2 != nil {
4747
return e, err2
4848
}
49-
id, err3 := c.findConflictingEnvID(ctx, request.TeamID, request.ProjectID, conflictingEnv)
50-
if err3 != nil {
51-
return e, fmt.Errorf("%w %s", err, err3)
49+
50+
envs, err3 := c.ListEnvironmentVariables(ctx, request.TeamID, request.ProjectID)
51+
if err != nil {
52+
return e, fmt.Errorf("%s: unable to list environment variables to detect conflict: %s", err, err3)
53+
}
54+
55+
id, found := findConflictingEnvID(request.TeamID, request.ProjectID, conflictingEnv, envs)
56+
if found {
57+
return e, fmt.Errorf("%w the conflicting environment variable ID is %s", err, id)
5258
}
53-
return e, fmt.Errorf("%w the conflicting environment variable ID is %s", err, id)
5459
}
5560
if err != nil {
5661
return e, err
@@ -89,22 +94,17 @@ func overlaps(s []string, e []string) bool {
8994
return false
9095
}
9196

92-
func (c *Client) findConflictingEnvID(ctx context.Context, teamID, projectID string, envConflict EnvConflictError) (string, error) {
93-
envs, err := c.ListEnvironmentVariables(ctx, teamID, projectID)
94-
if err != nil {
95-
return "", fmt.Errorf("unable to list environment variables to detect conflict: %w", err)
96-
}
97-
97+
func findConflictingEnvID(teamID, projectID string, envConflict EnvConflictError, envs []EnvironmentVariable) (string, bool) {
9898
for _, env := range envs {
9999
if env.Key == envConflict.Key && overlaps(env.Target, envConflict.Target) && env.GitBranch == envConflict.GitBranch {
100100
id := fmt.Sprintf("%s/%s", projectID, env.ID)
101101
if teamID != "" {
102102
id = fmt.Sprintf("%s/%s", teamID, id)
103103
}
104-
return id, nil
104+
return id, true
105105
}
106106
}
107-
return "", fmt.Errorf("conflicting environment variable not found")
107+
return "", false
108108
}
109109

110110
type CreateEnvironmentVariablesRequest struct {
@@ -113,7 +113,20 @@ type CreateEnvironmentVariablesRequest struct {
113113
TeamID string
114114
}
115115

116-
func (c *Client) CreateEnvironmentVariables(ctx context.Context, request CreateEnvironmentVariablesRequest) error {
116+
type CreateEnvironmentVariablesResponse struct {
117+
Created []EnvironmentVariable `json:"created"`
118+
Failed []struct {
119+
Error struct {
120+
Code string `json:"code"`
121+
Message string `json:"message"`
122+
Key string `json:"envVarKey"`
123+
GitBranch *string `json:"gitBranch"`
124+
Target []string `json:"target"`
125+
} `json:"error"`
126+
} `json:"failed"`
127+
}
128+
129+
func (c *Client) CreateEnvironmentVariables(ctx context.Context, request CreateEnvironmentVariablesRequest) ([]EnvironmentVariable, error) {
117130
url := fmt.Sprintf("%s/v10/projects/%s/env", c.baseURL, request.ProjectID)
118131
if c.teamID(request.TeamID) != "" {
119132
url = fmt.Sprintf("%s?teamId=%s", url, c.teamID(request.TeamID))
@@ -123,27 +136,41 @@ func (c *Client) CreateEnvironmentVariables(ctx context.Context, request CreateE
123136
"url": url,
124137
"payload": payload,
125138
})
139+
140+
var response CreateEnvironmentVariablesResponse
126141
err := c.doRequest(clientRequest{
127142
ctx: ctx,
128143
method: "POST",
129144
url: url,
130145
body: payload,
131-
}, nil)
132-
if conflictingEnv, isConflicting, err2 := conflictingEnvVar(err); isConflicting {
133-
if err2 != nil {
134-
return err2
146+
}, &response)
147+
if err != nil {
148+
return nil, err
149+
}
150+
151+
if len(response.Failed) > 0 {
152+
envs, err := c.ListEnvironmentVariables(ctx, request.TeamID, request.ProjectID)
153+
if err != nil {
154+
return response.Created, fmt.Errorf("failed to create environment variables. error detecting conflicting environment variables: %w", err)
135155
}
136-
id, err3 := c.findConflictingEnvID(ctx, request.TeamID, request.ProjectID, conflictingEnv)
137-
if err3 != nil {
138-
return fmt.Errorf("%w %s", err, err3)
156+
for _, failed := range response.Failed {
157+
if failed.Error.Code == "ENV_CONFLICT" {
158+
id, found := findConflictingEnvID(request.TeamID, request.ProjectID, EnvConflictError{
159+
Key: failed.Error.Key,
160+
Target: failed.Error.Target,
161+
GitBranch: failed.Error.GitBranch,
162+
}, envs)
163+
if found {
164+
err = fmt.Errorf("%w, conflicting environment variable ID is %s", err, id)
165+
}
166+
} else {
167+
err = fmt.Errorf("failed to create environment variables, %s %s %s", failed.Error.Message, failed.Error.Key, failed.Error.Target)
168+
}
139169
}
140-
return fmt.Errorf("%w the conflicting environment variable ID is %s", err, id)
141-
}
142-
if err != nil {
143-
return err
170+
return response.Created, err
144171
}
145172

146-
return err
173+
return response.Created, err
147174
}
148175

149176
// UpdateEnvironmentVariableRequest defines the information that needs to be passed to Vercel in order to

client/project.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type EnvironmentVariable struct {
3131
ID string `json:"id,omitempty"`
3232
TeamID string `json:"-"`
3333
Comment string `json:"comment"`
34+
Decrypted bool `json:"decrypted"`
3435
}
3536

3637
type DeploymentExpiration struct {

client/request.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ func (c *Client) _doRequest(req *http.Request, v interface{}, errorOnNoContent b
111111

112112
defer resp.Body.Close()
113113
responseBody, err := io.ReadAll(resp.Body)
114+
114115
if err != nil {
115116
return fmt.Errorf("error reading response body: %w", err)
116117
}

docs/resources/project.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ description: |-
66
Provides a Project resource.
77
A Project groups deployments and custom domains. To deploy on Vercel, you need to create a Project.
88
For more detailed information, please see the Vercel documentation https://vercel.com/docs/concepts/projects/overview.
9-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the environment field.
10-
At this time you cannot use a Vercel Project resource with in-line environment in conjunction with any vercel_project_environment_variable resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
9+
~> Terraform currently provides a standalone Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and this Project resource with Environment Variables defined in-line via the environment field.
10+
At this time you cannot use a Vercel Project resource with in-line environment in conjunction with any vercel_project_environment_variables or vercel_project_environment_variable resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
1111
---
1212

1313
# vercel_project (Resource)
@@ -18,8 +18,8 @@ A Project groups deployments and custom domains. To deploy on Vercel, you need t
1818

1919
For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/overview).
2020

21-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the `environment` field.
22-
At this time you cannot use a Vercel Project resource with in-line `environment` in conjunction with any `vercel_project_environment_variable` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
21+
~> Terraform currently provides a standalone Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and this Project resource with Environment Variables defined in-line via the `environment` field.
22+
At this time you cannot use a Vercel Project resource with in-line `environment` in conjunction with any `vercel_project_environment_variables` or `vercel_project_environment_variable` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
2323

2424
## Example Usage
2525

docs/resources/project_environment_variable.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ description: |-
66
Provides a Project Environment Variable resource.
77
A Project Environment Variable resource defines an Environment Variable on a Vercel Project.
88
For more detailed information, please see the Vercel documentation https://vercel.com/docs/concepts/projects/environment-variables.
9-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the environment field.
10-
At this time you cannot use a Vercel Project resource with in-line environment in conjunction with any vercel_project_environment_variable resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
9+
~> Terraform currently provides this Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and a Project resource with Environment Variables defined in-line via the environment field.
10+
At this time you cannot use a Vercel Project resource with in-line environment in conjunction with any vercel_project_environment_variables or vercel_project_environment_variable resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
1111
---
1212

1313
# vercel_project_environment_variable (Resource)
@@ -18,8 +18,8 @@ A Project Environment Variable resource defines an Environment Variable on a Ver
1818

1919
For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables).
2020

21-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the `environment` field.
22-
At this time you cannot use a Vercel Project resource with in-line `environment` in conjunction with any `vercel_project_environment_variable` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
21+
~> Terraform currently provides this Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and a Project resource with Environment Variables defined in-line via the `environment` field.
22+
At this time you cannot use a Vercel Project resource with in-line `environment` in conjunction with any `vercel_project_environment_variables` or `vercel_project_environment_variable` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
2323

2424
## Example Usage
2525

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "vercel_project_environment_variables Resource - terraform-provider-vercel"
4+
subcategory: ""
5+
description: |-
6+
Provides a resource for managing a number of Project Environment Variables.
7+
This resource defines multiple Environment Variables on a Vercel Project.
8+
For more detailed information, please see the Vercel documentation https://vercel.com/docs/concepts/projects/environment-variables.
9+
~> Terraform currently provides this Project Environment Variables resource (multiple Environment Variables), a single Project Environment Variable Resource, and a Project resource with Environment Variables defined in-line via the environment field.
10+
At this time you cannot use a Vercel Project resource with in-line environment in conjunction with any vercel_project_environment_variables or vercel_project_environment_variable resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
11+
---
12+
13+
# vercel_project_environment_variables (Resource)
14+
15+
Provides a resource for managing a number of Project Environment Variables.
16+
17+
This resource defines multiple Environment Variables on a Vercel Project.
18+
19+
For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables).
20+
21+
~> Terraform currently provides this Project Environment Variables resource (multiple Environment Variables), a single Project Environment Variable Resource, and a Project resource with Environment Variables defined in-line via the `environment` field.
22+
At this time you cannot use a Vercel Project resource with in-line `environment` in conjunction with any `vercel_project_environment_variables` or `vercel_project_environment_variable` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
23+
24+
## Example Usage
25+
26+
```terraform
27+
resource "vercel_project" "example" {
28+
name = "example-project"
29+
30+
git_repository = {
31+
type = "github"
32+
repo = "vercel/some-repo"
33+
}
34+
}
35+
36+
resource "vercel_project_environment_variables" "example" {
37+
project_id = vercel_project.test.id
38+
variables = [
39+
{
40+
key = "SOME_VARIABLE"
41+
value = "some_value"
42+
target = ["production", "preview"]
43+
},
44+
{
45+
key = "ANOTHER_VARIABLE"
46+
value = "another_value"
47+
git_branch = "staging"
48+
target = ["preview"]
49+
},
50+
{
51+
key = "SENSITIVE_VARIABLE"
52+
value = "sensitive_value"
53+
target = ["production"]
54+
sensitive = true
55+
}
56+
]
57+
}
58+
```
59+
60+
<!-- schema generated by tfplugindocs -->
61+
## Schema
62+
63+
### Required
64+
65+
- `project_id` (String) The ID of the Vercel project.
66+
- `variables` (Attributes Set) A set of Environment Variables that should be configured for the project. (see [below for nested schema](#nestedatt--variables))
67+
68+
### Optional
69+
70+
- `team_id` (String) The ID of the Vercel team. Required when configuring a team resource if a default team has not been set in the provider.
71+
72+
<a id="nestedatt--variables"></a>
73+
### Nested Schema for `variables`
74+
75+
Required:
76+
77+
- `key` (String) The name of the Environment Variable.
78+
- `target` (Set of String) The environments that the Environment Variable should be present on. Valid targets are either `production`, `preview`, or `development`.
79+
- `value` (String) The value of the Environment Variable.
80+
81+
Optional:
82+
83+
- `comment` (String) A comment explaining what the environment variable is for.
84+
- `git_branch` (String) The git branch of the Environment Variable.
85+
- `sensitive` (Boolean) Whether the Environment Variable is sensitive or not.
86+
87+
Read-Only:
88+
89+
- `id` (String) The ID of the Environment Variable.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
resource "vercel_project" "example" {
2+
name = "example-project"
3+
4+
git_repository = {
5+
type = "github"
6+
repo = "vercel/some-repo"
7+
}
8+
}
9+
10+
resource "vercel_project_environment_variables" "example" {
11+
project_id = vercel_project.test.id
12+
variables = [
13+
{
14+
key = "SOME_VARIABLE"
15+
value = "some_value"
16+
target = ["production", "preview"]
17+
},
18+
{
19+
key = "ANOTHER_VARIABLE"
20+
value = "another_value"
21+
git_branch = "staging"
22+
target = ["preview"]
23+
},
24+
{
25+
key = "SENSITIVE_VARIABLE"
26+
value = "sensitive_value"
27+
target = ["production"]
28+
sensitive = true
29+
}
30+
]
31+
}

vercel/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func (p *vercelProvider) Resources(_ context.Context) []func() resource.Resource
6363
newProjectDeploymentRetentionResource,
6464
newProjectDomainResource,
6565
newProjectEnvironmentVariableResource,
66+
newProjectEnvironmentVariablesResource,
6667
newProjectResource,
6768
newSharedEnvironmentVariableResource,
6869
newTeamConfigResource,

vercel/resource_project.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ A Project groups deployments and custom domains. To deploy on Vercel, you need t
7676
7777
For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/overview).
7878
79-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the ` + "`environment` field" + `.
80-
At this time you cannot use a Vercel Project resource with in-line ` + "`environment` in conjunction with any `vercel_project_environment_variable`" + ` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
79+
~> Terraform currently provides a standalone Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and this Project resource with Environment Variables defined in-line via the ` + "`environment` field" + `.
80+
At this time you cannot use a Vercel Project resource with in-line ` + "`environment` in conjunction with any `vercel_project_environment_variables` or `vercel_project_environment_variable`" + ` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
8181
`,
8282
Attributes: map[string]schema.Attribute{
8383
"team_id": schema.StringAttribute{
@@ -1753,7 +1753,7 @@ func (r *projectResource) Update(ctx context.Context, req resource.UpdateRequest
17531753
}
17541754

17551755
if items != nil {
1756-
err = r.client.CreateEnvironmentVariables(
1756+
_, err = r.client.CreateEnvironmentVariables(
17571757
ctx,
17581758
client.CreateEnvironmentVariablesRequest{
17591759
ProjectID: plan.ID.ValueString(),

vercel/resource_project_environment_variable.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ A Project Environment Variable resource defines an Environment Variable on a Ver
6565
6666
For more detailed information, please see the [Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables).
6767
68-
~> Terraform currently provides both a standalone Project Environment Variable resource (a single Environment Variable), and a Project resource with Environment Variables defined in-line via the ` + "`environment` field" + `.
69-
At this time you cannot use a Vercel Project resource with in-line ` + "`environment` in conjunction with any `vercel_project_environment_variable`" + ` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
68+
~> Terraform currently provides this Project Environment Variable resource (a single Environment Variable), a Project Environment Variables resource (multiple Environment Variables), and a Project resource with Environment Variables defined in-line via the ` + "`environment` field" + `.
69+
At this time you cannot use a Vercel Project resource with in-line ` + "`environment` in conjunction with any `vercel_project_environment_variables` or `vercel_project_environment_variable`" + ` resources. Doing so will cause a conflict of settings and will overwrite Environment Variables.
7070
`,
7171
Attributes: map[string]schema.Attribute{
7272
"target": schema.SetAttribute{

0 commit comments

Comments
 (0)