Skip to content

Commit 0785e69

Browse files
authored
Merge pull request #158720 from rickystewart/blathers/backport-release-25.3-158551
release-25.3: testowner: create helper binary to look up test owners
2 parents 2b84b19 + 59867f8 commit 0785e69

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

pkg/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ ALL_TESTS = [
163163
"//pkg/cmd/roachtest/testselector:testselector_test",
164164
"//pkg/cmd/roachtest:roachtest_test",
165165
"//pkg/cmd/run-pgo-build:run-pgo-build_test",
166+
"//pkg/cmd/testowner:testowner_test",
166167
"//pkg/col/coldata:coldata_disallowed_imports_test",
167168
"//pkg/col/coldata:coldata_test",
168169
"//pkg/col/coldataext:coldataext_test",
@@ -1280,6 +1281,9 @@ GO_TARGETS = [
12801281
"//pkg/cmd/sql-bootstrap-data:sql-bootstrap-data_lib",
12811282
"//pkg/cmd/testfilter:testfilter",
12821283
"//pkg/cmd/testfilter:testfilter_lib",
1284+
"//pkg/cmd/testowner:testowner",
1285+
"//pkg/cmd/testowner:testowner_lib",
1286+
"//pkg/cmd/testowner:testowner_test",
12831287
"//pkg/cmd/uptodate:uptodate",
12841288
"//pkg/cmd/uptodate:uptodate_lib",
12851289
"//pkg/cmd/urlcheck/lib/urlcheck:urlcheck",

pkg/cmd/testowner/BUILD.bazel

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
2+
3+
go_library(
4+
name = "testowner_lib",
5+
srcs = ["testowner.go"],
6+
importpath = "github.com/cockroachdb/cockroach/pkg/cmd/testowner",
7+
visibility = ["//visibility:private"],
8+
deps = [
9+
"//pkg/internal/codeowners",
10+
"//pkg/internal/team",
11+
],
12+
)
13+
14+
go_binary(
15+
name = "testowner",
16+
embed = [":testowner_lib"],
17+
visibility = ["//visibility:public"],
18+
)
19+
20+
go_test(
21+
name = "testowner_test",
22+
srcs = ["testowner_test.go"],
23+
embed = [":testowner_lib"],
24+
deps = ["@com_github_stretchr_testify//require"],
25+
)

pkg/cmd/testowner/testowner.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package main
2+
3+
// Copyright 2025 The Cockroach Authors.
4+
//
5+
// Use of this software is governed by the CockroachDB Software License
6+
// included in the /LICENSE file.
7+
//
8+
// testowner is a helper binary to get the owner of a given test.
9+
// Before invoking this binary, you should first generate Go code: `dev gen go`
10+
// This is because tests can be found in generated files that need to exist in
11+
// the workspace. Further, this should be run from the root of the workspace.
12+
//
13+
// The binary can be invoked in one of two ways:
14+
// * single test lookup: `testowner PKG TEST`. The owner(s) for the test will be
15+
// printed to stdout, separated by a space.
16+
// * multi-test lookup: `testowner` (with no arguments). In this case, stdin
17+
// will be a list of test lookups, one on each line, of the form `PKG TEST`.
18+
// the output will be one owner per line.
19+
20+
import (
21+
"bufio"
22+
"fmt"
23+
"io"
24+
"os"
25+
"strings"
26+
27+
"github.com/cockroachdb/cockroach/pkg/internal/codeowners"
28+
"github.com/cockroachdb/cockroach/pkg/internal/team"
29+
)
30+
31+
func main() {
32+
co, err := codeowners.DefaultLoadCodeOwners()
33+
if err != nil {
34+
panic(err)
35+
}
36+
stdout := bufio.NewWriter(os.Stdout)
37+
stderr := bufio.NewWriter(os.Stderr)
38+
if len(os.Args) == 1 {
39+
stdin := bufio.NewScanner(os.Stdin)
40+
for stdin.Scan() {
41+
line := stdin.Text()
42+
pkg, test := parseQuery(line)
43+
teams, logs := co.GetTestOwner(pkg, test)
44+
writeOwners(stdout, teams)
45+
for _, log := range logs {
46+
fmt.Fprintln(stderr, log)
47+
}
48+
}
49+
if err := stdin.Err(); err != nil {
50+
panic(err)
51+
}
52+
} else if len(os.Args) == 2 {
53+
pkg, test := parseQuery(os.Args[1])
54+
teams, logs := co.GetTestOwner(pkg, test)
55+
writeOwners(stdout, teams)
56+
for _, log := range logs {
57+
fmt.Fprintln(stderr, log)
58+
}
59+
} else {
60+
fmt.Fprintf(stderr, "usage: `testowner PKG.TEST` or `testowner` (with queries in stdin); got %d arguments, expected 1-2", len(os.Args))
61+
}
62+
if err := stdout.Flush(); err != nil {
63+
panic(err)
64+
}
65+
if err := stderr.Flush(); err != nil {
66+
panic(err)
67+
}
68+
}
69+
70+
func parseQuery(pkgAndTest string) (pkg string, test string) {
71+
const githubPrefix = "github.com/cockroachdb/cockroach/"
72+
var dotIdx int
73+
if strings.HasPrefix(pkgAndTest, githubPrefix) {
74+
dotIdx = strings.IndexByte(pkgAndTest[len(githubPrefix):], '.')
75+
if dotIdx <= 0 {
76+
panic(fmt.Sprintf("could not parse query (expected PKG.TEST): %s", pkgAndTest))
77+
}
78+
dotIdx += len(githubPrefix)
79+
} else {
80+
dotIdx = strings.IndexByte(pkgAndTest, '.')
81+
if dotIdx <= 0 {
82+
panic(fmt.Sprintf("could not parse query (expected PKG.TEST): %s", pkgAndTest))
83+
}
84+
}
85+
pkg, test = pkgAndTest[:dotIdx], pkgAndTest[dotIdx+1:]
86+
return
87+
}
88+
89+
func writeOwners(w io.Writer, teams []team.Team) {
90+
var prev bool
91+
if len(teams) == 0 {
92+
panic("empty team slice")
93+
}
94+
for _, team := range teams {
95+
if prev {
96+
_, err := w.Write([]byte{' '})
97+
if err != nil {
98+
panic(err)
99+
}
100+
}
101+
fmt.Fprintf(w, "%s", team.TeamName)
102+
prev = true
103+
}
104+
_, err := w.Write([]byte{'\n'})
105+
if err != nil {
106+
panic(err)
107+
}
108+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
// Copyright 2025 The Cockroach Authors.
4+
//
5+
// Use of this software is governed by the CockroachDB Software License
6+
// included in the /LICENSE file.
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestParseQuery(t *testing.T) {
15+
pkg, test := parseQuery("github.com/cockroachdb/cockroach/pkg/build.TestFoo")
16+
require.Equal(t, "github.com/cockroachdb/cockroach/pkg/build", pkg)
17+
require.Equal(t, "TestFoo", test)
18+
pkg, test = parseQuery("pkg/build.TestFoo")
19+
require.Equal(t, "pkg/build", pkg)
20+
require.Equal(t, "TestFoo", test)
21+
}

0 commit comments

Comments
 (0)