Import gazelle

This patch imports gazelle as a linter. It automatically generates
BUILD file entries for Go code and at the same time keeps BUILD files
formatted.

The `tools/lint:run-ci` target is set up to automatically add new Go
repositories as well.

I added a tool at `//tools/go:mirror_go_repos` that needs to be run
before anyone can merge code that uses third-party Go libraries.

Change-Id: I1fbf6761439d45893f5be88d294ccc3c567840ca
Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
diff --git a/tools/lint/BUILD b/tools/lint/BUILD
index 30fc7c9..80b4aa1 100644
--- a/tools/lint/BUILD
+++ b/tools/lint/BUILD
@@ -1,3 +1,5 @@
+load("@ci_configure//:ci.bzl", "RUNNING_IN_CI")
+
 sh_binary(
     name = "gofmt",
     srcs = ["gofmt.sh"],
@@ -16,7 +18,16 @@
     ],
     data = [
         ":gofmt",
+        "//:gazelle-runner",
+        "//tools/go:tweak_gazelle_go_deps",
+        "@go_sdk//:bin/go",
     ],
+    env = {
+        # Prevent CI errors like:
+        #   failed to initialize build cache at
+        #   /var/lib/buildkite-agent/.cache/go-build: permission denied
+        "RUNNING_IN_CI": "1" if RUNNING_IN_CI else "0",
+    },
     deps = [
         "@bazel_tools//tools/bash/runfiles",
     ],
diff --git a/tools/lint/run-ci.sh b/tools/lint/run-ci.sh
index a1bc07c..48c0960 100755
--- a/tools/lint/run-ci.sh
+++ b/tools/lint/run-ci.sh
@@ -14,10 +14,42 @@
   { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
 # --- end runfiles.bash initialization v2 ---
 
+set -o nounset
+
+# Redirect the Go cache on buildkite. Otherwise we run into errors like:
+# "failed to initialize build cache at /var/lib/buildkite-agent/.cache/go-build"
+# due to permission errors.
+if ((RUNNING_IN_CI == 1)); then
+    export GOCACHE=/tmp/lint_go_cache
+fi
+
 gofmt() {
     ./tools/lint/gofmt
 }
 
+gomod() {
+    local -r go="$(readlink -f external/go_sdk/bin/go)"
+    cd "${BUILD_WORKSPACE_DIRECTORY}"
+    "${go}" mod tidy -e
+}
+
+update_repos() {
+    ./gazelle-runner.bash update-repos \
+        -from_file=go.mod \
+        -to_macro=go_deps.bzl%go_dependencies \
+        -prune
+}
+
+gazelle() {
+    ./gazelle-runner.bash
+}
+
+tweak_gazelle_go_deps() {
+    local -r tweaker="$(readlink -f tools/go/tweak_gazelle_go_deps)"
+    cd "${BUILD_WORKSPACE_DIRECTORY}"
+    "${tweaker}" ./go_deps.bzl
+}
+
 git_status_is_clean() {
     cd "${BUILD_WORKSPACE_DIRECTORY}"
     if ! git diff --quiet; then
@@ -29,6 +61,10 @@
 # All the linters that we are going to run.
 readonly -a LINTERS=(
     gofmt
+    gomod
+    update_repos
+    gazelle
+    tweak_gazelle_go_deps
     git_status_is_clean  # This must the last linter.
 )