func extractFailures(revs []*Revision) []*failure { return processFailureLogs(revs, func(build *Build, data []byte) []*failure { // TODO: OS/Arch lfailures, err := loganal.Extract(string(data), "", "") if err != nil { log.Printf("%s: %v\n", build.LogPath(), err) return nil } if len(lfailures) == 0 { return nil } failures := make([]*failure, 0, len(lfailures)) for _, lf := range lfailures { // Ignore build failures. // // TODO: This has the effect of counting these // as successes for all tests. In the best // case, this cuts down on the number of // samples per revision. If we have an // across-the-board build failure, it will // drive down the failure rates of all // failures and may even effect timeline // subdivision. if strings.Contains(lf.Message, "build failed") { continue } failures = append(failures, &failure{ Failure: lf, }) } return failures }) }
func process(path, nicePath string) (found bool, err error) { // TODO: Use streaming if possible. data, err := ioutil.ReadFile(path) if err != nil { return false, err } // Check regexp match. if !fileRegexps.AllMatch(data) || !failRegexps.AllMatch(data) { return false, nil } // If this is from the dashboard, get the builder URL. var logURL string if _, err := os.Stat(filepath.Join(filepath.Dir(path), ".rev.json")); err == nil { // TODO: Get the URL from the rev.json metadata link, err := os.Readlink(path) if err == nil { hash := filepath.Base(link) logURL = "https://build.golang.org/log/" + hash } } printPath := nicePath if *flagMD && logURL != "" { printPath = fmt.Sprintf("[%s](%s)", nicePath, logURL) } if *flagFilesOnly { fmt.Printf("%s\n", printPath) return true, nil } // Extract failures. failures, err := loganal.Extract(string(data), "", "") if err != nil { return false, err } // Print failures. for _, failure := range failures { msg := failure.FullMessage if msg == "" { msg = failure.Message } if len(failRegexps) > 0 && !failRegexps.AllMatch([]byte(msg)) { continue } fmt.Printf("%s:\n", printPath) if *flagMD { fmt.Printf("```\n%s\n```\n\n", msg) } else { fmt.Printf("%s\n\n", msg) } } return true, nil }