Skip to content

Commit

Permalink
Update data sent to vercel for runs (vercel#4495)
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 authored and NicholasLYang committed Apr 21, 2023
1 parent 70a4f2a commit f2ac646
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 106 deletions.
2 changes: 2 additions & 0 deletions cli/integration_tests/single_package/run-summary.t
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ Check
[
"attempted",
"cached",
"command",
"endTime",
"exitCode",
"failed",
"repoPath",
"startTime",
"success"
]
Expand Down
6 changes: 5 additions & 1 deletion cli/internal/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ func optsFromArgs(args *turbostate.ParsedArgsFromRust) (*Opts, error) {

opts := getDefaultOptions()
// aliases := make(map[string]string)
scope.OptsFromArgs(&opts.scopeOpts, args)
if err := scope.OptsFromArgs(&opts.scopeOpts, args); err != nil {
return nil, err
}

// Cache flags
opts.clientOpts.Timeout = args.RemoteCacheTimeout
Expand Down Expand Up @@ -350,6 +352,7 @@ func (r *run) run(ctx gocontext.Context, targets []string) error {
startAt,
r.base.UI,
r.base.RepoRoot,
rs.Opts.scopeOpts.PackageInferenceRoot,
r.base.TurboVersion,
r.base.APIClient,
rs.Opts.runOpts,
Expand All @@ -361,6 +364,7 @@ func (r *run) run(ctx gocontext.Context, targets []string) error {
globalHashable.globalCacheKey,
globalHashable.pipeline,
),
rs.Opts.SynthesizeCommand(rs.Targets),
)

// Dry Run
Expand Down
32 changes: 32 additions & 0 deletions cli/internal/run/run_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package run

import (
"strings"

"github.com/vercel/turbo/cli/internal/cache"
"github.com/vercel/turbo/cli/internal/client"
"github.com/vercel/turbo/cli/internal/runcache"
Expand Down Expand Up @@ -45,6 +47,36 @@ type Opts struct {
scopeOpts scope.Opts
}

// SynthesizeCommand produces a command that produces an equivalent set of packages, tasks,
// and task arguments to what the current set of opts selects.
func (o *Opts) SynthesizeCommand(tasks []string) string {
cmd := "turbo run"
cmd += " " + strings.Join(tasks, " ")
for _, filterPattern := range o.scopeOpts.FilterPatterns {
cmd += " --filter=" + filterPattern
}
for _, filterPattern := range o.scopeOpts.LegacyFilter.AsFilterPatterns() {
cmd += " --filter=" + filterPattern
}
if o.runOpts.Parallel {
cmd += " --parallel"
}
if o.runOpts.ContinueOnError {
cmd += " --continue"
}
if o.runOpts.DryRun {
if o.runOpts.DryRunJSON {
cmd += " --dry=json"
} else {
cmd += " --dry"
}
}
if len(o.runOpts.PassThroughArgs) > 0 {
cmd += " -- " + strings.Join(o.runOpts.PassThroughArgs, " ")
}
return cmd
}

// getDefaultOptions returns the default set of Opts for every run
func getDefaultOptions() *Opts {
return &Opts{
Expand Down
107 changes: 107 additions & 0 deletions cli/internal/run/run_spec_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package run

import (
"testing"

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

func TestSynthesizeCommand(t *testing.T) {
testCases := []struct {
filterPatterns []string
legacyFilter scope.LegacyFilter
passThroughArgs []string
parallel bool
continueOnError bool
dryRun bool
dryRunJSON bool
tasks []string
expected string
}{
{
filterPatterns: []string{"my-app"},
tasks: []string{"build"},
expected: "turbo run build --filter=my-app",
},
{
filterPatterns: []string{"my-app"},
tasks: []string{"build"},
passThroughArgs: []string{"-v", "--foo=bar"},
expected: "turbo run build --filter=my-app -- -v --foo=bar",
},
{
legacyFilter: scope.LegacyFilter{
Entrypoints: []string{"my-app"},
SkipDependents: true,
},
tasks: []string{"build"},
passThroughArgs: []string{"-v", "--foo=bar"},
expected: "turbo run build --filter=my-app -- -v --foo=bar",
},
{
legacyFilter: scope.LegacyFilter{
Entrypoints: []string{"my-app"},
SkipDependents: true,
},
filterPatterns: []string{"other-app"},
tasks: []string{"build"},
passThroughArgs: []string{"-v", "--foo=bar"},
expected: "turbo run build --filter=other-app --filter=my-app -- -v --foo=bar",
},
{
legacyFilter: scope.LegacyFilter{
Entrypoints: []string{"my-app"},
IncludeDependencies: true,
Since: "some-ref",
},
filterPatterns: []string{"other-app"},
tasks: []string{"build"},
expected: "turbo run build --filter=other-app --filter=...my-app...[some-ref]...",
},
{
filterPatterns: []string{"my-app"},
tasks: []string{"build"},
parallel: true,
continueOnError: true,
expected: "turbo run build --filter=my-app --parallel --continue",
},
{
filterPatterns: []string{"my-app"},
tasks: []string{"build"},
dryRun: true,
expected: "turbo run build --filter=my-app --dry",
},
{
filterPatterns: []string{"my-app"},
tasks: []string{"build"},
dryRun: true,
dryRunJSON: true,
expected: "turbo run build --filter=my-app --dry=json",
},
}

for _, testCase := range testCases {
testCase := testCase
t.Run(testCase.expected, func(t *testing.T) {
o := Opts{
scopeOpts: scope.Opts{
FilterPatterns: testCase.filterPatterns,
LegacyFilter: testCase.legacyFilter,
},
runOpts: util.RunOpts{
PassThroughArgs: testCase.passThroughArgs,
Parallel: testCase.parallel,
ContinueOnError: testCase.continueOnError,
DryRun: testCase.dryRun,
DryRunJSON: testCase.dryRunJSON,
},
}
cmd := o.SynthesizeCommand(testCase.tasks)
if cmd != testCase.expected {
t.Errorf("SynthesizeCommand() got %v, want %v", cmd, testCase.expected)
}
})
}

}
39 changes: 26 additions & 13 deletions cli/internal/runsummary/execution_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/vercel/turbo/cli/internal/chrometracing"
"github.com/vercel/turbo/cli/internal/fs"
"github.com/vercel/turbo/cli/internal/turbopath"

"github.com/mitchellh/cli"
)
Expand Down Expand Up @@ -72,6 +73,10 @@ type TaskExecutionSummary struct {
exitCode *int // pointer so we can distinguish between 0 and unknown.
}

func (ts *TaskExecutionSummary) endTime() time.Time {
return ts.startAt.Add(ts.Duration)
}

// MarshalJSON munges the TaskExecutionSummary into a format we want
// We'll use an anonmyous, private struct for this, so it's not confusingly duplicated
func (ts *TaskExecutionSummary) MarshalJSON() ([]byte, error) {
Expand All @@ -82,7 +87,7 @@ func (ts *TaskExecutionSummary) MarshalJSON() ([]byte, error) {
ExitCode *int `json:"exitCode"`
}{
Start: ts.startAt.UnixMilli(),
End: ts.startAt.Add(ts.Duration).UnixMilli(),
End: ts.endTime().UnixMilli(),
Err: ts.err,
ExitCode: ts.exitCode,
}
Expand All @@ -108,10 +113,12 @@ type executionSummary struct {
profileFilename string

// These get serialized to JSON
success int // number of tasks that exited successfully (does not include cache hits)
failure int // number of tasks that exited with failure
cached int // number of tasks that had a cache hit
attempted int // number of tasks that started
command string // a synthesized turbo command to produce this invocation
repoPath turbopath.RelativeSystemPath // the (possibly empty) path from the turborepo root to where the command was run
success int // number of tasks that exited successfully (does not include cache hits)
failure int // number of tasks that exited with failure
cached int // number of tasks that had a cache hit
attempted int // number of tasks that started
startedAt time.Time
endedAt time.Time
exitCode int
Expand All @@ -121,14 +128,18 @@ type executionSummary struct {
// We'll use an anonmyous, private struct for this, so it's not confusingly duplicated.
func (es *executionSummary) MarshalJSON() ([]byte, error) {
serializable := struct {
Success int `json:"success"`
Failure int `json:"failed"`
Cached int `json:"cached"`
Attempted int `json:"attempted"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
ExitCode int `json:"exitCode"`
Command string `json:"command"`
RepoPath string `json:"repoPath"`
Success int `json:"success"`
Failure int `json:"failed"`
Cached int `json:"cached"`
Attempted int `json:"attempted"`
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
ExitCode int `json:"exitCode"`
}{
Command: es.command,
RepoPath: es.repoPath.ToString(),
StartTime: es.startedAt.UnixMilli(),
EndTime: es.endedAt.UnixMilli(),
Success: es.success,
Expand All @@ -142,12 +153,14 @@ func (es *executionSummary) MarshalJSON() ([]byte, error) {
}

// newExecutionSummary creates a executionSummary instance to track events in a `turbo run`.`
func newExecutionSummary(start time.Time, tracingProfile string) *executionSummary {
func newExecutionSummary(command string, repoPath turbopath.RelativeSystemPath, start time.Time, tracingProfile string) *executionSummary {
if tracingProfile != "" {
chrometracing.EnableTracing()
}

return &executionSummary{
command: command,
repoPath: repoPath,
success: 0,
failure: 0,
cached: 0,
Expand Down

0 comments on commit f2ac646

Please sign in to comment.