aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/cli/internal/client/cache.go
diff options
context:
space:
mode:
Diffstat (limited to 'cli/internal/client/cache.go')
-rw-r--r--cli/internal/client/cache.go167
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(&params)
- // 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(&params)
- // 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)
-}