@@ -20,12 +20,11 @@ import (
2020 "io"
2121 "log"
2222 "os"
23- "os/exec"
24- "path/filepath"
2523 "regexp"
2624 "sort"
2725 "strconv"
2826 "strings"
27+ "sync"
2928 "time"
3029
3130 buildutil "github.com/cockroachdb/cockroach/pkg/build/util"
@@ -40,23 +39,30 @@ const (
4039 unknown = "(unknown)"
4140)
4241
43- type packageAndTest struct {
44- packageName , testName string
45- }
42+ var (
43+ co * codeowners.CodeOwners
44+ codeownersOnce sync.Once
45+ )
4646
47- type fileAndLine struct {
48- filename , linenum string
47+ func initCo () {
48+ codeownersOnce .Do (func () {
49+ co_ , err := codeowners .DefaultLoadCodeOwners ()
50+ if err != nil {
51+ panic (err )
52+ }
53+ co = co_
54+ })
4955}
5056
51- // This should be set to some non-nil map in test scenarios. This is used to
52- // mock out the results of the getFileLine function.
53- var fileLineForTesting map [packageAndTest ]fileAndLine
54-
5557type Formatter func (context.Context , Failure ) (issues.IssueFormatter , issues.PostRequest )
5658type FailurePoster func (context.Context , Failure ) error
5759
5860func DefaultFormatter (ctx context.Context , f Failure ) (issues.IssueFormatter , issues.PostRequest ) {
59- teams := getOwner (ctx , f .packageName , f .testName )
61+ initCo ()
62+ teams , logs := co .GetTestOwner (f .packageName , f .testName )
63+ for _ , line := range logs {
64+ log .Println (line )
65+ }
6066 repro := fmt .Sprintf ("./dev test ./pkg/%s --race --stress -f %s" ,
6167 trimPkg (f .packageName ), f .testName )
6268
@@ -448,21 +454,22 @@ func listFailuresFromJSON(
448454 // 2) Otherwise, we don't blame anybody in particular. We file a generic issue
449455 // listing the package name containing the report of long-running tests.
450456 if timedOutCulprit .name != "" {
457+ initCo ()
451458 slowest := slowFailEvents [0 ]
452459 if len (slowPassEvents ) > 0 && slowPassEvents [0 ].Elapsed > slowest .Elapsed {
453460 slowest = slowPassEvents [0 ]
454461 }
455462
456- culpritOwner := fmt . Sprintf ( "%v" , getOwner ( ctx , timedOutCulprit .pkg , timedOutCulprit .name ) )
463+ culpritOwner , _ := co . GetTestOwner ( timedOutCulprit .pkg , timedOutCulprit .name )
457464 slowEvents := append (slowFailEvents , slowPassEvents ... )
458465 // The predicate determines if the union of the slow events is owned by the _same_ team(s) as timedOutCulprit.
459466 hasSameOwner := func () bool {
460467 for _ , slowEvent := range slowEvents {
461468 scopedEvent := scoped (slowEvent )
462- owner := fmt . Sprintf ( "%v" , getOwner ( ctx , scopedEvent .pkg , scopedEvent .name ) )
469+ owner , _ := co . GetTestOwner ( scopedEvent .pkg , scopedEvent .name )
463470
464- if culpritOwner != owner {
465- log .Printf ("%v has a different owner: %s ;bailing out...\n " , scopedEvent , owner )
471+ if len ( culpritOwner ) < 1 || len ( owner ) < 1 || culpritOwner [ 0 ]. TeamName != owner [ 0 ]. TeamName {
472+ log .Printf ("%v has a different owner: %v ;bailing out...\n " , scopedEvent , owner )
466473 return false
467474 }
468475 }
@@ -623,95 +630,6 @@ func writeSlowTestsReport(report string) error {
623630 return os .WriteFile ("artifacts/slow-tests-report.txt" , []byte (report ), 0644 )
624631}
625632
626- // getFileLine returns the file (relative to repo root) and line for the given test.
627- // The package name is assumed relative to the repo root as well, i.e. pkg/foo/bar.
628- func getFileLine (
629- ctx context.Context , packageName , testName string ,
630- ) (_filename string , _linenum string , _ error ) {
631- if fileLineForTesting != nil {
632- res , ok := fileLineForTesting [packageAndTest {packageName : packageName , testName : testName }]
633- if ok {
634- return res .filename , res .linenum , nil
635- }
636- return "" , "" , errors .Newf ("could not find testing line:num for %s.%s" , packageName , testName )
637- }
638- // Search the source code for the email address of the last committer to touch
639- // the first line of the source code that contains testName. Then, ask GitHub
640- // for the GitHub username of the user with that email address by searching
641- // commits in cockroachdb/cockroach for commits authored by the address.
642- subtests := strings .Split (testName , "/" )
643- testName = subtests [0 ]
644- packageName = strings .TrimPrefix (packageName , "github.com/cockroachdb/cockroach/" )
645- for {
646- if ! strings .Contains (packageName , "pkg" ) {
647- return "" , "" , errors .Newf ("could not find test %s" , testName )
648- }
649- cmd := exec .Command (`/bin/bash` , `-c` ,
650- fmt .Sprintf (`cd "$(git rev-parse --show-toplevel)" && git grep -n 'func %s(' '%s/*_test.go'` ,
651- testName , packageName ))
652- // This command returns output such as:
653- // ../ccl/storageccl/export_test.go:31:func TestExportCmd(t *testing.T) {
654- out , err := cmd .CombinedOutput ()
655- if err != nil {
656- fmt .Printf ("couldn't find test %s in %s: %s %+v\n " ,
657- testName , packageName , string (out ), err )
658- packageName = filepath .Dir (packageName )
659- continue
660- }
661- re := regexp .MustCompile (`(.*):(.*):` )
662- // The first 2 :-delimited fields are the filename and line number.
663- matches := re .FindSubmatch (out )
664- if matches == nil {
665- fmt .Printf ("couldn't find filename/line number for test %s in %s: %s %+v\n " ,
666- testName , packageName , string (out ), err )
667- packageName = filepath .Dir (packageName )
668- continue
669- }
670- return string (matches [1 ]), string (matches [2 ]), nil
671- }
672- }
673-
674- // getOwner looks up the file containing the given test and returns
675- // the owning teams. It does not return
676- // errors, but instead simply returns what it can.
677- // In case no owning team is found, "test-eng" team is returned.
678- func getOwner (ctx context.Context , packageName , testName string ) (_teams []team.Team ) {
679- filename , _ , err := getFileLine (ctx , packageName , testName )
680- if err != nil {
681- log .Printf ("error getting file:line for %s.%s: %s" , packageName , testName , err )
682- // Let's continue so that we can assign the "catch-all" owner.
683- }
684- co , err := codeowners .DefaultLoadCodeOwners ()
685- if err != nil {
686- log .Printf ("loading codeowners: %s" , err )
687- return nil
688- }
689- match := co .Match (filename )
690-
691- if match == nil {
692- // N.B. if no owning team is found, we default to 'test-eng'. This should be a rare exception rather than the rule.
693- testEng := co .GetTeamForAlias ("cockroachdb/test-eng" )
694- if testEng .Name () == "" {
695- log .Fatalf ("test-eng team could not be found in TEAMS.yaml" )
696- }
697-
698- // Workaround for #107885.
699- if strings .Contains (packageName , "backup" ) {
700- dr := co .GetTeamForAlias ("cockroachdb/disaster-recovery" )
701- if dr .Name () == "" {
702- log .Fatalf ("disaster-recovery team could not be found in TEAMS.yaml" )
703- }
704-
705- log .Printf ("assigning %s.%s to 'disaster-recovery' due to #107885" , packageName , testName )
706- match = []team.Team {dr }
707- } else {
708- log .Printf ("assigning %s.%s to 'test-eng' as catch-all" , packageName , testName )
709- match = []team.Team {testEng }
710- }
711- }
712- return match
713- }
714-
715633func formatPebbleMetamorphicIssue (
716634 ctx context.Context , f Failure ,
717635) (issues.IssueFormatter , issues.PostRequest ) {
0 commit comments