forked from evergreen-ci/evergreen
/
status_diff.go
126 lines (110 loc) · 3.73 KB
/
status_diff.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package model
import (
"github.com/evergreen-ci/evergreen/apimodels"
"github.com/evergreen-ci/evergreen/model/build"
"path"
"strings"
)
// StatusDiff stores a pairing of status strings
// for easy visualization/aggregation later.
type StatusDiff struct {
Original string `json:"original"`
Patch string `json:"patch"`
}
// StatusDetailsDiff stores a pairing of status details
// for easy visualization/aggregation later.
type StatusDetailsDiff struct {
Original apimodels.TaskEndDetail `json:"original"`
Patch apimodels.TaskEndDetail `json:"patch"`
}
// BuildStatusDiff stores a diff of two build statuses.
type BuildStatusDiff struct {
Name string `json:"name"`
Diff StatusDiff `json:"diff"`
Tasks []TaskStatusDiff `json:"tasks"`
}
// TaskStatusDiff stores a diff of two task statuses.
type TaskStatusDiff struct {
Name string `json:"name"`
Diff StatusDetailsDiff `json:"diff"`
Tests []TestStatusDiff `json:"tests"`
Original string `json:"original"`
Patch string `json:"patch"`
BuildVariant string `json:"build_variant"`
}
// TestStatusDiff stores a diff of two test results.
type TestStatusDiff struct {
Name string `json:"name"`
Diff StatusDiff `json:"diff"`
Original string `json:"original"`
Patch string `json:"patch"`
}
// StatusDiffBuilds takes two builds and returns a diff of their results
// for easy comparison and analysis.
func StatusDiffBuilds(original, patch *build.Build) BuildStatusDiff {
// return an empty diff if one of builds is nonexistant
// this is likely to occur after adding a new buildvariant or task
if original == nil || patch == nil {
return BuildStatusDiff{}
}
diff := BuildStatusDiff{
Name: original.DisplayName,
Diff: StatusDiff{original.Status, patch.Status},
}
// build maps of task statuses, for matching
originalTasks := make(map[string]build.TaskCache)
for _, task := range original.Tasks {
originalTasks[task.DisplayName] = task
}
// iterate through all patch tasks and create diffs
// NOTE: this implicitly skips all tasks not present in the patch
for _, task := range patch.Tasks {
baseTask := originalTasks[task.DisplayName]
diff.Tasks = append(diff.Tasks,
TaskStatusDiff{
Name: task.DisplayName,
Diff: StatusDetailsDiff{baseTask.StatusDetails, task.StatusDetails},
Original: baseTask.Id,
Patch: task.Id,
BuildVariant: diff.Name,
})
}
return diff
}
// StatusDiffTasks takes two tasks and returns a diff of their results
// for easy comparison and analysis.
func StatusDiffTasks(original *Task, patch *Task) TaskStatusDiff {
// return an empty diff if one of tasks is nonexistant
// this is likely to occur after adding a new buildvariant or task
if original == nil || patch == nil {
return TaskStatusDiff{}
}
diff := TaskStatusDiff{
Name: original.DisplayName,
Original: original.Id,
Patch: patch.Id,
Diff: StatusDetailsDiff{original.Details, patch.Details},
}
if original.TestResults == nil || patch.TestResults == nil {
return diff
}
// build maps of test statuses, for matching
originalTests := make(map[string]TestResult)
for _, test := range original.TestResults {
originalTests[test.TestFile] = test
}
// iterate through all patch tests and create diffs
for _, test := range patch.TestResults {
baseTest := originalTests[test.TestFile]
// get the base name for windows/non-windows paths
testFile := path.Base(strings.Replace(test.TestFile, "\\", "/", -1))
diff.Tests = append(diff.Tests,
TestStatusDiff{
Name: testFile,
Diff: StatusDiff{baseTest.Status, test.Status},
Original: getTestUrl(&baseTest),
Patch: getTestUrl(&test),
})
}
return diff
}