[build] maintner: add TrackGitHub method variant taking an oauth2.TokenSource

0 views
Skip to first unread message

Brad Fitzpatrick (Gerrit)

unread,
Mar 18, 2026, 3:08:49 PM (2 days ago) Mar 18
to goph...@pubsubhelper.golang.org, Brad Fitzpatrick, golang-co...@googlegroups.com

Brad Fitzpatrick has uploaded the change for review

Commit message

maintner: add TrackGitHub method variant taking an oauth2.TokenSource

Replace the plain string token with an oauth2.TokenSource throughout
the GitHub tracking and polling code. This allows callers to provide
token sources that can refresh credentials, rather than being limited
to static tokens. (e.g. GitHub Apps credentials)
Change-Id: I70a4d2731409fe080390650549a062874afb1d33

Change diff

diff --git a/maintner/github.go b/maintner/github.go
index 772408f..ad05a8f 100644
--- a/maintner/github.go
+++ b/maintner/github.go
@@ -782,6 +782,13 @@
// watch and append to the mutation log. Only valid in leader mode.
// The token is the auth token to use to make API calls.
func (c *Corpus) TrackGitHub(owner, repo, token string) {
+ c.TrackGitHubWithTokenSource(owner, repo, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}))
+}
+
+// TrackGitHubWithTokenSource registers the named GitHub repo as a repo to
+// watch and append to the mutation log. Only valid in leader mode.
+// The tokenSource is used to obtain auth tokens for GitHub API calls.
+func (c *Corpus) TrackGitHubWithTokenSource(owner, repo string, tokenSource oauth2.TokenSource) {
if c.mutationLogger == nil {
panic("can't TrackGitHub in non-leader mode")
}
@@ -794,14 +801,14 @@
log.Fatalf("invalid github owner/repo %q/%q", owner, repo)
}
c.watchedGithubRepos = append(c.watchedGithubRepos, watchedGithubRepo{
- gr: gr,
- token: token,
+ gr: gr,
+ tokenSource: tokenSource,
})
}

type watchedGithubRepo struct {
- gr *GitHubRepo
- token string
+ gr *GitHubRepo
+ tokenSource oauth2.TokenSource
}

// g.c.mu must be held
@@ -1450,9 +1457,8 @@
// sync checks for new changes on a single GitHub repository and
// updates the Corpus with any changes. If loop is true, it runs
// forever.
-func (gr *GitHubRepo) sync(ctx context.Context, token string, loop bool) error {
- ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
- hc := oauth2.NewClient(ctx, ts)
+func (gr *GitHubRepo) sync(ctx context.Context, tokenSource oauth2.TokenSource, loop bool) error {
+ hc := oauth2.NewClient(ctx, tokenSource)
if tr, ok := hc.Transport.(*http.Transport); ok {
defer tr.CloseIdleConnections()
}
@@ -1468,7 +1474,7 @@

p := &githubRepoPoller{
c: gr.github.c,
- token: token,
+ tokenSource: tokenSource,
gr: gr,
githubDirect: github.NewClient(&http.Client{Transport: directTransport}),
githubCaching: github.NewClient(&http.Client{Transport: cachingTransport}),
@@ -1529,7 +1535,7 @@
type githubRepoPoller struct {
c *Corpus // shortcut for gr.github.c
gr *GitHubRepo
- token string
+ tokenSource oauth2.TokenSource
lastUpdate time.Time // modified by sync
githubCaching *github.Client
githubDirect *github.Client // not caching
@@ -2048,7 +2054,11 @@
p.Owner(), p.Repo(), issueNum, perPage, page)
req, _ := http.NewRequest("GET", u, nil)

- req.Header.Set("Authorization", "Bearer "+p.token)
+ tok, err := p.tokenSource.Token()
+ if err != nil {
+ return nil, nil, fmt.Errorf("getting token: %v", err)
+ }
+ req.Header.Set("Authorization", "Bearer "+tok.AccessToken)
req.Header.Set("User-Agent", "golang-x-build-maintner/1.0")
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
@@ -2292,7 +2302,11 @@
p.Owner(), p.Repo(), issueNum, perPage, page)
req, _ := http.NewRequest("GET", u, nil)

- req.Header.Set("Authorization", "Bearer "+p.token)
+ tok, err := p.tokenSource.Token()
+ if err != nil {
+ return nil, nil, fmt.Errorf("getting token: %v", err)
+ }
+ req.Header.Set("Authorization", "Bearer "+tok.AccessToken)
req.Header.Set("User-Agent", "golang-x-build-maintner/1.0")
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
diff --git a/maintner/github_test.go b/maintner/github_test.go
index b9d9b9c..374c474 100644
--- a/maintner/github_test.go
+++ b/maintner/github_test.go
@@ -21,6 +21,7 @@

"github.com/google/go-github/v74/github"
"golang.org/x/build/maintner/maintpb"
+ "golang.org/x/oauth2"
"google.golang.org/protobuf/types/known/timestamppb"
)

@@ -669,7 +670,7 @@
defer server.Close()
p := &githubRepoPoller{
c: &c,
- token: "foobar",
+ tokenSource: oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "foobar"}),
gr: gr,
githubDirect: github.NewClient(server.Client()),
githubCaching: github.NewClient(server.Client()),
@@ -745,7 +746,7 @@
defer server.Close()
p := &githubRepoPoller{
c: &c,
- token: "foobar",
+ tokenSource: oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "foobar"}),
gr: gr,
githubDirect: github.NewClient(server.Client()),
githubCaching: github.NewClient(server.Client()),
diff --git a/maintner/maintner.go b/maintner/maintner.go
index d78802b..c8ad3ca 100644
--- a/maintner/maintner.go
+++ b/maintner/maintner.go
@@ -371,11 +371,11 @@

group, ctx := errgroup.WithContext(ctx)
for _, w := range c.watchedGithubRepos {
- gr, token := w.gr, w.token
+ gr, ts := w.gr, w.tokenSource
group.Go(func() error {
log.Printf("Polling %v ...", gr.id)
for {
- err := gr.sync(ctx, token, loop)
+ err := gr.sync(ctx, ts, loop)
if loop && isTempErr(err) {
log.Printf("Temporary error from github %v: %v", gr.ID(), err)
time.Sleep(30 * time.Second)

Change information

Files:
  • M maintner/github.go
  • M maintner/github_test.go
  • M maintner/maintner.go
Change size: S
Delta: 3 files changed, 30 insertions(+), 15 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: build
Gerrit-Branch: master
Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
Gerrit-Change-Number: 756520
Gerrit-PatchSet: 1
Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
unsatisfied_requirement
satisfied_requirement
open
diffy

Brad Fitzpatrick (Gerrit)

unread,
Mar 18, 2026, 3:09:40 PM (2 days ago) Mar 18
to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, golang-co...@googlegroups.com
Attention needed from Dmitri Shuralyov

Brad Fitzpatrick voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Dmitri Shuralyov
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: build
Gerrit-Branch: master
Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
Gerrit-Change-Number: 756520
Gerrit-PatchSet: 1
Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
Gerrit-Comment-Date: Wed, 18 Mar 2026 19:09:36 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
unsatisfied_requirement
satisfied_requirement
open
diffy

Kevin Burke (Gerrit)

unread,
Mar 18, 2026, 3:18:10 PM (2 days ago) Mar 18
to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Go LUCI, Dmitri Shuralyov, golang-co...@googlegroups.com
Attention needed from Brad Fitzpatrick and Dmitri Shuralyov

Kevin Burke voted and added 2 comments

Votes added by Kevin Burke

Code-Review+1

2 comments

File maintner/github.go
Line 785, Patchset 1 (Latest): c.TrackGitHubWithTokenSource(owner, repo, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}))
Kevin Burke . unresolved

// The token is the auth token to use to make API calls.

now that we have a new method, worth editing the last doc line to read "The token is a static auth token; for dynamic OAuth try the WithTokenSource variant" or something?

Line 2057, Patchset 1 (Latest): tok, err := p.tokenSource.Token()
Kevin Burke . unresolved

Don't like that this is a new source of latency with uncontrollable timeout when the token refreshes, but don't think it makes sense to change here - if people care they can have the TokenSource refresh in the background.

Open in Gerrit

Related details

Attention is currently required from:
  • Brad Fitzpatrick
  • Dmitri Shuralyov
Submit Requirements:
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: build
    Gerrit-Branch: master
    Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
    Gerrit-Change-Number: 756520
    Gerrit-PatchSet: 1
    Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
    Gerrit-Attention: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Wed, 18 Mar 2026 19:18:06 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    unsatisfied_requirement
    open
    diffy

    Dmitri Shuralyov (Gerrit)

    unread,
    Mar 18, 2026, 3:18:13 PM (2 days ago) Mar 18
    to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Kevin Burke, Go LUCI, golang-co...@googlegroups.com
    Attention needed from Brad Fitzpatrick

    Dmitri Shuralyov voted and added 2 comments

    Votes added by Dmitri Shuralyov

    Code-Review+2

    2 comments

    Patchset-level comments
    File-level comment, Patchset 1 (Latest):
    Dmitri Shuralyov . resolved

    Thanks.

    File maintner/github.go
    Line 2061, Patchset 1 (Latest): req.Header.Set("Authorization", "Bearer "+tok.AccessToken)
    Dmitri Shuralyov . resolved

    I think we could start using `tok.SetAuthHeader(req)` here now that there's an `oauth2.Token`, if you want. But this should be equivalent at least for today's needs, so either way is fine. (Similarly on line 2309.)

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Brad Fitzpatrick
    Submit Requirements:
    • requirement satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: build
    Gerrit-Branch: master
    Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
    Gerrit-Change-Number: 756520
    Gerrit-PatchSet: 1
    Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Wed, 18 Mar 2026 19:18:09 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Kevin Burke (Gerrit)

    unread,
    Mar 18, 2026, 3:18:15 PM (2 days ago) Mar 18
    to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Go LUCI, golang-co...@googlegroups.com
    Attention needed from Brad Fitzpatrick

    Kevin Burke voted Code-Review+2

    Code-Review+2
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Brad Fitzpatrick
    Submit Requirements:
    • requirement satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: build
    Gerrit-Branch: master
    Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
    Gerrit-Change-Number: 756520
    Gerrit-PatchSet: 1
    Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Wed, 18 Mar 2026 19:18:12 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dmitri Shuralyov (Gerrit)

    unread,
    Mar 18, 2026, 3:18:50 PM (2 days ago) Mar 18
    to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Kevin Burke, Go LUCI, golang-co...@googlegroups.com
    Attention needed from Brad Fitzpatrick

    Dmitri Shuralyov voted Code-Review+1

    Code-Review+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Brad Fitzpatrick
    Submit Requirements:
    • requirement satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: build
    Gerrit-Branch: master
    Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
    Gerrit-Change-Number: 756520
    Gerrit-PatchSet: 1
    Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
    Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Wed, 18 Mar 2026 19:18:46 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dmitri Shuralyov (Gerrit)

    unread,
    Mar 18, 2026, 3:21:41 PM (2 days ago) Mar 18
    to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Dmitri Shuralyov, Dmitri Shuralyov, Kevin Burke, Go LUCI, golang-co...@googlegroups.com
    Attention needed from Brad Fitzpatrick

    Dmitri Shuralyov added 1 comment

    File maintner/github.go
    Line 2057, Patchset 1 (Latest): tok, err := p.tokenSource.Token()
    Kevin Burke . unresolved

    Don't like that this is a new source of latency with uncontrollable timeout when the token refreshes, but don't think it makes sense to change here - if people care they can have the TokenSource refresh in the background.

    Dmitri Shuralyov

    Can the potential latency be dealt with by wrapping with something like [oauth2.ReuseTokenSource](https://pkg.go.dev/golang.org/x/oauth2#ReuseTokenSource)?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Brad Fitzpatrick
    Submit Requirements:
    • requirement satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement is not satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: build
    Gerrit-Branch: master
    Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
    Gerrit-Change-Number: 756520
    Gerrit-PatchSet: 1
    Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
    Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
    Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
    Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
    Gerrit-Comment-Date: Wed, 18 Mar 2026 19:21:38 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Kevin Burke <ke...@burke.dev>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Brad Fitzpatrick (Gerrit)

    unread,
    Mar 19, 2026, 11:00:19 AM (15 hours ago) Mar 19
    to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Go LUCI, Dmitri Shuralyov, Dmitri Shuralyov, Kevin Burke, golang-co...@googlegroups.com

    Brad Fitzpatrick added 1 comment

    File maintner/github.go
    Line 2061, Patchset 1 (Latest): req.Header.Set("Authorization", "Bearer "+tok.AccessToken)
    Dmitri Shuralyov . resolved

    I think we could start using `tok.SetAuthHeader(req)` here now that there's an `oauth2.Token`, if you want. But this should be equivalent at least for today's needs, so either way is fine. (Similarly on line 2309.)

    Brad Fitzpatrick

    This CL was my minimally-sized trial balloon to see if this code had somebody around to still review these things. If so (seems like it!) then I can send more changes. ;)

    Open in Gerrit

    Related details

    Attention set is empty
    Submit Requirements:
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: build
      Gerrit-Branch: master
      Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
      Gerrit-Change-Number: 756520
      Gerrit-PatchSet: 1
      Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
      Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
      Gerrit-Comment-Date: Thu, 19 Mar 2026 15:00:13 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Dmitri Shuralyov <dmit...@golang.org>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Dmitri Shuralyov (Gerrit)

      unread,
      Mar 19, 2026, 6:31:55 PM (7 hours ago) Mar 19
      to Brad Fitzpatrick, goph...@pubsubhelper.golang.org, Go LUCI, Dmitri Shuralyov, Dmitri Shuralyov, Kevin Burke, golang-co...@googlegroups.com
      Attention needed from Brad Fitzpatrick

      Dmitri Shuralyov added 1 comment

      File maintner/github.go
      Line 2061, Patchset 1 (Latest): req.Header.Set("Authorization", "Bearer "+tok.AccessToken)
      Dmitri Shuralyov . resolved

      I think we could start using `tok.SetAuthHeader(req)` here now that there's an `oauth2.Token`, if you want. But this should be equivalent at least for today's needs, so either way is fine. (Similarly on line 2309.)

      Brad Fitzpatrick

      This CL was my minimally-sized trial balloon to see if this code had somebody around to still review these things. If so (seems like it!) then I can send more changes. ;)

      Dmitri Shuralyov

      Makes sense.

      seems like it!

      To an extent. :) Issue #37603 is still applicable today. For instance, it's taken me a while to find time to review CL 726080 partly because managing risk of applying comparatively larger changes to maintner is still quite high cost.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Brad Fitzpatrick
      Submit Requirements:
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: build
      Gerrit-Branch: master
      Gerrit-Change-Id: I70a4d2731409fe080390650549a062874afb1d33
      Gerrit-Change-Number: 756520
      Gerrit-PatchSet: 1
      Gerrit-Owner: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@golang.org>
      Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
      Gerrit-Reviewer: Kevin Burke <ke...@burke.dev>
      Gerrit-Attention: Brad Fitzpatrick <brad...@golang.org>
      Gerrit-Comment-Date: Thu, 19 Mar 2026 22:31:51 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Dmitri Shuralyov <dmit...@golang.org>
      Comment-In-Reply-To: Brad Fitzpatrick <brad...@golang.org>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages