Skip to content

Commit

Permalink
Make Run Summaries work for Single Package repos (vercel#4387)
Browse files Browse the repository at this point in the history
Instead of maintaining separate structs for the Single Package case,
this PR mutates the RunSummary when it's formatting it for use.
Since `isSinglePackage` doesn't change during a run, we don't need
to worry about operating on an Run Summary in different states.
  • Loading branch information
mehulkar authored Mar 31, 2023
1 parent ec70b15 commit 52dfda9
Show file tree
Hide file tree
Showing 12 changed files with 242 additions and 106 deletions.
3 changes: 0 additions & 3 deletions cli/integration_tests/basic_monorepo/run_summary/get-build.sh

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ Setup
[0-9]+ (re)

# Extract some task-specific summaries from each
$ FIRST_APP_BUILD=$("$TESTDIR/get-build.sh" "$FIRST" "my-app")
$ FIRST_UTIL_BUILD=$("$TESTDIR/get-build.sh" "$FIRST" "util")
$ source "$TESTDIR/../../run-summary-utils.sh"
$ FIRST_APP_BUILD=$(getSummaryTaskId "$FIRST" "my-app#build")
$ FIRST_UTIL_BUILD=$(getSummaryTaskId "$FIRST" "util#build")

$ echo $FIRST_APP_BUILD | jq '.execution'
{
Expand Down Expand Up @@ -71,5 +72,5 @@ Setup
}

# another#build is not in tasks, because it didn't execute (script was not implemented)
$ "$TESTDIR/get-build.sh" $FIRST "another"
$ getSummaryTaskId $FIRST "another#build"
null
9 changes: 9 additions & 0 deletions cli/integration_tests/run-summary-utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

function getSummaryTask() {
cat "$1" | jq ".tasks | map(select(.task == \"$2\")) | .[0]"
}

function getSummaryTaskId() {
cat "$1" | jq ".tasks | map(select(.taskId == \"$2\")) | .[0]"
}
34 changes: 34 additions & 0 deletions cli/integration_tests/single_package/dry-run.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,40 @@ Check

$ ${TURBO} run build --dry=json --single-package
{
"id": "[a-zA-Z0-9]+", (re)
"version": "0",
"turboVersion": "[0-9\.]+", (re)
"globalHashSummary": {
"globalFileHashMap": {
"package-lock.json": "8db0df575e6509336a6719094b63eb23d2c649c1",
"package.json": "185771929d92c3865ce06c863c07d357500d3364",
"somefile.txt": "45b983be36b73c0788dc9cbcb76cbb80fc7bb057"
},
"rootExternalDepsHash": "",
"globalCacheKey": "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo",
"pipeline": {
"//#build": {
"outputs": [
"foo"
],
"cache": true,
"dependsOn": [],
"inputs": [],
"outputMode": "full",
"env": [],
"persistent": false
}
}
},
"executionSummary": {
"success": 0,
"failed": 0,
"cached": 0,
"attempted": 0,
"startTime": [0-9]+, (re)
"endTime": [0-9-]+, (re)
"exitCode": 0
},
"tasks": [
{
"task": "build",
Expand Down
85 changes: 85 additions & 0 deletions cli/integration_tests/single_package/run-summary.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
Setup
$ . ${TESTDIR}/../setup.sh
$ . ${TESTDIR}/setup.sh $(pwd)

Check
$ ${TURBO} run build --summarize=true > /dev/null
$ test -d .turbo/runs
$ ls .turbo/runs/*.json | wc -l
\s*1 (re)

$ source "$TESTDIR/../run-summary-utils.sh"
$ SUMMARY=$(/bin/ls .turbo/runs/*.json | head -n1)
$ TASK_SUMMARY=$(getSummaryTask "$SUMMARY" "build")

$ cat $SUMMARY | jq '.tasks | length'
1
$ cat $SUMMARY | jq '.version'
"0"
$ cat $SUMMARY | jq '.executionSummary | keys'
[
"attempted",
"cached",
"endTime",
"exitCode",
"failed",
"startTime",
"success"
]

$ cat $SUMMARY | jq '.executionSummary.exitCode'
0
$ cat $SUMMARY | jq '.executionSummary.attempted'
1
$ cat $SUMMARY | jq '.executionSummary.cached'
0
$ cat $SUMMARY | jq '.executionSummary.failed'
0
$ cat $SUMMARY | jq '.executionSummary.success'
1
$ cat $SUMMARY | jq '.executionSummary.startTime'
[0-9]+ (re)
$ cat $SUMMARY | jq '.executionSummary.endTime'
[0-9]+ (re)

$ echo $TASK_SUMMARY | jq 'keys'
[
"cacheState",
"command",
"commandArguments",
"dependencies",
"dependents",
"environmentVariables",
"excludedOutputs",
"execution",
"expandedInputs",
"expandedOutputs",
"framework",
"hash",
"hashOfExternalDependencies",
"logFile",
"outputs",
"resolvedTaskDefinition",
"task"
]

$ echo $TASK_SUMMARY | jq '.execution'
{
"startTime": [0-9]+, (re)
"endTime": [0-9]+, (re)
"status": "built",
"error": null,
"exitCode": 0
}
$ echo $TASK_SUMMARY | jq '.commandArguments'
[]
$ echo $TASK_SUMMARY | jq '.expandedOutputs'
[
".turbo/turbo-build.log",
"foo"
]
$ echo $TASK_SUMMARY | jq '.cacheState'
{
"local": false,
"remote": false
}
3 changes: 3 additions & 0 deletions cli/integration_tests/single_package/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Check
Cached: 0 cached, 1 total
Time:\s*[\.0-9]+m?s (re)

$ test -d .turbo/runs/
[1]

Run a second time, verify caching works because there is a config
$ ${TURBO} run build --single-package
\xe2\x80\xa2 Running build (esc)
Expand Down
44 changes: 44 additions & 0 deletions cli/integration_tests/single_package_deps/dry-run.t
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,50 @@ Check

$ ${TURBO} run test --dry=json --single-package
{
"id": "[a-zA-Z0-9]+", (re)
"version": "0",
"turboVersion": "[0-9\.]+", (re)
"globalHashSummary": {
"globalFileHashMap": {
"package-lock.json": "8db0df575e6509336a6719094b63eb23d2c649c1",
"package.json": "bc24e5c5b8bd13d419e0742ae3e92a2bf61c53d0"
},
"rootExternalDepsHash": "",
"globalCacheKey": "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo",
"pipeline": {
"//#build": {
"outputs": [
"foo"
],
"cache": true,
"dependsOn": [],
"inputs": [],
"outputMode": "full",
"env": [],
"persistent": false
},
"//#test": {
"outputs": [],
"cache": true,
"dependsOn": [
"build"
],
"inputs": [],
"outputMode": "full",
"env": [],
"persistent": false
}
}
},
"executionSummary": {
"success": 0,
"failed": 0,
"cached": 0,
"attempted": 0,
"startTime": [0-9]+, (re)
"endTime": [0-9-]+, (re)
"exitCode": 0
},
"tasks": [
{
"task": "build",
Expand Down
31 changes: 31 additions & 0 deletions cli/integration_tests/single_package_no_config/dry-run.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,37 @@ Check

$ ${TURBO} run build --dry=json --single-package
{
"id": "[a-zA-Z0-9]+", (re)
"version": "0",
"turboVersion": "[0-9\.]+", (re)
"globalHashSummary": {
"globalFileHashMap": {
"package-lock.json": "8db0df575e6509336a6719094b63eb23d2c649c1",
"package.json": "581fe2b8dcba5b03cbe51d78a973143eb6d33e3a"
},
"rootExternalDepsHash": "",
"globalCacheKey": "Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo",
"pipeline": {
"//#build": {
"outputs": [],
"cache": false,
"dependsOn": [],
"inputs": [],
"outputMode": "full",
"env": [],
"persistent": false
}
}
},
"executionSummary": {
"success": 0,
"failed": 0,
"cached": 0,
"attempted": 0,
"startTime": [0-9]+, (re)
"endTime": [0-9-]+, (re)
"exitCode": 0
},
"tasks": [
{
"task": "build",
Expand Down
27 changes: 11 additions & 16 deletions cli/internal/runsummary/format_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ import (

// FormatJSON returns a json string representing a RunSummary
func (rsm *Meta) FormatJSON() ([]byte, error) {
rsm.RunSummary.normalize() // normalize data

if rsm.singlePackage {
return rsm.formatJSONSinglePackage()
}
rsm.normalize() // normalize data

bytes, err := json.MarshalIndent(rsm.RunSummary, "", " ")
if err != nil {
Expand All @@ -21,19 +17,18 @@ func (rsm *Meta) FormatJSON() ([]byte, error) {
return bytes, nil
}

func (rsm *Meta) formatJSONSinglePackage() ([]byte, error) {
singlePackageTasks := make([]singlePackageTaskSummary, len(rsm.RunSummary.Tasks))

for i, task := range rsm.RunSummary.Tasks {
singlePackageTasks[i] = task.toSinglePackageTask()
func (rsm *Meta) normalize() {
for _, t := range rsm.RunSummary.Tasks {
t.EnvVars.Global = rsm.RunSummary.GlobalHashSummary.EnvVars
}

spSummary := &singlePackageRunSummary{Tasks: singlePackageTasks}
// For single packages, we don't need the Packages
// and each task summary needs some cleaning.
if rsm.singlePackage {
rsm.RunSummary.Packages = []string{}

bytes, err := json.MarshalIndent(spSummary, "", " ")
if err != nil {
return nil, errors.Wrap(err, "failed to render JSON")
for _, task := range rsm.RunSummary.Tasks {
task.cleanForSinglePackage()
}
}

return bytes, nil
}
23 changes: 4 additions & 19 deletions cli/internal/runsummary/format_text.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (rsm Meta) FormatAndPrintText(workspaceInfos workspace.Catalog) error {
ui := rsm.ui
summary := rsm.RunSummary

summary.normalize() // normalize data
rsm.normalize() // normalize data

if !rsm.singlePackage {
ui.Output("")
Expand Down Expand Up @@ -56,31 +56,16 @@ func (rsm Meta) FormatAndPrintText(workspaceInfos workspace.Catalog) error {
taskName := task.TaskID

if rsm.singlePackage {
taskName = util.RootTaskTaskName(taskName)
taskName = task.Task
}

ui.Info(util.Sprintf("${BOLD}%s${RESET}", taskName))
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintln(w, util.Sprintf(" ${GREY}Task\t=\t%s\t${RESET}", task.Task))

var dependencies []string
var dependents []string

if !rsm.singlePackage {
fmt.Fprintln(w, util.Sprintf(" ${GREY}Package\t=\t%s\t${RESET}", task.Package))
dependencies = task.Dependencies
dependents = task.Dependents
} else {
dependencies = make([]string, len(task.Dependencies))
for i, dependency := range task.Dependencies {
dependencies[i] = util.StripPackageName(dependency)
}
dependents = make([]string, len(task.Dependents))
for i, dependent := range task.Dependents {
dependents[i] = util.StripPackageName(dependent)
}
}

fmt.Fprintln(w, util.Sprintf(" ${GREY}Hash\t=\t%s\t${RESET}", task.Hash))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Cached (Local)\t=\t%s\t${RESET}", strconv.FormatBool(task.CacheState.Local)))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Cached (Remote)\t=\t%s\t${RESET}", strconv.FormatBool(task.CacheState.Remote)))
Expand All @@ -92,8 +77,8 @@ func (rsm Meta) FormatAndPrintText(workspaceInfos workspace.Catalog) error {
fmt.Fprintln(w, util.Sprintf(" ${GREY}Command\t=\t%s\t${RESET}", task.Command))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Outputs\t=\t%s\t${RESET}", strings.Join(task.Outputs, ", ")))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Log File\t=\t%s\t${RESET}", task.LogFile))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Dependencies\t=\t%s\t${RESET}", strings.Join(dependencies, ", ")))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Dependendents\t=\t%s\t${RESET}", strings.Join(dependents, ", ")))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Dependencies\t=\t%s\t${RESET}", strings.Join(task.Dependencies, ", ")))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Dependendents\t=\t%s\t${RESET}", strings.Join(task.Dependents, ", ")))
fmt.Fprintln(w, util.Sprintf(" ${GREY}Inputs Files Considered\t=\t%d\t${RESET}", len(task.ExpandedInputs)))

fmt.Fprintln(w, util.Sprintf(" ${GREY}Configured Environment Variables\t=\t%s\t${RESET}", strings.Join(task.EnvVars.Configured, ", ")))
Expand Down
15 changes: 1 addition & 14 deletions cli/internal/runsummary/run_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,11 @@ type RunSummary struct {
Version string `json:"version"`
TurboVersion string `json:"turboVersion"`
GlobalHashSummary *GlobalHashSummary `json:"globalHashSummary"`
Packages []string `json:"packages"`
Packages []string `json:"packages,omitempty"`
ExecutionSummary *executionSummary `json:"executionSummary"`
Tasks []*TaskSummary `json:"tasks"`
}

// singlePackageRunSummary is the same as RunSummary with some adjustments
// to the internal struct for a single package. It's likely that we can use the
// same struct for Single Package repos in the future.
type singlePackageRunSummary struct {
Tasks []singlePackageTaskSummary `json:"tasks"`
}

// NewRunSummary returns a RunSummary instance
func NewRunSummary(
startAt time.Time,
Expand Down Expand Up @@ -278,9 +271,3 @@ func (rsm *Meta) postTaskSummaries(runID string) {
close(queue)
wg.Wait()
}

func (summary *RunSummary) normalize() {
for _, t := range summary.Tasks {
t.EnvVars.Global = summary.GlobalHashSummary.EnvVars
}
}
Loading

0 comments on commit 52dfda9

Please sign in to comment.