Skip to content

Commit 0b82a20

Browse files
dmitshurgopherbot
authored andcommitted
cmd/gopherbot: add "close luci-config issues" task
The "close luci-config issues" task is based on the "close cherry pick issues" task and exists for the same reason. For example, the Go issue go.dev/issue/63482 should've been closed when https://go.dev/cl/586036 was submitted (since it had a "Fixes golang/go#63482." line), but that didn't happen because it was submitted to the luci-config branch. While here, update the "close cherry pick issues" task message to note the CL number in its closing message too. Also access the scratch repo directly in abandonScratchReviews without using a loop (for simplicity and consistency). Tested with go run . -dry-run -only-run="close luci-config issues" but with the 'monthAgo' optimization temporarily left out. Change-Id: I363842e97ab8867afb1933ab97a4e64e0aceeb17 Reviewed-on: https://go-review.googlesource.com/c/build/+/597435 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Carlos Amedee <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
1 parent 59576ec commit 0b82a20

File tree

1 file changed

+58
-23
lines changed

1 file changed

+58
-23
lines changed

cmd/gopherbot/gopherbot.go

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ var tasks = []struct {
468468
{"handle telemetry issues", (*gopherbot).handleTelemetryIssues},
469469
{"open cherry pick issues", (*gopherbot).openCherryPickIssues},
470470
{"close cherry pick issues", (*gopherbot).closeCherryPickIssues},
471+
{"close luci-config issues", (*gopherbot).closeLUCIConfigIssues},
471472
{"set subrepo milestones", (*gopherbot).setSubrepoMilestones},
472473
{"set misc milestones", (*gopherbot).setMiscMilestones},
473474
{"apply minor release milestones", (*gopherbot).setMinorMilestones},
@@ -1859,7 +1860,7 @@ func (b *gopherbot) setMinorMilestones(ctx context.Context) error {
18591860
}
18601861

18611862
// closeCherryPickIssues closes cherry-pick issues when CLs are merged to
1862-
// release branches, as GitHub only does that on merge to master.
1863+
// release branches, as GitHub only does that on merge to the main branch.
18631864
func (b *gopherbot) closeCherryPickIssues(ctx context.Context) error {
18641865
cherryPickIssues := make(map[int32]*maintner.GitHubIssue) // by GitHub Issue Number
18651866
b.foreachIssue(b.gorepo, open, func(gi *maintner.GitHubIssue) error {
@@ -1902,7 +1903,7 @@ func (b *gopherbot) closeCherryPickIssues(ctx context.Context) error {
19021903
}
19031904
printIssue("close-cherry-pick", ref.Repo.ID(), gi)
19041905
if err := b.addGitHubComment(ctx, ref.Repo, gi.Number, fmt.Sprintf(
1905-
"Closed by merging %s to %s.", cl.Commit.Hash, cl.Branch())); err != nil {
1906+
"Closed by merging [CL %d](https://go.dev/cl/%d) (commit %s) to `%s`.", cl.Number, cl.Number, cl.Commit.Hash, cl.Branch())); err != nil {
19061907
return err
19071908
}
19081909
return b.closeGitHubIssue(ctx, ref.Repo.ID(), gi.Number, completed)
@@ -1912,6 +1913,43 @@ func (b *gopherbot) closeCherryPickIssues(ctx context.Context) error {
19121913
})
19131914
}
19141915

1916+
// closeLUCIConfigIssues closes specified issues when CLs are merged to the
1917+
// luci-config branch, as GitHub only does that on merge to the main branch.
1918+
func (b *gopherbot) closeLUCIConfigIssues(ctx context.Context) error {
1919+
buildProject := b.corpus.Gerrit().Project("go.googlesource.com", "build")
1920+
if buildProject == nil {
1921+
return fmt.Errorf("no go.googlesource.com/build Gerrit project in corpus")
1922+
}
1923+
monthAgo := time.Now().Add(-30 * 24 * time.Hour)
1924+
return buildProject.ForeachCLUnsorted(func(cl *maintner.GerritCL) error {
1925+
if cl.Commit.CommitTime.Before(monthAgo) {
1926+
// If the CL was last updated over a month ago, assume (as an
1927+
// optimization) that gopherbot already processed this CL.
1928+
return nil
1929+
}
1930+
if cl.Status != "merged" || cl.Private || cl.Branch() != "luci-config" {
1931+
return nil
1932+
}
1933+
for _, ref := range cl.GitHubIssueRefs {
1934+
if ref.Repo != b.gorepo {
1935+
continue
1936+
}
1937+
gi := b.gorepo.Issue(ref.Number)
1938+
if gi == nil || gi.NotExist || gi.PullRequest || gi.Locked || b.deletedIssues[githubIssue{ref.Repo.ID(), gi.Number}] ||
1939+
gi.Closed || gi.HasEvent("reopened") || !strings.Contains(cl.Commit.Msg, fmt.Sprintf("\nFixes golang/go#%d", gi.Number)) {
1940+
continue
1941+
}
1942+
printIssue("close luci-config issues", ref.Repo.ID(), gi)
1943+
if err := b.addGitHubComment(ctx, ref.Repo, gi.Number, fmt.Sprintf(
1944+
"Closed by merging [CL %d](https://go.dev/cl/%d) (commit %s@%s) to `%s`.", cl.Number, cl.Number, ref.Repo.ID(), cl.Commit.Hash, cl.Branch())); err != nil {
1945+
return err
1946+
}
1947+
return b.closeGitHubIssue(ctx, ref.Repo.ID(), gi.Number, completed)
1948+
}
1949+
return nil
1950+
})
1951+
}
1952+
19151953
type labelCommand struct {
19161954
action string // "add" or "remove"
19171955
label string // the label name
@@ -2129,11 +2167,11 @@ var assignReviewersOptOut = map[string]bool{
21292167
// using the go.dev/s/owners API.
21302168
func (b *gopherbot) assignReviewersToCLs(ctx context.Context) error {
21312169
const tagNoOwners = "no-owners"
2132-
b.corpus.Gerrit().ForeachProjectUnsorted(func(gp *maintner.GerritProject) error {
2170+
return b.corpus.Gerrit().ForeachProjectUnsorted(func(gp *maintner.GerritProject) error {
21332171
if gp.Project() == "scratch" || gp.Server() != "go.googlesource.com" {
21342172
return nil
21352173
}
2136-
gp.ForeachOpenCL(func(cl *maintner.GerritCL) error {
2174+
return gp.ForeachOpenCL(func(cl *maintner.GerritCL) error {
21372175
if cl.Private || cl.WorkInProgress() || time.Since(cl.Created) < 10*time.Minute {
21382176
return nil
21392177
}
@@ -2235,9 +2273,7 @@ func (b *gopherbot) assignReviewersToCLs(ctx context.Context) error {
22352273
}
22362274
return nil
22372275
})
2238-
return nil
22392276
})
2240-
return nil
22412277
}
22422278

22432279
func sameReviewers(reviewers []string, review gerrit.ReviewInput) bool {
@@ -2274,26 +2310,25 @@ outer:
22742310

22752311
// abandonScratchReviews abandons Gerrit CLs in the "scratch" project if they've been open for over a week.
22762312
func (b *gopherbot) abandonScratchReviews(ctx context.Context) error {
2313+
scratchProject := b.corpus.Gerrit().Project("go.googlesource.com", "scratch")
2314+
if scratchProject == nil {
2315+
return fmt.Errorf("no go.googlesource.com/scratch Gerrit project in corpus")
2316+
}
22772317
tooOld := time.Now().Add(-24 * time.Hour * 7)
2278-
return b.corpus.Gerrit().ForeachProjectUnsorted(func(gp *maintner.GerritProject) error {
2279-
if gp.Project() != "scratch" || gp.Server() != "go.googlesource.com" {
2318+
return scratchProject.ForeachOpenCL(func(cl *maintner.GerritCL) error {
2319+
if b.deletedChanges[gerritChange{scratchProject.Project(), cl.Number}] || !cl.Meta.Commit.CommitTime.Before(tooOld) {
22802320
return nil
22812321
}
2282-
return gp.ForeachOpenCL(func(cl *maintner.GerritCL) error {
2283-
if b.deletedChanges[gerritChange{gp.Project(), cl.Number}] || !cl.Meta.Commit.CommitTime.Before(tooOld) {
2284-
return nil
2285-
}
2286-
if *dryRun {
2287-
log.Printf("[dry-run] would've closed scratch CL https://go.dev/cl/%d ...", cl.Number)
2288-
return nil
2289-
}
2290-
log.Printf("closing scratch CL https://go.dev/cl/%d ...", cl.Number)
2291-
err := b.gerrit.AbandonChange(ctx, fmt.Sprint(cl.Number), "Auto-abandoning old scratch review.")
2292-
if err != nil && strings.Contains(err.Error(), "404 Not Found") {
2293-
return nil
2294-
}
2295-
return err
2296-
})
2322+
if *dryRun {
2323+
log.Printf("[dry-run] would've closed scratch CL https://go.dev/cl/%d ...", cl.Number)
2324+
return nil
2325+
}
2326+
log.Printf("closing scratch CL https://go.dev/cl/%d ...", cl.Number)
2327+
err := b.gerrit.AbandonChange(ctx, fmt.Sprint(cl.Number), "Auto-abandoning old scratch review.")
2328+
if err != nil && strings.Contains(err.Error(), "404 Not Found") {
2329+
return nil
2330+
}
2331+
return err
22972332
})
22982333
}
22992334

0 commit comments

Comments
 (0)