@@ -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
@@ -455,21 +461,22 @@ func listFailuresFromJSON(
455461 // 2) Otherwise, we don't blame anybody in particular. We file a generic issue
456462 // listing the package name containing the report of long-running tests.
457463 if timedOutCulprit .name != "" {
464+ initCo ()
458465 slowest := slowFailEvents [0 ]
459466 if len (slowPassEvents ) > 0 && slowPassEvents [0 ].Elapsed > slowest .Elapsed {
460467 slowest = slowPassEvents [0 ]
461468 }
462469
463- culpritOwner := fmt . Sprintf ( "%v" , getOwner ( ctx , timedOutCulprit .pkg , timedOutCulprit .name ) )
470+ culpritOwner , _ := co . GetTestOwner ( timedOutCulprit .pkg , timedOutCulprit .name )
464471 slowEvents := append (slowFailEvents , slowPassEvents ... )
465472 // The predicate determines if the union of the slow events is owned by the _same_ team(s) as timedOutCulprit.
466473 hasSameOwner := func () bool {
467474 for _ , slowEvent := range slowEvents {
468475 scopedEvent := scoped (slowEvent )
469- owner := fmt . Sprintf ( "%v" , getOwner ( ctx , scopedEvent .pkg , scopedEvent .name ) )
476+ owner , _ := co . GetTestOwner ( scopedEvent .pkg , scopedEvent .name )
470477
471- if culpritOwner != owner {
472- log .Printf ("%v has a different owner: %s ;bailing out...\n " , scopedEvent , owner )
478+ if len ( culpritOwner ) < 1 || len ( owner ) < 1 || culpritOwner [ 0 ]. TeamName != owner [ 0 ]. TeamName {
479+ log .Printf ("%v has a different owner: %v ;bailing out...\n " , scopedEvent , owner )
473480 return false
474481 }
475482 }
@@ -630,95 +637,6 @@ func writeSlowTestsReport(report string) error {
630637 return os .WriteFile ("artifacts/slow-tests-report.txt" , []byte (report ), 0644 )
631638}
632639
633- // getFileLine returns the file (relative to repo root) and line for the given test.
634- // The package name is assumed relative to the repo root as well, i.e. pkg/foo/bar.
635- func getFileLine (
636- ctx context.Context , packageName , testName string ,
637- ) (_filename string , _linenum string , _ error ) {
638- if fileLineForTesting != nil {
639- res , ok := fileLineForTesting [packageAndTest {packageName : packageName , testName : testName }]
640- if ok {
641- return res .filename , res .linenum , nil
642- }
643- return "" , "" , errors .Newf ("could not find testing line:num for %s.%s" , packageName , testName )
644- }
645- // Search the source code for the email address of the last committer to touch
646- // the first line of the source code that contains testName. Then, ask GitHub
647- // for the GitHub username of the user with that email address by searching
648- // commits in cockroachdb/cockroach for commits authored by the address.
649- subtests := strings .Split (testName , "/" )
650- testName = subtests [0 ]
651- packageName = strings .TrimPrefix (packageName , "github.com/cockroachdb/cockroach/" )
652- for {
653- if ! strings .Contains (packageName , "pkg" ) {
654- return "" , "" , errors .Newf ("could not find test %s" , testName )
655- }
656- cmd := exec .Command (`/bin/bash` , `-c` ,
657- fmt .Sprintf (`cd "$(git rev-parse --show-toplevel)" && git grep -n 'func %s(' '%s/*_test.go'` ,
658- testName , packageName ))
659- // This command returns output such as:
660- // ../ccl/storageccl/export_test.go:31:func TestExportCmd(t *testing.T) {
661- out , err := cmd .CombinedOutput ()
662- if err != nil {
663- fmt .Printf ("couldn't find test %s in %s: %s %+v\n " ,
664- testName , packageName , string (out ), err )
665- packageName = filepath .Dir (packageName )
666- continue
667- }
668- re := regexp .MustCompile (`(.*):(.*):` )
669- // The first 2 :-delimited fields are the filename and line number.
670- matches := re .FindSubmatch (out )
671- if matches == nil {
672- fmt .Printf ("couldn't find filename/line number for test %s in %s: %s %+v\n " ,
673- testName , packageName , string (out ), err )
674- packageName = filepath .Dir (packageName )
675- continue
676- }
677- return string (matches [1 ]), string (matches [2 ]), nil
678- }
679- }
680-
681- // getOwner looks up the file containing the given test and returns
682- // the owning teams. It does not return
683- // errors, but instead simply returns what it can.
684- // In case no owning team is found, "test-eng" team is returned.
685- func getOwner (ctx context.Context , packageName , testName string ) (_teams []team.Team ) {
686- filename , _ , err := getFileLine (ctx , packageName , testName )
687- if err != nil {
688- log .Printf ("error getting file:line for %s.%s: %s" , packageName , testName , err )
689- // Let's continue so that we can assign the "catch-all" owner.
690- }
691- co , err := codeowners .DefaultLoadCodeOwners ()
692- if err != nil {
693- log .Printf ("loading codeowners: %s" , err )
694- return nil
695- }
696- match := co .Match (filename )
697-
698- if match == nil {
699- // N.B. if no owning team is found, we default to 'test-eng'. This should be a rare exception rather than the rule.
700- testEng := co .GetTeamForAlias ("cockroachdb/test-eng" )
701- if testEng .Name () == "" {
702- log .Fatalf ("test-eng team could not be found in TEAMS.yaml" )
703- }
704-
705- // Workaround for #107885.
706- if strings .Contains (packageName , "backup" ) {
707- dr := co .GetTeamForAlias ("cockroachdb/disaster-recovery" )
708- if dr .Name () == "" {
709- log .Fatalf ("disaster-recovery team could not be found in TEAMS.yaml" )
710- }
711-
712- log .Printf ("assigning %s.%s to 'disaster-recovery' due to #107885" , packageName , testName )
713- match = []team.Team {dr }
714- } else {
715- log .Printf ("assigning %s.%s to 'test-eng' as catch-all" , packageName , testName )
716- match = []team.Team {testEng }
717- }
718- }
719- return match
720- }
721-
722640func formatPebbleMetamorphicIssue (
723641 ctx context.Context , f Failure ,
724642) (issues.IssueFormatter , issues.PostRequest ) {
0 commit comments