cmd/watchflakes: set RPC deadline

The LUCI RPC call sometimes hangs. Set a deadline so we can
restart.

For golang/go#66687.

Change-Id: Ia61d5d91ac78915cfc18cf37e85550b4c4fbb146
Reviewed-on: https://go-review.googlesource.com/c/build/+/601797
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/cmd/watchflakes/main.go b/cmd/watchflakes/main.go
index 89de6ad..23e36a5 100644
--- a/cmd/watchflakes/main.go
+++ b/cmd/watchflakes/main.go
@@ -92,16 +92,18 @@
 	}
 
 	// Load LUCI dashboards
-	ctx := context.Background()
 	c := NewLUCIClient(runtime.GOMAXPROCS(0) * 4)
 	c.TraceSteps = true
 
 	var ticker *time.Ticker
+	timeout := 30 * time.Minute // default timeout for one-off run
 	if *repeat != 0 {
 		ticker = time.NewTicker(*repeat)
+		timeout = *repeat * 2 // expected to finish in one repeat cycle, give some extra room
 	}
 Repeat:
 	startTime := time.Now()
+	ctx, cancel := context.WithTimeout(context.Background(), timeout)
 	var boards []*Dashboard
 	if *build == "" {
 		// fetch the dashboard
@@ -110,7 +112,10 @@
 		if err != nil {
 			log.Fatalln("ListBoards:", err)
 		}
-		c.ReadBoards(ctx, boards, startTime.Add(-timeLimit))
+		err = c.ReadBoards(ctx, boards, startTime.Add(-timeLimit))
+		if err != nil {
+			log.Fatalln("ReadBoards:", err)
+		}
 		skipBrokenCommits(boards)
 		skipBrokenBuilders(boards)
 	} else {
@@ -268,6 +273,8 @@
 		}
 	}
 
+	cancel()
+
 	log.Printf("Done. %d boards, %d failures, %d issues, %d posts, in %v\n", len(boards), len(failRes), len(issues), posts, time.Since(startTime))
 
 	if *repeat != 0 {