Skip to content

Commit 8cc7007

Browse files
committed
cmd/gerritbot: post proper display name of message author to GitHub
Gerrit's NoteDB git-based metadata format changed recently to display "Gerrit User 1234" as the display name for meta commit authors. Use the Gerrit REST API to retrieve the proper display name and cache the result to prevent superfluous API calls. Also updates the maintner doc for the Author property of GerritMessage to reflect NoteDB's format. Fixes golang/go#28663 Change-Id: I549474ad139e48c736d715414e82b6db83a9fdf3 Reviewed-on: https://go-review.googlesource.com/c/148560 Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent fada1f3 commit 8cc7007

File tree

2 files changed

+65
-12
lines changed

2 files changed

+65
-12
lines changed

cmd/gerritbot/gerritbot.go

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"os/user"
2222
"path/filepath"
2323
"regexp"
24+
"strconv"
2425
"strings"
2526
"sync"
2627
"time"
@@ -246,15 +247,19 @@ type bot struct {
246247
// CLs that have been created/updated on Gerrit for GitHub PRs but are not yet
247248
// reflected in the maintner corpus yet.
248249
pendingCLs map[string]string // GitHub owner/repo#n -> Commit message from PR
250+
251+
// Cache of Gerrit Account IDs to AccountInfo structs.
252+
cachedGerritAccounts map[int]*gerrit.AccountInfo // 1234 -> Detailed Account Info
249253
}
250254

251255
func newBot(githubClient *github.Client, gerritClient *gerrit.Client) *bot {
252256
return &bot{
253-
githubClient: githubClient,
254-
gerritClient: gerritClient,
255-
importedPRs: map[string]*maintner.GerritCL{},
256-
pendingCLs: map[string]string{},
257-
cachedPRs: map[string]*cachedPullRequest{},
257+
githubClient: githubClient,
258+
gerritClient: gerritClient,
259+
importedPRs: map[string]*maintner.GerritCL{},
260+
pendingCLs: map[string]string{},
261+
cachedPRs: map[string]*cachedPullRequest{},
262+
cachedGerritAccounts: map[int]*gerrit.AccountInfo{},
258263
}
259264
}
260265

@@ -371,7 +376,7 @@ func prShortLink(pr *github.PullRequest) string {
371376
// imported. If the Gerrit change associated with a PR has been merged, the PR
372377
// is closed. Those that have no associated open or merged Gerrit changes will
373378
// result in one being created.
374-
// b's RWMutex read-write lock must be held.
379+
// b.RWMutex must be Lock'ed.
375380
func (b *bot) processPullRequest(ctx context.Context, pr *github.PullRequest) error {
376381
log.Printf("Processing PR %s ...", pr.GetHTMLURL())
377382
shortLink := prShortLink(pr)
@@ -428,24 +433,72 @@ func (b *bot) processPullRequest(ctx context.Context, pr *github.PullRequest) er
428433
return nil
429434
}
430435

436+
// gerritMessageAuthorID returns the Gerrit Account ID of the author of m.
437+
func gerritMessageAuthorID(m *maintner.GerritMessage) (int, error) {
438+
email := m.Author.Email()
439+
if strings.Index(email, "@") == -1 {
440+
return -1, fmt.Errorf("message author email %q does not contain '@' character", email)
441+
}
442+
i, err := strconv.Atoi(strings.Split(email, "@")[0])
443+
if err != nil {
444+
return -1, fmt.Errorf("strconv.Atoi: %v (email: %q)", err, email)
445+
}
446+
return i, nil
447+
}
448+
449+
// gerritMessageAuthorName returns a message author's display name. To prevent a
450+
// thundering herd of redundant comments created by posting a different message
451+
// via postGitHubMessageNoDup in syncGerritCommentsToGitHub, it will only return
452+
// the correct display name for messages posted after a hard-coded date.
453+
// b.RWMutex must be Lock'ed.
454+
func (b *bot) gerritMessageAuthorName(ctx context.Context, m *maintner.GerritMessage) (string, error) {
455+
t := time.Date(2018, time.November, 9, 0, 0, 0, 0, time.UTC)
456+
if m.Date.Before(t) {
457+
return m.Author.Name(), nil
458+
}
459+
id, err := gerritMessageAuthorID(m)
460+
if err != nil {
461+
return "", fmt.Errorf("gerritMessageAuthorID: %v", err)
462+
}
463+
account := b.cachedGerritAccounts[id]
464+
if account != nil {
465+
return account.Name, nil
466+
}
467+
ai, err := b.gerritClient.GetAccountInfo(ctx, strconv.Itoa(id))
468+
if err != nil {
469+
return "", fmt.Errorf("b.gerritClient.GetAccountInfo: %v", err)
470+
}
471+
b.cachedGerritAccounts[id] = &ai
472+
return ai.Name, nil
473+
}
474+
475+
// b.RWMutex must be Lock'ed.
431476
func (b *bot) syncGerritCommentsToGitHub(ctx context.Context, pr *github.PullRequest, cl *maintner.GerritCL) error {
432477
if *dryRun {
433478
log.Printf("[dry run] would sync Gerrit comments to %v", prShortLink(pr))
434479
return nil
435480
}
436481
repo := pr.GetBase().GetRepo()
437482
for _, m := range cl.Messages {
438-
if m.Author.Email() == cl.Owner().Email() {
483+
id, err := gerritMessageAuthorID(m)
484+
if err != nil {
485+
return fmt.Errorf("gerritMessageAuthorID: %v", err)
486+
}
487+
if id == cl.OwnerID() {
439488
continue
440489
}
490+
authorName, err := b.gerritMessageAuthorName(ctx, m)
491+
if err != nil {
492+
return fmt.Errorf("b.gerritMessageAuthorName: %v", err)
493+
}
441494
msg := fmt.Sprintf(`Message from %s:
442495
443496
%s
444497
445498
---
446499
Please don’t reply on this GitHub thread. Visit [golang.org/cl/%d](https://go-review.googlesource.com/c/%s/+/%d#message-%s).
447500
After addressing review feedback, remember to [publish your drafts](https://github.com/golang/go/wiki/GerritBot#i-left-a-reply-to-a-comment-in-gerrit-but-no-one-but-me-can-see-it)!`,
448-
m.Author.Name(), m.Message, cl.Number, cl.Project.Project(), cl.Number, m.Meta.Hash.String())
501+
authorName, m.Message, cl.Number, cl.Project.Project(), cl.Number, m.Meta.Hash.String())
449502
if err := b.postGitHubMessageNoDup(ctx, repo.GetOwner().GetLogin(), repo.GetName(), pr.GetNumber(), msg); err != nil {
450503
return fmt.Errorf("postGitHubMessageNoDup: %v", err)
451504
}
@@ -696,7 +749,7 @@ func reposRoot() string {
696749
}
697750

698751
// getFullPR retrieves a Pull Request via GitHub’s API.
699-
// b's RWMutex read-write lock must be held.
752+
// b.RWMutex must be Lock'ed.
700753
func (b *bot) getFullPR(ctx context.Context, owner, repo string, number int) (*github.PullRequest, error) {
701754
shortLink := githubShortLink(owner, repo, number)
702755
cpr := b.cachedPRs[shortLink]

maintner/gerrit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,9 @@ type GerritMessage struct {
335335
// the git commit).
336336
Date time.Time
337337

338-
// Author returns the author of the commit. This takes the form "Kevin Burke
339-
// <13437@62eb7196-b449-3ce5-99f1-c037f21e1705>", where the number before
340-
// the '@' sign is your Gerrit user ID, and the UUID after the '@' sign
338+
// Author returns the author of the commit. This takes the form "Gerrit User
339+
// 13437 <13437@62eb7196-b449-3ce5-99f1-c037f21e1705>", where the number
340+
// before the '@' sign is your Gerrit user ID, and the UUID after the '@' sign
341341
// seems to be the same for all commits for the same Gerrit server, across
342342
// projects.
343343
//

0 commit comments

Comments
 (0)