Skip to content

Commit c639adb

Browse files
committed
cmd/relnote: avoid TODOs for issues in existing relnotes
Don't write a TODO for an issue that is mentioned in the release notes. For golang/go#64169. Change-Id: I9829957cb07c997a1d763fc00a996aeb2a53ba17 Reviewed-on: https://go-review.googlesource.com/c/build/+/584398 Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent dfad60d commit c639adb

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

cmd/relnote/todo.go

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,37 +31,41 @@ type ToDo struct {
3131
// It takes the doc/next directory of the repo and the date of the last release.
3232
func todo(w io.Writer, fsys fs.FS, prevRelDate time.Time) error {
3333
var todos []ToDo
34+
addToDo := func(td ToDo) { todos = append(todos, td) }
3435

35-
add := func(td ToDo) { todos = append(todos, td) }
36+
mentionedIssues := map[int]bool{} // issues mentioned in the existing relnotes
37+
addIssue := func(num int) { mentionedIssues[num] = true }
3638

37-
if err := todosFromDocFiles(fsys, add); err != nil {
39+
if err := infoFromDocFiles(fsys, addToDo, addIssue); err != nil {
3840
return err
3941
}
4042
if !prevRelDate.IsZero() {
41-
if err := todosFromCLs(prevRelDate, add); err != nil {
43+
if err := todosFromCLs(prevRelDate, mentionedIssues, addToDo); err != nil {
4244
return err
4345
}
4446
}
4547
return writeToDos(w, todos)
4648
}
4749

48-
// Collect TODOs from the markdown files in the main repo.
49-
func todosFromDocFiles(fsys fs.FS, add func(ToDo)) error {
50+
// Collect TODOs and issue numbers from the markdown files in the main repo.
51+
func infoFromDocFiles(fsys fs.FS, addToDo func(ToDo), addIssue func(int)) error {
5052
// This is essentially a grep.
5153
return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
5254
if err != nil {
5355
return err
5456
}
5557
if !d.IsDir() && strings.HasSuffix(path, ".md") {
56-
if err := todosFromFile(fsys, path, add); err != nil {
58+
if err := infoFromFile(fsys, path, addToDo, addIssue); err != nil {
5759
return err
5860
}
5961
}
6062
return nil
6163
})
6264
}
6365

64-
func todosFromFile(dir fs.FS, filename string, add func(ToDo)) error {
66+
var issueRE = regexp.MustCompile("/issue/([0-9]+)")
67+
68+
func infoFromFile(dir fs.FS, filename string, addToDo func(ToDo), addIssue func(int)) error {
6569
f, err := dir.Open(filename)
6670
if err != nil {
6771
return err
@@ -71,17 +75,25 @@ func todosFromFile(dir fs.FS, filename string, add func(ToDo)) error {
7175
ln := 0
7276
for scan.Scan() {
7377
ln++
74-
if line := scan.Text(); strings.Contains(line, "TODO") {
75-
add(ToDo{
78+
line := scan.Text()
79+
if strings.Contains(line, "TODO") {
80+
addToDo(ToDo{
7681
message: line,
7782
provenance: fmt.Sprintf("%s:%d", filename, ln),
7883
})
7984
}
85+
for _, matches := range issueRE.FindAllStringSubmatch(line, -1) {
86+
num, err := strconv.Atoi(matches[1])
87+
if err != nil {
88+
return fmt.Errorf("%s:%d: %v", filename, ln, err)
89+
}
90+
addIssue(num)
91+
}
8092
}
8193
return scan.Err()
8294
}
8395

84-
func todosFromCLs(cutoff time.Time, add func(ToDo)) error {
96+
func todosFromCLs(cutoff time.Time, mentionedIssues map[int]bool, add func(ToDo)) error {
8597
ctx := context.Background()
8698
// The maintner corpus doesn't track inline comments. See go.dev/issue/24863.
8799
// So we need to use a Gerrit API client to fetch them instead. If maintner starts
@@ -120,7 +132,7 @@ func todosFromCLs(cutoff time.Time, add func(ToDo)) error {
120132
}
121133
}
122134
// Add a TODO if the CL refers to an accepted proposal.
123-
todoFromProposal(ctx, cl, gh, add)
135+
todoFromProposal(cl, gh, mentionedIssues, add)
124136
return nil
125137
})
126138
})
@@ -143,11 +155,12 @@ func todoFromRelnote(ctx context.Context, cl *maintner.GerritCL, gc *gerrit.Clie
143155
return nil
144156
}
145157

146-
func todoFromProposal(ctx context.Context, cl *maintner.GerritCL, gh *maintner.GitHubRepo, add func(ToDo)) {
158+
func todoFromProposal(cl *maintner.GerritCL, gh *maintner.GitHubRepo, mentionedIssues map[int]bool, add func(ToDo)) {
147159
for _, num := range issueNumbers(cl) {
148-
// TODO(jba): look for CL references in existing release notes to avoid adding TODOs for
149-
// CLs that have already been documented.
150-
if issue := gh.Issue(num); issue != nil && hasLabel(issue, "Proposal-Accepted") {
160+
if mentionedIssues[num] {
161+
continue
162+
}
163+
if issue := gh.Issue(int32(num)); issue != nil && hasLabel(issue, "Proposal-Accepted") {
151164
// Add a TODO for all issues, regardless of when or whether they are closed.
152165
// Any work on an accepted proposal is potentially worthy of a release note.
153166
add(ToDo{
@@ -223,18 +236,18 @@ var numbersRE = regexp.MustCompile(`(?m)(?:^|\s|golang/go)#([0-9]{3,})`)
223236
var golangGoNumbersRE = regexp.MustCompile(`(?m)golang/go#([0-9]{3,})`)
224237

225238
// issueNumbers returns the golang/go issue numbers referred to by the CL.
226-
func issueNumbers(cl *maintner.GerritCL) []int32 {
239+
func issueNumbers(cl *maintner.GerritCL) []int {
227240
var re *regexp.Regexp
228241
if cl.Project.Project() == "go" {
229242
re = numbersRE
230243
} else {
231244
re = golangGoNumbersRE
232245
}
233246

234-
var list []int32
247+
var list []int
235248
for _, s := range re.FindAllStringSubmatch(cl.Commit.Msg, -1) {
236249
if n, err := strconv.Atoi(s[1]); err == nil && n < 1e9 {
237-
list = append(list, int32(n))
250+
list = append(list, n)
238251
}
239252
}
240253
// Remove duplicates.

0 commit comments

Comments
 (0)