internal/task: link to failed builds

This has been bugging me and I keep not getting to it.

For golang/go#63147.

Change-Id: I3c6c6a171fdb5d99887738f561daeaf70a0de975
Reviewed-on: https://go-review.googlesource.com/c/build/+/542655
Auto-Submit: Heschi Kreinick <heschi@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
diff --git a/cmd/relui/main.go b/cmd/relui/main.go
index c8230f8..b246ea9 100644
--- a/cmd/relui/main.go
+++ b/cmd/relui/main.go
@@ -242,6 +242,7 @@
 		},
 		SwarmingClient: &task.RealSwarmingClient{
 			SwarmingClient: swarmingClient,
+			SwarmingURL:    *swarmingURL,
 			ServiceAccount: *swarmingAccount,
 			Realm:          *swarmingRealm,
 			Pool:           *swarmingPool,
diff --git a/internal/task/buildbucket.go b/internal/task/buildbucket.go
index d90d47a..248ed1a 100644
--- a/internal/task/buildbucket.go
+++ b/internal/task/buildbucket.go
@@ -73,7 +73,7 @@
 		return "", false, nil
 	}
 	if build.Status&pb.Status_ENDED_MASK != 0 && build.Status != pb.Status_SUCCESS {
-		return "", true, fmt.Errorf("build failed with status %v: %v", build.Status, build.SummaryMarkdown)
+		return "", true, fmt.Errorf("build failed with status %v, see https://ci.chromium.org/b/%v: %v", build.Status, id, build.SummaryMarkdown)
 	}
 	return build.SummaryMarkdown, true, nil
 }
diff --git a/internal/task/cloudbuild.go b/internal/task/cloudbuild.go
index b844c0a..40af9fd 100644
--- a/internal/task/cloudbuild.go
+++ b/internal/task/cloudbuild.go
@@ -158,7 +158,7 @@
 		return "", false, nil
 	}
 	if b.Status != cloudbuildpb.Build_SUCCESS {
-		return "", false, fmt.Errorf("build %q failed: %v", build.ID, b.FailureInfo)
+		return "", false, fmt.Errorf("build %q failed, see %v: %v", build.ID, build.ResultURL, b.FailureInfo)
 	}
 	return b.StatusDetail, true, nil
 }
diff --git a/internal/task/swarming.go b/internal/task/swarming.go
index ceba480..2c873b5 100644
--- a/internal/task/swarming.go
+++ b/internal/task/swarming.go
@@ -25,8 +25,8 @@
 }
 
 type RealSwarmingClient struct {
-	SwarmingClient              swarming.Client
-	ServiceAccount, Realm, Pool string
+	SwarmingClient                           swarming.Client
+	SwarmingURL, ServiceAccount, Realm, Pool string
 }
 
 func (c *RealSwarmingClient) RunTask(ctx context.Context, dims map[string]string, script string, env map[string]string) (string, error) {
@@ -89,7 +89,7 @@
 		return "", false, nil
 	}
 	if result.State != apipb.TaskState_COMPLETED || result.ExitCode != 0 {
-		return "", true, fmt.Errorf("build failed with state %v and exit code %v: ", result.State, result.ExitCode)
+		return "", true, fmt.Errorf("build failed with state %v and exit code %v, see %v/task?id=%v", result.State, result.ExitCode, c.SwarmingURL, id)
 	}
 	return "", true, nil
 }