cmd/gitmirror: change Gerrit API URL to include "-review"

Using "https://go.googlesource.com" without "-review" as the Gerrit API
URL no longer works. Use "https://go-review.googlesource.com" instead.
This is the canonical Gerrit API URL for the Go project, and it's
already being used in many other places in x/build.

Return and handle errors from gerritMetaMap. Make it so gitmirror treats
an error from gerritMetaMap on startup as fatal, otherwise it would have
started in an incorrect state. While running, skip transient errors from
gerritMetaMap as before, but also log them when they happen.

Remove unneeded trailing slashes from the Gerrit API URLs in packages
maintner/maintnerd and maintner/maintnerd/maintapi for consistency.
This is a no-op as the gerrit client library used to trim them anyway.

Fixes golang/go#32931

Change-Id: Icc20b798946d6317ee89533691f92b1f4d1564f0
Reviewed-on: https://go-review.googlesource.com/c/build/+/184922
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
diff --git a/cmd/gitmirror/gitmirror.go b/cmd/gitmirror/gitmirror.go
index 3ecf33b..18c4767 100644
--- a/cmd/gitmirror/gitmirror.go
+++ b/cmd/gitmirror/gitmirror.go
@@ -78,7 +78,7 @@
 	Timeout: 30 * time.Second, // overkill
 }
 
-var gerritClient = gerrit.NewClient(goBase, gerrit.NoAuth)
+var gerritClient = gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
 
 var (
 	// gitLogFn returns the list of unseen Commits on a Repo,
@@ -225,7 +225,11 @@
 		go startRepo(name, path, true)
 	}
 	if *mirror {
-		for name := range gerritMetaMap() {
+		gerritRepos, err := gerritMetaMap()
+		if err != nil {
+			return fmt.Errorf("gerritMetaMap: %v", err)
+		}
+		for name := range gerritRepos {
 			if seen[name] {
 				// Repo already picked up by dashboard list.
 				continue
@@ -1427,7 +1431,12 @@
 func pollGerritAndTickle() {
 	last := map[string]string{} // repo -> last seen hash
 	for {
-		for repo, hash := range gerritMetaMap() {
+		gerritRepos, err := gerritMetaMap()
+		if err != nil {
+			log.Printf("pollGerritAndTickle: gerritMetaMap failed, skipping: %v", err)
+			gerritRepos = nil
+		}
+		for repo, hash := range gerritRepos {
 			if hash != last[repo] {
 				last[repo] = hash
 				select {
@@ -1493,13 +1502,12 @@
 
 // gerritMetaMap returns the map from repo name (e.g. "go") to its
 // latest master hash.
-// The returned map is nil on any transient error.
-func gerritMetaMap() map[string]string {
+func gerritMetaMap() (map[string]string, error) {
 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	defer cancel()
 	meta, err := gerritClient.GetProjects(ctx, "master")
 	if err != nil {
-		return nil
+		return nil, fmt.Errorf("gerritClient.GetProjects: %v", err)
 	}
 	m := map[string]string{}
 	for repo, v := range meta {
@@ -1507,7 +1515,7 @@
 			m[repo] = master
 		}
 	}
-	return m
+	return m, nil
 }
 
 func (r *Repo) getLocalRefs() (map[string]string, error) {
diff --git a/gerrit/gerrit.go b/gerrit/gerrit.go
index 91d2cdf..ec53276 100644
--- a/gerrit/gerrit.go
+++ b/gerrit/gerrit.go
@@ -27,7 +27,7 @@
 
 // Client is a Gerrit client.
 type Client struct {
-	url  string // URL prefix, e.g. "https://go-review.googlesource.com/a" (without trailing slash)
+	url  string // URL prefix, e.g. "https://go-review.googlesource.com" (without trailing slash)
 	auth Auth
 
 	// HTTPClient optionally specifies an HTTP client to use
@@ -37,7 +37,7 @@
 
 // NewClient returns a new Gerrit client with the given URL prefix
 // and authentication mode.
-// The url should be just the scheme and hostname.
+// The url should be just the scheme and hostname. For example, "https://go-review.googlesource.com".
 // If auth is nil, a default is used, or requests are made unauthenticated.
 func NewClient(url string, auth Auth) *Client {
 	if auth == nil {
diff --git a/maintner/maintnerd/maintapi/api.go b/maintner/maintnerd/maintapi/api.go
index 39b9692..f5a1538 100644
--- a/maintner/maintnerd/maintapi/api.go
+++ b/maintner/maintnerd/maintapi/api.go
@@ -126,7 +126,7 @@
 	val           *apipb.GoFindTryWorkResponse
 }
 
-var tryBotGerrit = gerrit.NewClient("https://go-review.googlesource.com/", gerrit.NoAuth)
+var tryBotGerrit = gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
 
 func (s apiService) GoFindTryWork(ctx context.Context, req *apipb.GoFindTryWorkRequest) (*apipb.GoFindTryWorkResponse, error) {
 	tryCache.Lock()
diff --git a/maintner/maintnerd/maintnerd.go b/maintner/maintnerd/maintnerd.go
index 57f8303..6667ec2 100644
--- a/maintner/maintnerd/maintnerd.go
+++ b/maintner/maintnerd/maintnerd.go
@@ -351,7 +351,7 @@
 	*pubsub = "https://pubsubhelper.golang.org"
 	*watchGithub = strings.Join(goGitHubProjects, ",")
 
-	gerrc := gerrit.NewClient("https://go-review.googlesource.com/", gerrit.NoAuth)
+	gerrc := gerrit.NewClient("https://go-review.googlesource.com", gerrit.NoAuth)
 	projs, err := gerrc.ListProjects(context.Background())
 	if err != nil {
 		log.Fatalf("error listing Go's gerrit projects: %v", err)