Skip to content
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

Include logs when posting task summary #4642

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/internal/run/dry_run.go
Expand Up @@ -86,7 +86,7 @@ func DryRun(

// The exitCode isn't really used by the Run Summary Close() method for dry runs
// but we pass in a successful value to match Real Runs.
return summary.Close(0, g.WorkspaceInfos)
return summary.Close(ctx, 0, g.WorkspaceInfos)
}

func populateCacheState(turboCache cache.Cache, taskSummaries []*runsummary.TaskSummary) {
Expand Down
2 changes: 1 addition & 1 deletion cli/internal/run/real_run.go
Expand Up @@ -172,7 +172,7 @@ func RealRun(
}
}

if err := runSummary.Close(exitCode, g.WorkspaceInfos); err != nil {
if err := runSummary.Close(ctx, exitCode, g.WorkspaceInfos); err != nil {
// We don't need to throw an error, but we can warn on this.
// Note: this method doesn't actually return an error for Real Runs at the time of writing.
base.UI.Info(fmt.Sprintf("Failed to close Run Summary %v", err))
Expand Down
21 changes: 17 additions & 4 deletions cli/internal/runsummary/run_summary.go
Expand Up @@ -2,6 +2,7 @@
package runsummary

import (
"context"
"encoding/json"
"fmt"
"path/filepath"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/mitchellh/cli"
"github.com/segmentio/ksuid"
"github.com/vercel/turbo/cli/internal/client"
"github.com/vercel/turbo/cli/internal/spinner"
"github.com/vercel/turbo/cli/internal/turbopath"
"github.com/vercel/turbo/cli/internal/util"
"github.com/vercel/turbo/cli/internal/workspace"
Expand Down Expand Up @@ -124,7 +126,7 @@ func (rsm *Meta) getPath() turbopath.AbsoluteSystemPath {
}

// Close wraps up the RunSummary at the end of a `turbo run`.
func (rsm *Meta) Close(exitCode int, workspaceInfos workspace.Catalog) error {
func (rsm *Meta) Close(ctx context.Context, exitCode int, workspaceInfos workspace.Catalog) error {
if rsm.runType == runTypeDryJSON || rsm.runType == runTypeDryText {
return rsm.closeDryRun(workspaceInfos)
}
Expand Down Expand Up @@ -161,8 +163,19 @@ func (rsm *Meta) Close(exitCode int, workspaceInfos workspace.Catalog) error {
return nil
}

url, errs := rsm.record()
// Wrap the record function so we can hoist out url/errors but keep
// the function signature/type the spinner.WaitFor expects.
var url string
var errs []error
record := func() {
url, errs = rsm.record()
}

func() {
_ = spinner.WaitFor(ctx, record, rsm.ui, "...sending run summary...", 1000*time.Millisecond)
}()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm using this correctly, but would appreciate another look


// After the spinner is done
if len(errs) > 0 {
rsm.ui.Warn("Errors recording run to Spaces")
for _, err := range errs {
Expand Down Expand Up @@ -234,7 +247,7 @@ func (rsm *Meta) record() (string, []error) {
payload := rsm.newSpacesRunCreatePayload()
if startPayload, err := json.Marshal(payload); err == nil {
if resp, err := rsm.apiClient.JSONPost(createRunEndpoint, startPayload); err != nil {
errs = append(errs, err)
errs = append(errs, fmt.Errorf("POST %s: %w", createRunEndpoint, err))
} else {
if err := json.Unmarshal(resp, response); err != nil {
errs = append(errs, fmt.Errorf("Error unmarshaling response: %w", err))
Expand All @@ -250,7 +263,7 @@ func (rsm *Meta) record() (string, []error) {
if donePayload, err := json.Marshal(newSpacesDonePayload(rsm.RunSummary)); err == nil {
patchURL := fmt.Sprintf(runsPatchEndpoint, rsm.spaceID, response.ID)
if _, err := rsm.apiClient.JSONPatch(patchURL, donePayload); err != nil {
errs = append(errs, fmt.Errorf("Error marking run as done: %w", err))
errs = append(errs, fmt.Errorf("PATCH %s: %w", patchURL, err))
}
}
}
Expand Down
34 changes: 10 additions & 24 deletions cli/internal/runsummary/spaces.go
Expand Up @@ -11,30 +11,14 @@ type spacesRunResponse struct {
}

type spacesRunPayload struct {
// StartTime is when this run was started
StartTime int64 `json:"startTime,omitempty"`

// EndTime is when this run ended. We will never be submitting start and endtime at the same time.
EndTime int64 `json:"endTime,omitempty"`

// Status is
Status string `json:"status,omitempty"`

// Type should be hardcoded to TURBO
Type string `json:"type,omitempty"`

// 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"`

// RepositoryPath is the relative directory from the turborepo root to where
// the command was invoked.
RepositoryPath string `json:"repositoryPath,omitempty"`

// Context is the host on which this Run was executed (e.g. Github Action, Vercel, etc)
Context string `json:"context,omitempty"`
StartTime int64 `json:"startTime,omitempty"` // when the run was started
EndTime int64 `json:"endTime,omitempty"` // when the run ended. we should never submit start and end at the same time.
Status string `json:"status,omitempty"` // Status is "running" or "completed"
Type string `json:"type,omitempty"` // hardcoded to "TURBO"
ExitCode int `json:"exitCode,omitempty"` // exit code for the full run
Command string `json:"command,omitempty"` // the thing that kicked off the turbo run
RepositoryPath string `json:"repositoryPath,omitempty"` // where the command was invoked from
Context string `json:"context,omitempty"` // the host on which this Run was executed (e.g. Github Action, Vercel, etc)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no changes, just tightened it up by putting comments on the same line


// TODO: we need to add these in
// originationUser string
Expand Down Expand Up @@ -64,6 +48,7 @@ type spacesTask struct {
ExitCode int `json:"exitCode,omitempty"`
Dependencies []string `json:"dependencies,omitempty"`
Dependents []string `json:"dependents,omitempty"`
Logs string `json:"log"`
}

func (rsm *Meta) newSpacesRunCreatePayload() *spacesRunPayload {
Expand Down Expand Up @@ -106,5 +91,6 @@ func newSpacesTaskPayload(taskSummary *TaskSummary) *spacesTask {
ExitCode: *taskSummary.Execution.exitCode,
Dependencies: taskSummary.Dependencies,
Dependents: taskSummary.Dependents,
Logs: string(taskSummary.GetLogs()),
}
}
11 changes: 11 additions & 0 deletions cli/internal/runsummary/task_summary.go
@@ -1,6 +1,8 @@
package runsummary

import (
"os"

"github.com/vercel/turbo/cli/internal/cache"
"github.com/vercel/turbo/cli/internal/fs"
"github.com/vercel/turbo/cli/internal/turbopath"
Expand Down Expand Up @@ -76,6 +78,15 @@ type TaskSummary struct {
Execution *TaskExecutionSummary `json:"execution,omitempty"` // omit when it's not set
}

// GetLogs reads the Logfile and returns the data
func (ts *TaskSummary) GetLogs() []byte {
bytes, err := os.ReadFile(ts.LogFile)
if err != nil {
return []byte{}
}
return bytes
}

// TaskEnvVarSummary contains the environment variables that impacted a task's hash
type TaskEnvVarSummary struct {
Configured []string `json:"configured"`
Expand Down