cmd/coordinator: tag TryBot comments on Gerrit as autogenerated

This will only show the latest one in the web UI unless "Show all
entries" is checked.

Also added the status link to the in progress failure notification, as
the previous one won't be as accessible.

Fixes golang/go#39828

Change-Id: I9d81006ac3822a9dc0201637bbb0ce1bae860cc7
Reviewed-on: https://go-review.googlesource.com/c/build/+/310011
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
Trust: Alexander Rakoczy <alex@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Alexander Rakoczy <alex@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/cmd/coordinator/coordinator.go b/cmd/coordinator/coordinator.go
index cfbf1d3..278e7fc 100644
--- a/cmd/coordinator/coordinator.go
+++ b/cmd/coordinator/coordinator.go
@@ -1390,6 +1390,12 @@
 	return ts.trySetState.clone()
 }
 
+// tryBotsTag returns a Gerrit tag for the TryBots state s. See Issue 39828 and
+// https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#review-input.
+func tryBotsTag(s string) string {
+	return "autogenerated:trybots~" + s
+}
+
 // notifyStarting runs in its own goroutine and posts to Gerrit that
 // the trybots have started on the user's CL with a link of where to watch.
 func (ts *trySet) notifyStarting() {
@@ -1424,7 +1430,8 @@
 	}
 
 	// Ignore error. This isn't critical.
-	gerritClient.SetReview(ctx, ts.ChangeTriple(), ts.Commit, gerrit.ReviewInput{Message: msg})
+	gerritClient.SetReview(ctx, ts.ChangeTriple(), ts.Commit,
+		gerrit.ReviewInput{Message: msg, Tag: tryBotsTag("beginning")})
 }
 
 // awaitTryBuild runs in its own goroutine and waits for a build in a
@@ -1558,12 +1565,13 @@
 
 		if numFail == 1 && remain > 0 {
 			if err := pool.NewGCEConfiguration().GerritClient().SetReview(context.Background(), ts.ChangeTriple(), ts.Commit, gerrit.ReviewInput{
-				Message: fmt.Sprintf(
-					"Build is still in progress...\n"+
-						"This change failed on %s:\n"+
-						"See %s\n\n"+
-						"Other builds still in progress; subsequent failure notices suppressed until final report. "+failureFooter,
-					bs.NameAndBranch(), logURL),
+				Message: fmt.Sprintf("Build is still in progress... "+
+					"Status page: https://farmer.golang.org/try?commit=%s\n"+
+					"Failed on %s: %s\n"+
+					"Other builds still in progress; subsequent failure notices suppressed until final report.\n\n"+
+					failureFooter,
+					ts.Commit[:8], bs.NameAndBranch(), logURL),
+				Tag: tryBotsTag("progress"),
 			}); err != nil {
 				log.Printf("Failed to call Gerrit: %v", err)
 				return
@@ -1579,16 +1587,19 @@
 
 		var buf bytes.Buffer
 		var score int
+		var tag string
 		if numFail == 0 {
 			score = 1
 			fmt.Fprintf(&buf, "%s are happy.\n", name)
+			tag = tryBotsTag("happy")
 		} else {
 			score = -1
 			ts.mu.Lock()
 			errMsg := ts.errMsg.String()
 			ts.mu.Unlock()
-			fmt.Fprintf(&buf, "%d of %d %s failed:\n%s\n"+failureFooter,
+			fmt.Fprintf(&buf, "%d of %d %s failed.\n%s\n"+failureFooter,
 				numFail, len(ts.builds), name, errMsg)
+			tag = tryBotsTag("failed")
 		}
 		fmt.Fprintln(&buf)
 		if len(ts.slowBots) > 0 {
@@ -1614,6 +1625,7 @@
 			Labels: map[string]int{
 				"TryBot-Result": score,
 			},
+			Tag: tag,
 		}); err != nil {
 			log.Printf("Failed to call Gerrit: %v", err)
 			return
diff --git a/gerrit/gerrit.go b/gerrit/gerrit.go
index e7f7fa8..9ec0721 100644
--- a/gerrit/gerrit.go
+++ b/gerrit/gerrit.go
@@ -526,6 +526,7 @@
 type ReviewInput struct {
 	Message string         `json:"message,omitempty"`
 	Labels  map[string]int `json:"labels,omitempty"`
+	Tag     string         `json:"tag,omitempty"`
 
 	// Comments contains optional per-line comments to post.
 	// The map key is a file path (such as "src/foo/bar.go").