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

Fix issue where deleted resources were not detected properly #9

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 1 commit into from
Feb 19, 2022
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: 2 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"
)

// Client is an API wrapper, providing a high-level interface to the Vercel API.
type Client struct {
token string
client *http.Client
Expand All @@ -23,6 +24,7 @@ func (c *Client) http() *http.Client {
return c.client
}

// New creates a new instace of Client for a given API token.
func New(token string) *Client {
return &Client{
token: token,
Expand Down
11 changes: 11 additions & 0 deletions client/deployment_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"
)

// DeploymentFile is a struct defining the required information about a singular file
// that should be used within a deployment.
type DeploymentFile struct {
File string `json:"file"`
Sha string `json:"sha"`
Size int `json:"size"`
}

// CreateDeploymentRequest defines the request the Vercel API expects in order to create a deployment.
type CreateDeploymentRequest struct {
Files []DeploymentFile `json:"files,omitempty"`
Functions map[string]interface{} `json:"functions,omitempty"`
Expand All @@ -34,6 +37,7 @@ type CreateDeploymentRequest struct {
Target string `json:"target,omitempty"`
}

// DeploymentResponse defines the response the Vercel API returns when a deployment is created or updated.
type DeploymentResponse struct {
Aliases []string `json:"alias"`
AliasError *struct {
Expand Down Expand Up @@ -66,10 +70,12 @@ type DeploymentResponse struct {
URL string `json:"url"`
}

// IsComplete is used to determine whether a deployment is still processing, or whether it is fully done.
func (dr *DeploymentResponse) IsComplete() bool {
return dr.AliasAssigned && dr.AliasError == nil
}

// DeploymentLogsURL provides a user friendly URL that links directly to the vercel UI for a particular deployment.
func (dr *DeploymentResponse) DeploymentLogsURL(projectID string) string {
teamSlug := dr.Creator.Username
if dr.Team != nil {
Expand All @@ -83,6 +89,7 @@ func (dr *DeploymentResponse) DeploymentLogsURL(projectID string) string {
)
}

// CheckForError checks through the various failure modes of a deployment to see if any were hit.
func (dr *DeploymentResponse) CheckForError(projectID string) error {
if dr.ReadyState == "CANCELED" {
return fmt.Errorf("deployment canceled")
Expand Down Expand Up @@ -116,16 +123,20 @@ func (dr *DeploymentResponse) CheckForError(projectID string) error {
return nil
}

// MissingFilesError is a sentinel error that indicates a deployment could not be created
// because additional files need to be uploaded first.
type MissingFilesError struct {
Code string `json:"code"`
Message string `json:"message"`
Missing []string `json:"missing"`
}

// Error gives the MissingFilesError a user friendly error message.
func (e MissingFilesError) Error() string {
return fmt.Sprintf("%s - %s", e.Code, e.Message)
}

// CreateDeployment creates a deployment within Vercel.
func (c *Client) CreateDeployment(ctx context.Context, request CreateDeploymentRequest, teamID string) (r DeploymentResponse, err error) {
request.Name = request.ProjectID // Name is ignored if project is specified
request.Build.Environment = request.Environment // Ensure they are both the same, as project environment variables are
Expand Down
1 change: 1 addition & 0 deletions client/deployment_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// GetDeployment retrieves information from Vercel about an existing Deployment.
func (c *Client) GetDeployment(ctx context.Context, deploymentID, teamID string) (r DeploymentResponse, err error) {
url := fmt.Sprintf("%s/v13/deployments/%s", c.baseURL, deploymentID)
if teamID != "" {
Expand Down
4 changes: 4 additions & 0 deletions client/environment_variable_upsert.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ import (
"strings"
)

// UpsertEnvironmentVariableRequest defines the information that needs to be passed to Vercel in order to
// create or update an environment variable.
type UpsertEnvironmentVariableRequest EnvironmentVariable

// UpsertEnvironmentVariable will either create a brand new environment variable if one does not exist, or will
// update an existing environment variable to the latest information.
func (c *Client) UpsertEnvironmentVariable(ctx context.Context, projectID, teamID string, request UpsertEnvironmentVariableRequest) error {
url := fmt.Sprintf("%s/v8/projects/%s/env", c.baseURL, projectID)
if teamID != "" {
Expand Down
1 change: 1 addition & 0 deletions client/environment_variables_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// DeleteEnvironmentVariable will remove an environment variable from Vercel.
func (c *Client) DeleteEnvironmentVariable(ctx context.Context, projectID, teamID, variableID string) error {
url := fmt.Sprintf("%s/v8/projects/%s/env/%s", c.baseURL, projectID, variableID)
if teamID != "" {
Expand Down
1 change: 1 addition & 0 deletions client/file_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// CreateFile will upload a file to Vercel so that it can be later used for a Deployment.
func (c *Client) CreateFile(ctx context.Context, filename, sha, content string) error {
req, err := http.NewRequestWithContext(
ctx,
Expand Down
5 changes: 5 additions & 0 deletions client/must_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package client

import "encoding/json"

// mustMarshal is a helper to remove unnecessary error checking when marshaling a Go
// struct to json. There are only a few instances where marshaling can fail, and they
// are around the shape of the data. e.g. if a struct contains a channel, then it cannot
// be marshaled. As our structs are known ahead of time and are all safe to marshal,
// this simplifies the error checking process.
func mustMarshal(v interface{}) []byte {
res, _ := json.Marshal(v)
return res
Expand Down
6 changes: 6 additions & 0 deletions client/project_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import (
"strings"
)

// GitRepository is the information Vercel requires and surfaces about which git provider and repository
// a project is linked with.
type GitRepository struct {
Type string `json:"type"`
Repo string `json:"repo"`
}

// EnvironmentVariable defines the information Vercel requires and surfaces about an environment variable
// that is associated with a project.
type EnvironmentVariable struct {
Key string `json:"key"`
Value string `json:"value"`
Expand All @@ -20,6 +24,7 @@ type EnvironmentVariable struct {
ID string `json:"id,omitempty"`
}

// CreateProjectRequest defines the information necessary to create a project.
type CreateProjectRequest struct {
Name string `json:"name"`
BuildCommand *string `json:"buildCommand"`
Expand All @@ -33,6 +38,7 @@ type CreateProjectRequest struct {
RootDirectory *string `json:"rootDirectory"`
}

// CreateProject will create a project within Vercel.
func (c *Client) CreateProject(ctx context.Context, teamID string, request CreateProjectRequest) (r ProjectResponse, err error) {
url := fmt.Sprintf("%s/v8/projects", c.baseURL)
if teamID != "" {
Expand Down
2 changes: 2 additions & 0 deletions client/project_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"
)

// DeleteProject deletes a project within Vercel. Note that there is no need to explicitly
// remove every environment variable, as these cease to exist when a project is removed.
func (c *Client) DeleteProject(ctx context.Context, projectID, teamID string) error {
url := fmt.Sprintf("%s/v8/projects/%s", c.baseURL, projectID)
if teamID != "" {
Expand Down
5 changes: 5 additions & 0 deletions client/project_domain_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ import (
"strings"
)

// CreateProjectDomainRequest defines the information necessary to create a project domain.
// A project domain is an association of a specific domain name to a project. These are typically
// used to assign a domain name to any production deployments, but can also be used to configure
// redirects, or to give specific git branches a domain name.
type CreateProjectDomainRequest struct {
Name string `json:"name"`
GitBranch string `json:"gitBranch,omitempty"`
Redirect string `json:"redirect,omitempty"`
RedirectStatusCode int64 `json:"redirectStatusCode,omitempty"`
}

// CreateProjectDomain creates a project domain within Vercel.
func (c *Client) CreateProjectDomain(ctx context.Context, projectID, teamID string, request CreateProjectDomainRequest) (r ProjectDomainResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s/domains", c.baseURL, projectID)
if teamID != "" {
Expand Down
1 change: 1 addition & 0 deletions client/project_domain_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// DeleteProjectDomain removes any association of a domain name with a Vercel project.
func (c *Client) DeleteProjectDomain(ctx context.Context, projectID, domain, teamID string) error {
url := fmt.Sprintf("%s/v8/projects/%s/domains/%s", c.baseURL, projectID, domain)
if teamID != "" {
Expand Down
3 changes: 3 additions & 0 deletions client/project_domain_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"
)

// ProjectDomainResponse defines the information that Vercel exposes about a domain that is
// associated with a vercel project.
type ProjectDomainResponse struct {
Name string `json:"name"`
ProjectID string `json:"projectId"`
Expand All @@ -15,6 +17,7 @@ type ProjectDomainResponse struct {
GitBranch *string `json:"gitBranch"`
}

// GetProjectDomain retrieves information about a project domain from Vercel.
func (c *Client) GetProjectDomain(ctx context.Context, projectID, domain, teamID string) (r ProjectDomainResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s/domains/%s", c.baseURL, projectID, domain)
if teamID != "" {
Expand Down
2 changes: 2 additions & 0 deletions client/project_domain_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (
"strings"
)

// UpdateProjectDomainRequest defines the information necessary to update a project domain.
type UpdateProjectDomainRequest struct {
GitBranch *string `json:"gitBranch"`
Redirect *string `json:"redirect"`
RedirectStatusCode *int64 `json:"redirectStatusCode"`
}

// UpdateProjectDomain updates an existing project domain within Vercel.
func (c *Client) UpdateProjectDomain(ctx context.Context, projectID, domain, teamID string, request UpdateProjectDomainRequest) (r ProjectDomainResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s/domains/%s", c.baseURL, projectID, domain)
if teamID != "" {
Expand Down
5 changes: 5 additions & 0 deletions client/project_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (
"strings"
)

// Repository defines the information about a projects git connection.
type Repository struct {
Type string
Repo string
}

// Repository is a helper method to convert the ProjectResponse Repository information into a more
// digestible format.
func (r *ProjectResponse) Repository() *Repository {
if r.Link == nil {
return nil
Expand All @@ -36,6 +39,7 @@ func (r *ProjectResponse) Repository() *Repository {
return nil
}

// ProjectResponse defines the information vercel returns about a project.
type ProjectResponse struct {
BuildCommand *string `json:"buildCommand"`
DevCommand *string `json:"devCommand"`
Expand All @@ -61,6 +65,7 @@ type ProjectResponse struct {
RootDirectory *string `json:"rootDirectory"`
}

// GetProject retrieves information about an existing project from vercel.
func (c *Client) GetProject(ctx context.Context, projectID, teamID string) (r ProjectResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s", c.baseURL, projectID)
if teamID != "" {
Expand Down
1 change: 1 addition & 0 deletions client/project_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// ListProjects lists the top 100 projects (no pagination) from within Vercel.
func (c *Client) ListProjects(ctx context.Context, teamID string) (r []ProjectResponse, err error) {
url := fmt.Sprintf("%s/v8/projects?limit=100", c.baseURL)
if teamID != "" {
Expand Down
7 changes: 7 additions & 0 deletions client/project_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import (
"strings"
)

// UpdateProjectRequest defines the possible fields that can be updated within a vercel project.
// note that the values are all pointers, with many containing `omitempty` for serialisation.
// This is because the Vercel API behaves in the following manner:
// - a provided field will be updated
// - setting the field to an empty value (e.g. '') will remove the setting for that field.
// - omitting the value entirely from the request will _not_ update the field.
type UpdateProjectRequest struct {
Name *string `json:"name,omitempty"`
BuildCommand *string `json:"buildCommand"`
Expand All @@ -18,6 +24,7 @@ type UpdateProjectRequest struct {
RootDirectory *string `json:"rootDirectory"`
}

// UpdateProject updates an existing projects configuration within vercel.
func (c *Client) UpdateProject(ctx context.Context, projectID, teamID string, request UpdateProjectRequest) (r ProjectResponse, err error) {
url := fmt.Sprintf("%s/v8/projects/%s", c.baseURL, projectID)
if teamID != "" {
Expand Down
7 changes: 7 additions & 0 deletions client/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@ import (
"net/http"
)

// APIError is an error type that exposes additional information about why an API request failed.
type APIError struct {
Code string `json:"code"`
Message string `json:"message"`
StatusCode int
RawMessage []byte
}

// Error provides a user friendly error message.
func (e APIError) Error() string {
return fmt.Sprintf("%s - %s", e.Code, e.Message)
}

// doRequest is a helper function for consistently requesting data from vercel.
// This manages:
// - Authorization via the Bearer token
// - Converting error responses into an inspectable type
// - Unmarshaling responses
func (c *Client) doRequest(req *http.Request, v interface{}) error {
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.token))
resp, err := c.http().Do(req)
Expand Down
3 changes: 3 additions & 0 deletions client/team_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,18 @@ import (
"strings"
)

// TeamCreateRequest defines the information needed to create a team within vercel.
type TeamCreateRequest struct {
Slug string `json:"slug"`
Name string `json:"name"`
}

// TeamResponse is the information returned by the vercel api when a team is created.
type TeamResponse struct {
ID string `json:"id"`
}

// CreateTeam creates a team within vercel.
func (c *Client) CreateTeam(ctx context.Context, request TeamCreateRequest) (r TeamResponse, err error) {
req, err := http.NewRequestWithContext(
ctx,
Expand Down
1 change: 1 addition & 0 deletions client/team_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// DeleteTeam deletes an existing team within vercel.
func (c *Client) DeleteTeam(ctx context.Context, teamID string) error {
req, err := http.NewRequestWithContext(
ctx,
Expand Down
1 change: 1 addition & 0 deletions client/team_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
)

// GetTeam returns information about an existing team within vercel.
func (c *Client) GetTeam(ctx context.Context, teamID, slug string) (r TeamResponse, err error) {
url := c.baseURL + "/v1/teams"
if teamID != "" {
Expand Down
2 changes: 2 additions & 0 deletions glob/glob.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
gitignore "github.com/sabhiram/go-gitignore"
)

// GetPaths is used to find all the files within a directory that do not match a specified
// set of ignore patterns.
func GetPaths(basePath string, ignorePatterns []string) ([]string, error) {
ignore := gitignore.CompileIgnoreLines(ignorePatterns...)

Expand Down
2 changes: 2 additions & 0 deletions glob/ignores.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ var defaultIgnores = []string{
".terraform*",
}

// GetIgnores is used to parse a .vercelignore file from a given directory, and
// combine the expected results with a default set of ignored files.
func GetIgnores(path string) ([]string, error) {
ignoreFilePath := filepath.Join(path, ".vercelignore")
ignoreFile, err := os.ReadFile(ignoreFilePath)
Expand Down
Loading