diff options
Diffstat (limited to 'cli/internal/client/cache.go')
| -rw-r--r-- | cli/internal/client/cache.go | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/cli/internal/client/cache.go b/cli/internal/client/cache.go deleted file mode 100644 index 11ad87a..0000000 --- a/cli/internal/client/cache.go +++ /dev/null @@ -1,167 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strings" - - "github.com/hashicorp/go-retryablehttp" - "github.com/vercel/turbo/cli/internal/ci" - "github.com/vercel/turbo/cli/internal/util" -) - -// PutArtifact uploads an artifact associated with a given hash string to the remote cache -func (c *APIClient) PutArtifact(hash string, artifactBody []byte, duration int, tag string) error { - if err := c.okToRequest(); err != nil { - return err - } - params := url.Values{} - c.addTeamParam(¶ms) - // only add a ? if it's actually needed (makes logging cleaner) - encoded := params.Encode() - if encoded != "" { - encoded = "?" + encoded - } - - requestURL := c.makeURL("/v8/artifacts/" + hash + encoded) - allowAuth := true - if c.usePreflight { - resp, latestRequestURL, err := c.doPreflight(requestURL, http.MethodPut, "Content-Type, x-artifact-duration, Authorization, User-Agent, x-artifact-tag") - if err != nil { - return fmt.Errorf("pre-flight request failed before trying to store in HTTP cache: %w", err) - } - requestURL = latestRequestURL - headers := resp.Header.Get("Access-Control-Allow-Headers") - allowAuth = strings.Contains(strings.ToLower(headers), strings.ToLower("Authorization")) - } - - req, err := retryablehttp.NewRequest(http.MethodPut, requestURL, artifactBody) - req.Header.Set("Content-Type", "application/octet-stream") - req.Header.Set("x-artifact-duration", fmt.Sprintf("%v", duration)) - if allowAuth { - req.Header.Set("Authorization", "Bearer "+c.token) - } - req.Header.Set("User-Agent", c.userAgent()) - if ci.IsCi() { - req.Header.Set("x-artifact-client-ci", ci.Constant()) - } - if tag != "" { - req.Header.Set("x-artifact-tag", tag) - } - if err != nil { - return fmt.Errorf("[WARNING] Invalid cache URL: %w", err) - } - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return fmt.Errorf("[ERROR] Failed to store files in HTTP cache: %w", err) - } - defer func() { _ = resp.Body.Close() }() - if resp.StatusCode == http.StatusForbidden { - return c.handle403(resp.Body) - } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("[ERROR] Failed to store files in HTTP cache: %s against URL %s", resp.Status, requestURL) - } - return nil -} - -// FetchArtifact attempts to retrieve the build artifact with the given hash from the remote cache -func (c *APIClient) FetchArtifact(hash string) (*http.Response, error) { - return c.getArtifact(hash, http.MethodGet) -} - -// ArtifactExists attempts to determine if the build artifact with the given hash exists in the Remote Caching server -func (c *APIClient) ArtifactExists(hash string) (*http.Response, error) { - return c.getArtifact(hash, http.MethodHead) -} - -// getArtifact attempts to retrieve the build artifact with the given hash from the remote cache -func (c *APIClient) getArtifact(hash string, httpMethod string) (*http.Response, error) { - if httpMethod != http.MethodHead && httpMethod != http.MethodGet { - return nil, fmt.Errorf("invalid httpMethod %v, expected GET or HEAD", httpMethod) - } - - if err := c.okToRequest(); err != nil { - return nil, err - } - params := url.Values{} - c.addTeamParam(¶ms) - // only add a ? if it's actually needed (makes logging cleaner) - encoded := params.Encode() - if encoded != "" { - encoded = "?" + encoded - } - - requestURL := c.makeURL("/v8/artifacts/" + hash + encoded) - allowAuth := true - if c.usePreflight { - resp, latestRequestURL, err := c.doPreflight(requestURL, http.MethodGet, "Authorization, User-Agent") - if err != nil { - return nil, fmt.Errorf("pre-flight request failed before trying to fetch files in HTTP cache: %w", err) - } - requestURL = latestRequestURL - headers := resp.Header.Get("Access-Control-Allow-Headers") - allowAuth = strings.Contains(strings.ToLower(headers), strings.ToLower("Authorization")) - } - - req, err := retryablehttp.NewRequest(httpMethod, requestURL, nil) - if allowAuth { - req.Header.Set("Authorization", "Bearer "+c.token) - } - req.Header.Set("User-Agent", c.userAgent()) - if err != nil { - return nil, fmt.Errorf("invalid cache URL: %w", err) - } - - resp, err := c.HTTPClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to fetch artifact: %v", err) - } else if resp.StatusCode == http.StatusForbidden { - err = c.handle403(resp.Body) - _ = resp.Body.Close() - return nil, err - } - return resp, nil -} - -func (c *APIClient) handle403(body io.Reader) error { - raw, err := ioutil.ReadAll(body) - if err != nil { - return fmt.Errorf("failed to read response %v", err) - } - apiError := &apiError{} - err = json.Unmarshal(raw, apiError) - if err != nil { - return fmt.Errorf("failed to read response (%v): %v", string(raw), err) - } - disabledErr, err := apiError.cacheDisabled() - if err != nil { - return err - } - return disabledErr -} - -type apiError struct { - Code string `json:"code"` - Message string `json:"message"` -} - -func (ae *apiError) cacheDisabled() (*util.CacheDisabledError, error) { - if strings.HasPrefix(ae.Code, "remote_caching_") { - statusString := ae.Code[len("remote_caching_"):] - status, err := util.CachingStatusFromString(statusString) - if err != nil { - return nil, err - } - return &util.CacheDisabledError{ - Status: status, - Message: ae.Message, - }, nil - } - return nil, fmt.Errorf("unknown status %v: %v", ae.Code, ae.Message) -} |
