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

Support individual environment resources #58

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
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
## Requirements

- [Terraform](https://www.terraform.io/downloads.html) 1.1 or higher
- [Go](https://golang.org/doc/install) 1.17 (to build the provider plugin)
- [Go](https://golang.org/doc/install) 1.19 (to build the provider plugin)
- [Task](https://taskfile.dev) v3 (to run Taskfile commands)

## Building The Provider
Expand All @@ -19,7 +19,7 @@ $ task build

## Developing the Provider

If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.17+ is _required_).
If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.19+ is _required_).

To compile the provider, run `task build`. This will build the provider and put the provider binary in the repository root.

Expand All @@ -41,7 +41,6 @@ The acceptance tests require a few environment variables to be set:
* `VERCEL_API_TOKEN` - this can be generated [here](https://vercel.com/account/tokens)
* `VERCEL_TERRAFORM_TESTING_TEAM` - a Vercel team_id where resources can be created and destroyed
* `VERCEL_TERRAFORM_TESTING_GITHUB_REPO` - a GitHub repository in the form 'org/repo' that can be used to trigger deployments
* `VERCEL_TERRAFORM_TESTING_GITLAB_REPO` - a GitLab repository in the form 'namespace/repo' that can be used to trigger deployments
* `VERCEL_TERRAFORM_TESTING_BITBUCKET_REPO` - a Bitbucket repository in the form 'project/repo' that can be used to trigger deployments

```sh
Expand All @@ -51,7 +50,7 @@ $ task test
In order to run the tests with extra debugging context, prefix with `TF_LOG` (see the [terraform documentation](https://www.terraform.io/docs/internals/debugging.html) for details).

```sh
$ TF_LOG=trace task test
$ TF_LOG=INFO task test
```

To run a specific set of tests, use the `-run` flag and specify a regex pattern matching the test names.
Expand Down
3 changes: 3 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ tasks:
desc: "Install the tfplugindocs tool"
cmds:
- go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs@v0.7.0
status:
- which staticcheck

docs:
desc: "Update the docs generated from description fields"
Expand All @@ -37,6 +39,7 @@ tasks:
- "vercel/**/*.go"
- "main.go"
- "examples/**/*.tf"
- "examples/**/*.sh"
generates:
- docs/**/*.md

Expand Down
2 changes: 1 addition & 1 deletion client/deployment_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (e MissingFilesError) Error() string {
}

func (c *Client) getGitSource(ctx context.Context, projectID, ref, teamID string) (gs gitSource, err error) {
project, err := c.GetProject(ctx, projectID, teamID)
project, err := c.GetProject(ctx, projectID, teamID, false)
if err != nil {
return gs, fmt.Errorf("error getting project: %w", err)
}
Expand Down
49 changes: 49 additions & 0 deletions client/environment_variable_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package client

import (
"context"
"fmt"
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-log/tflog"
)

// CreateEnvironmentVariableRequest defines the information that needs to be passed to Vercel in order to
// create an environment variable.
type CreateEnvironmentVariableRequest struct {
Key string `json:"key"`
Value string `json:"value"`
Target []string `json:"target"`
GitBranch *string `json:"gitBranch,omitempty"`
Type string `json:"type"`
ProjectID string `json:"-"`
TeamID string `json:"-"`
}

// CreateEnvironmentVariable will create a brand new environment variable if one does not exist.
func (c *Client) CreateEnvironmentVariable(ctx context.Context, request CreateEnvironmentVariableRequest) (e EnvironmentVariable, err error) {
url := fmt.Sprintf("%s/v9/projects/%s/env", c.baseURL, request.ProjectID)
if request.TeamID != "" {
url = fmt.Sprintf("%s?teamId=%s", url, request.TeamID)
}
payload := string(mustMarshal(request))
req, err := http.NewRequestWithContext(
ctx,
"POST",
url,
strings.NewReader(payload),
)
if err != nil {
return e, err
}

tflog.Trace(ctx, "creating environment variable", map[string]interface{}{
"url": url,
"payload": payload,
})
err = c.doRequest(req, &e)
// The API response returns an encrypted environment variable, but we want to return the decrypted version.
e.Value = request.Value
return e, err
}
50 changes: 50 additions & 0 deletions client/environment_variable_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package client

import (
"context"
"fmt"
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-log/tflog"
)

// UpdateEnvironmentVariableRequest defines the information that needs to be passed to Vercel in order to
// update an environment variable.
type UpdateEnvironmentVariableRequest struct {
Key string `json:"key"`
Value string `json:"value"`
Target []string `json:"target"`
GitBranch *string `json:"gitBranch,omitempty"`
Type string `json:"type"`
ProjectID string `json:"-"`
TeamID string `json:"-"`
EnvID string `json:"-"`
}

// UpdateEnvironmentVariable will update an existing environment variable to the latest information.
func (c *Client) UpdateEnvironmentVariable(ctx context.Context, request UpdateEnvironmentVariableRequest) (e EnvironmentVariable, err error) {
url := fmt.Sprintf("%s/v9/projects/%s/env/%s", c.baseURL, request.ProjectID, request.EnvID)
if request.TeamID != "" {
url = fmt.Sprintf("%s?teamId=%s", url, request.TeamID)
}
payload := string(mustMarshal(request))
req, err := http.NewRequestWithContext(
ctx,
"PATCH",
url,
strings.NewReader(payload),
)
if err != nil {
return e, err
}

tflog.Trace(ctx, "updating environment variable", map[string]interface{}{
"url": url,
"payload": payload,
})
err = c.doRequest(req, &e)
// The API response returns an encrypted environment variable, but we want to return the decrypted version.
e.Value = request.Value
return e, err
}
39 changes: 0 additions & 39 deletions client/environment_variable_upsert.go

This file was deleted.

24 changes: 23 additions & 1 deletion client/environment_variables_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,31 @@ func (c *Client) getEnvironmentVariables(ctx context.Context, projectID, teamID
envResponse := struct {
Env []EnvironmentVariable `json:"envs"`
}{}
tflog.Trace(ctx, "getting environment variable", map[string]interface{}{
tflog.Trace(ctx, "getting environment variables", map[string]interface{}{
"url": url,
})
err = c.doRequest(req, &envResponse)
return envResponse.Env, err
}

func (c *Client) GetEnvironmentVariable(ctx context.Context, projectID, teamID, envID string) (e EnvironmentVariable, err error) {
url := fmt.Sprintf("%s/v1/projects/%s/env/%s", c.baseURL, projectID, envID)
if teamID != "" {
url = fmt.Sprintf("%s?teamId=%s", url, teamID)
}
req, err := http.NewRequestWithContext(
ctx,
"GET",
url,
nil,
)
if err != nil {
return e, err
}

tflog.Trace(ctx, "getting environment variable", map[string]interface{}{
"url": url,
})
err = c.doRequest(req, &e)
return e, err
}
20 changes: 13 additions & 7 deletions client/project_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type ProjectResponse struct {
}

// GetProject retrieves information about an existing project from Vercel.
func (c *Client) GetProject(ctx context.Context, projectID, teamID string) (r ProjectResponse, err error) {
func (c *Client) GetProject(ctx context.Context, projectID, teamID string, shouldFetchEnvironmentVariables bool) (r ProjectResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s", c.baseURL, projectID)
if teamID != "" {
url = fmt.Sprintf("%s?teamId=%s", url, teamID)
Expand All @@ -85,17 +85,23 @@ func (c *Client) GetProject(ctx context.Context, projectID, teamID string) (r Pr
return r, err
}
tflog.Trace(ctx, "getting project", map[string]interface{}{
"url": url,
"url": url,
"shouldFetchEnvironment": shouldFetchEnvironmentVariables,
})
err = c.doRequest(req, &r)
if err != nil {
return r, err
return r, fmt.Errorf("unable to get project: %w", err)
}

env, err := c.getEnvironmentVariables(ctx, projectID, teamID)
if err != nil {
return r, fmt.Errorf("error getting environment variables for project: %w", err)
if shouldFetchEnvironmentVariables {
r.EnvironmentVariables, err = c.getEnvironmentVariables(ctx, projectID, teamID)
if err != nil {
return r, fmt.Errorf("error getting environment variables for project: %w", err)
}
} else {
// The get project endpoint returns environment variables, but returns them fully
// encrypted. This isn't useful, so we just remove them.
r.EnvironmentVariables = nil
}
r.EnvironmentVariables = env
return r, err
}
33 changes: 11 additions & 22 deletions docs/resources/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ description: |-
Provides a Project resource.
A Project groups deployments and custom domains. To deploy on Vercel, you need to create a Project.
For more detailed information, please see the Vercel documentation https://vercel.com/docs/concepts/projects/overview.
~> 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.
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.
---

# vercel_project (Resource)
Expand All @@ -16,6 +18,9 @@ A Project groups deployments and custom domains. To deploy on Vercel, you need t

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

~> 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.
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.

## Example Usage

```terraform
Expand All @@ -26,14 +31,6 @@ resource "vercel_project" "with_git" {
name = "example-project-with-git"
framework = "nextjs"

environment = [
{
key = "bar"
value = "baz"
target = ["preview"]
}
]

git_repository = {
type = "github"
repo = "vercel/some-repo"
Expand All @@ -46,14 +43,6 @@ resource "vercel_project" "with_git" {
resource "vercel_project" "example" {
name = "example-project"
framework = "nextjs"

environment = [
{
key = "bar"
value = "baz"
target = ["preview", "production"]
}
]
}
```

Expand All @@ -68,7 +57,7 @@ resource "vercel_project" "example" {

- `build_command` (String) The build command for this project. If omitted, this value will be automatically detected.
- `dev_command` (String) The dev command for this project. If omitted, this value will be automatically detected.
- `environment` (Attributes Set) A set of environment variables that should be configured for the project. (see [below for nested schema](#nestedatt--environment))
- `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.
- `git_repository` (Attributes) The Git Repository that will be connected to the project. When this is defined, any pushes to the specified connected Git Repository will be automatically deployed. This requires the corresponding Vercel for [Github](https://vercel.com/docs/concepts/git/vercel-for-github), [Gitlab](https://vercel.com/docs/concepts/git/vercel-for-gitlab) or [Bitbucket](https://vercel.com/docs/concepts/git/vercel-for-bitbucket) plugins to be installed. (see [below for nested schema](#nestedatt--git_repository))
- `ignore_command` (String) When a commit is pushed to the Git repository that is connected with your Project, its SHA will determine if a new Build has to be issued. If the SHA was deployed before, no new Build will be issued. You can customize this behavior with a command that exits with code 1 (new Build needed) or code 0.
Expand All @@ -88,11 +77,11 @@ resource "vercel_project" "example" {

Optional:

- `git_branch` (String) The git branch of the environment variable.
- `id` (String) The ID of the environment variable
- `key` (String) The name of the environment variable.
- `target` (Set of String) The environments that the environment variable should be present on. Valid targets are either `production`, `preview`, or `development`.
- `value` (String, Sensitive) The value of the environment variable.
- `git_branch` (String) The git branch of the Environment Variable.
- `id` (String) The ID of the Environment Variable.
- `key` (String) The name of the Environment Variable.
- `target` (Set of String) The environments that the Environment Variable should be present on. Valid targets are either `production`, `preview`, or `development`.
- `value` (String, Sensitive) The value of the Environment Variable.


<a id="nestedatt--git_repository"></a>
Expand Down
Loading