66
// commitOrder lists SHAs from oldest to newest.
67
// Runs whose SHA is not in commitOrder are skipped (e.g. from force-pushes or unrelated branches).
68
>
func buildObservations(testName string, runs []TestRun, commitOrderSlice []string, runToSHA map[int64]string) []CommitObservation {
bisect.go
69
>
// Build commit index map: SHA → index
70
>
commitIdx := make(map[string]int, len(commitOrderSlice))
71
>
for i, sha := range commitOrderSlice {
72
>
commitIdx[sha] = i
73
>
}
74
75
// Aggregate pass/fail counts per commit SHA for this test
76
>
type counts struct{ passes, fails int }
bisect.go
77
>
bySHA := make(map[string]*counts)
78
>
79
>
for _, run := range runs {
80
>
if run.Skipped {
81
continue
82
}
83
>
if normalizeTestName(run.Name) != testName {
bisect.go
84
continue
85
}
86
>
sha, ok := runToSHA[run.RunID]
bisect.go
87
>
if !ok || sha == "" {
88
continue
89
}
90
>
if _, inOrder := commitIdx[sha]; !inOrder {
bisect.go
91
continue
92
}
94
>
bySHA[sha] = &counts{}
95
>
}
96
>
if run.Failed {
97
>
bySHA[sha].fails++
98
>
} else {
99
>
bySHA[sha].passes++
100
>
}
101
}
102
103
// Convert to slice and sort by commit index
104
>
obs := make([]CommitObservation, 0, len(bySHA))
bisect.go
105
>
for sha, c := range bySHA {
106
>
obs = append(obs, CommitObservation{
107
>
CommitSHA: sha,
108
>
CommitIdx: commitIdx[sha],
109
>
Prior: 1.0, // uniform prior; adjusted by heuristics if enabled
110
>
Passes: c.passes,
111
>
Fails: c.fails,
112
>
})
113
>
}
114
>
sort.Slice(obs, func(i, j int) bool {
115
>
return obs[i].CommitIdx < obs[j].CommitIdx
116
>
})
117
>
return obs
118
}
119