-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Send run summary to API #4250
Send run summary to API #4250
Changes from 12 commits
8a34c7d
86f1645
45308c3
ab8e511
59a1d06
ee8a1b0
4547ed4
b106c8a
df45d35
1e33d10
5adaa68
6b326da
6dee6d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"crypto/x509" | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"net/url" | ||
"runtime" | ||
|
@@ -15,6 +16,7 @@ import ( | |
|
||
"github.com/hashicorp/go-hclog" | ||
"github.com/hashicorp/go-retryablehttp" | ||
"github.com/vercel/turbo/cli/internal/ci" | ||
) | ||
|
||
// APIClient is the main interface for making network requests to Vercel | ||
|
@@ -211,3 +213,97 @@ func (c *APIClient) addTeamParam(params *url.Values) { | |
params.Add("slug", c.teamSlug) | ||
} | ||
} | ||
|
||
// JSONPatch sends a byte array (json.marshalled payload) to a given endpoint with PATCH | ||
func (c *APIClient) JSONPatch(endpoint string, body []byte) ([]byte, error) { | ||
resp, err := c.request(endpoint, http.MethodPatch, body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rawResponse, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read response %v", err) | ||
} | ||
if resp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("%s", string(rawResponse)) | ||
} | ||
|
||
return rawResponse, nil | ||
} | ||
|
||
// JSONPost sends a byte array (json.marshalled payload) to a given endpoint with POST | ||
func (c *APIClient) JSONPost(endpoint string, body []byte) ([]byte, error) { | ||
resp, err := c.request(endpoint, http.MethodPost, body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rawResponse, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read response %v", err) | ||
} | ||
|
||
// For non 200/201 status codes, return the response body as an error | ||
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { | ||
return nil, fmt.Errorf("%s", string(rawResponse)) | ||
} | ||
|
||
return rawResponse, nil | ||
} | ||
|
||
func (c *APIClient) request(endpoint string, method string, body []byte) (*http.Response, error) { | ||
if err := c.okToRequest(); err != nil { | ||
return nil, err | ||
} | ||
|
||
params := url.Values{} | ||
c.addTeamParam(¶ms) | ||
encoded := params.Encode() | ||
if encoded != "" { | ||
encoded = "?" + encoded | ||
} | ||
|
||
requestURL := c.makeURL(endpoint + encoded) | ||
|
||
allowAuth := false | ||
if c.usePreflight { | ||
resp, latestRequestURL, err := c.doPreflight(requestURL, method, "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(method, requestURL, body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Set headers | ||
req.Header.Set("Content-Type", "application/json") | ||
req.Header.Set("User-Agent", c.userAgent()) | ||
|
||
if allowAuth { | ||
req.Header.Set("Authorization", "Bearer "+c.token) | ||
} | ||
|
||
if ci.IsCi() { | ||
req.Header.Set("x-artifact-client-ci", ci.Constant()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know headers are case-insensitive but we should go all-camel or no-camel 🐫 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I think there's more work to be done in the ApiClient, but since this is the existing code, I'll keep it as-is |
||
} | ||
|
||
resp, err := c.HTTPClient.Do(req) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// If there isn't a response, something else probably went wrong | ||
if resp == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems ok, we just need to make sure we don't end up getting 204 No Content back from a request There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, Ideally we should just be checking for 2xx, not specifically 200/201 , but also going to defer this since I've just used existing code and I don't want to affect what's going on |
||
return nil, fmt.Errorf("response from %s is nil, something went wrong", requestURL) | ||
} | ||
|
||
return resp, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,4 +85,6 @@ type runOpts struct { | |
|
||
// Whether turbo should create a run summary | ||
summarize bool | ||
|
||
experimentalSpaceID string | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth renaming this, as I was expecting https://jsonpatch.com/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you have a better name? I considered just
Post
andPatch
, but since there are other methods here that use,application/octect-stream
for example, I wanted to be clear that I'm not attempting to co-opt.