Skip to content

Commit

Permalink
Update data sent to vercel for runs
Browse files Browse the repository at this point in the history
- Add context and command when starting a Run
- Update data sent for Tasks
- Fix PATCH endpoint to mark Run as done
- Improve error propagation
  • Loading branch information
mehulkar committed Apr 7, 2023
1 parent 46bba2e commit feda5d0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 16 deletions.
35 changes: 25 additions & 10 deletions cli/internal/runsummary/run_summary.go
Expand Up @@ -26,6 +26,7 @@ const MissingFrameworkLabel = "<NO FRAMEWORK DETECTED>"

const runSummarySchemaVersion = "0"
const runsEndpoint = "/v0/spaces/%s/runs"
const runsPatchEndpoint = "/v0/spaces/%s/runs/%s"
const tasksEndpoint = "/v0/spaces/%s/runs/%s/tasks"

type runType int
Expand Down Expand Up @@ -144,8 +145,11 @@ func (rsm *Meta) Close(exitCode int, workspaceInfos workspace.Catalog) error {

if rsm.shouldSave {
if rsm.spaceID != "" && rsm.apiClient.IsLinked() {
if err := rsm.record(); err != nil {
rsm.ui.Warn(fmt.Sprintf("Error recording Run to Vercel: %v", err))
if errs := rsm.record(); len(errs) > 0 {
rsm.ui.Warn("Errors recording run to Vercel")
for _, err := range errs {
rsm.ui.Warn(fmt.Sprintf("%v", err))
}
}
}
}
Expand Down Expand Up @@ -207,23 +211,25 @@ func (rsm *Meta) record() []error {
payload := newVercelRunCreatePayload(rsm.RunSummary)
if startPayload, err := json.Marshal(payload); err == nil {
if resp, err := rsm.apiClient.JSONPost(runsURL, startPayload); err != nil {
errs = append(errs, err)
errs = append(errs, fmt.Errorf("Failed to POST to /run: %v", err))
} else {
vercelRunResponse := &vercelRunResponse{}
if err := json.Unmarshal(resp, vercelRunResponse); err != nil {
errs = append(errs, err)
errs = append(errs, fmt.Errorf("Failed to unmarshal response: %v", err))
} else {

runID = vercelRunResponse.ID

}
}
}

if runID != "" {
rsm.postTaskSummaries(runID)

if donePayload, err := json.Marshal(newVercelDonePayload(rsm.RunSummary)); err == nil {
if _, err := rsm.apiClient.JSONPatch(runsURL, donePayload); err != nil {
errs = append(errs, err)
patchURL := fmt.Sprintf(runsPatchEndpoint, rsm.spaceID, runID)
if _, err := rsm.apiClient.JSONPatch(patchURL, donePayload); err != nil {
errs = append(errs, fmt.Errorf("Failed to post PATCH: %s", err))
}
}
}
Expand All @@ -235,7 +241,8 @@ func (rsm *Meta) record() []error {
return nil
}

func (rsm *Meta) postTaskSummaries(runID string) {
func (rsm *Meta) postTaskSummaries(runID string) []error {
errs := []error{}
// We make at most 8 requests at a time.
maxParallelRequests := 8
taskSummaries := rsm.RunSummary.Tasks
Expand All @@ -256,9 +263,11 @@ func (rsm *Meta) postTaskSummaries(runID string) {
defer wg.Done()
for index := range queue {
task := taskSummaries[index]
if taskPayload, err := json.Marshal(task); err == nil {
payload := newVercelTaskPayload(task)
if taskPayload, err := json.Marshal(payload); err == nil {

if _, err := rsm.apiClient.JSONPost(taskURL, taskPayload); err != nil {
rsm.ui.Warn(fmt.Sprintf("Eror uploading summary of %s", task.TaskID))
errs = append(errs, fmt.Errorf("Eror uploading summary of %s", task.TaskID))
}
}
}
Expand All @@ -270,4 +279,10 @@ func (rsm *Meta) postTaskSummaries(runID string) {
}
close(queue)
wg.Wait()

if len(errs) > 0 {
return errs
}

return nil
}
89 changes: 83 additions & 6 deletions cli/internal/runsummary/vercel.go
@@ -1,5 +1,13 @@
package runsummary

import (
"fmt"
"strings"

"github.com/vercel/turbo/cli/internal/ci"
"github.com/vercel/turbo/cli/internal/util"
)

type vercelRunResponse struct {
ID string
}
Expand All @@ -22,28 +30,97 @@ type vercelRunPayload struct {

// ExitCode is the exit code for the full run
ExitCode int `json:"exitCode,omitempty"`

// The command that kicked off the turbo run
Command string `json:"command,omitempty"`

Context string `json:"context,omitempy"`

// TODO: we need to add these in
// originationUser string
// gitBranch string
// gitSha string
// context string
// command string
}

type vercelCacheStatus struct {
Status string `json:"status,omitempty"`
Source string `json:"source,omitempty"`
}

type vercelTask struct {
// id string
// log string
// TODO: add in command

Key string `json:"key,omitempty"`
Name string `json:"name,omitempty"`
Workspace string `json:"workspace,omitempty"`
Hash string `json:"hash,omitempty"`
StartTime int `json:"startTime,omitempty"`
EndTime int `json:"endTime,omitempty"`
Cache vercelCacheStatus `json:"cache,omitempty"`
ExitCode int `json:"exitCode,omitempty"`
Dependencies []string `json:"dependencies,omitempty"`
Dependents []string `json:"dependents,omitempty"`
}

func newVercelRunCreatePayload(runsummary *RunSummary) *vercelRunPayload {
startTime := int(runsummary.ExecutionSummary.startedAt.UnixMilli())
startTime := runsummary.ExecutionSummary.startedAt.UnixMilli()
taskNames := make(util.Set, len(runsummary.Tasks))
for _, task := range runsummary.Tasks {
taskNames.Add(task.Task)
}
return &vercelRunPayload{
StartTime: startTime,
Status: "started",
StartTime: int(startTime),
Status: "running",
Command: fmt.Sprintf("turbo run %s", strings.Join(taskNames.UnsafeListOfStrings(), " ")),
Type: "TURBO",
Context: getContext(),
}
}

func getContext() string {
name := ci.Constant()
if name == "" {
return "LOCAL"
}

return name

}

func newVercelDonePayload(runsummary *RunSummary) *vercelRunPayload {
endTime := int(runsummary.ExecutionSummary.endedAt.UnixMilli())
endTime := runsummary.ExecutionSummary.endedAt.UnixMilli()
return &vercelRunPayload{
Status: "completed",
EndTime: endTime,
EndTime: int(endTime),
ExitCode: runsummary.ExecutionSummary.exitCode,
}
}

func newVercelTaskPayload(taskSummary *TaskSummary) *vercelTask {
hit := taskSummary.CacheState.Local || taskSummary.CacheState.Remote
status := "MISS"
var source string
if hit {
source = "REMOTE"
status = "HIT"
}

return &vercelTask{
Key: taskSummary.TaskID,
Name: taskSummary.Task,
Workspace: taskSummary.Package,
Hash: taskSummary.Hash,
StartTime: int(taskSummary.Execution.startAt.UnixMilli()),
EndTime: int(taskSummary.Execution.startAt.Add(taskSummary.Execution.Duration).UnixMilli()),
Cache: vercelCacheStatus{
Status: status,
Source: source,
},
ExitCode: *taskSummary.Execution.exitCode,
Dependencies: taskSummary.Dependencies,
Dependents: taskSummary.Dependents,
}
}

0 comments on commit feda5d0

Please sign in to comment.