Merge "Add a gofmt check to CI"
diff --git a/build_tests/hello.go b/build_tests/hello.go
index 4cc584b..d2c4e91 100644
--- a/build_tests/hello.go
+++ b/build_tests/hello.go
@@ -3,5 +3,5 @@
 import "fmt"
 
 func main() {
-    fmt.Println("Hello world")
+	fmt.Println("Hello world")
 }
diff --git a/tools/ci/buildkite.yaml b/tools/ci/buildkite.yaml
index 6792591..55288f9 100644
--- a/tools/ci/buildkite.yaml
+++ b/tools/ci/buildkite.yaml
@@ -8,6 +8,11 @@
   ROBORIO_TARGETS: ${TARGETS} //y2020:download_stripped
 
 steps:
+  - label: "lint"
+    commands:
+      - tools/ci/clean-disk.sh
+      - tools/bazel ${STARTUP} --output_base=../lint_output_base run ${COMMON} --config=k8 //tools/lint:run-ci
+
   - label: "x86_64"
     commands:
       - tools/ci/clean-disk.sh
diff --git a/tools/lint/BUILD b/tools/lint/BUILD
new file mode 100644
index 0000000..30fc7c9
--- /dev/null
+++ b/tools/lint/BUILD
@@ -0,0 +1,23 @@
+sh_binary(
+    name = "gofmt",
+    srcs = ["gofmt.sh"],
+    data = [
+        "@go_sdk//:bin/gofmt",
+    ],
+    deps = [
+        "@bazel_tools//tools/bash/runfiles",
+    ],
+)
+
+sh_binary(
+    name = "run-ci",
+    srcs = [
+        "run-ci.sh",
+    ],
+    data = [
+        ":gofmt",
+    ],
+    deps = [
+        "@bazel_tools//tools/bash/runfiles",
+    ],
+)
diff --git a/tools/lint/gofmt.sh b/tools/lint/gofmt.sh
new file mode 100755
index 0000000..b040d35
--- /dev/null
+++ b/tools/lint/gofmt.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# --- begin runfiles.bash initialization v2 ---
+# Copy-pasted from the Bazel Bash runfiles library v2.
+set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
+source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
+  source "$0.runfiles/$f" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+  { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
+# --- end runfiles.bash initialization v2 ---
+
+readonly GOFMT="$(rlocation go_sdk/bin/gofmt)"
+
+# Run everything from the root of the tree.
+cd "${BUILD_WORKSPACE_DIRECTORY}"
+
+# Find all the Go files in the repo.
+go_files=($(git ls-tree --name-only --full-tree -r @ \
+    | grep -v '^third_party/' \
+    | (grep '\.go$' || :)))
+
+# If we have any Go files, format them.
+if ((${#go_files[@]} > 0)); then
+    exec "${GOFMT}" -w "${go_files[@]}"
+fi
diff --git a/tools/lint/run-ci.sh b/tools/lint/run-ci.sh
new file mode 100755
index 0000000..a1bc07c
--- /dev/null
+++ b/tools/lint/run-ci.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Perform runfile initialization here so that child processes have a proper
+# RUNFILES_DIR variable set.
+
+# --- begin runfiles.bash initialization v2 ---
+# Copy-pasted from the Bazel Bash runfiles library v2.
+set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
+source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
+  source "$0.runfiles/$f" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+  source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
+  { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
+# --- end runfiles.bash initialization v2 ---
+
+gofmt() {
+    ./tools/lint/gofmt
+}
+
+git_status_is_clean() {
+    cd "${BUILD_WORKSPACE_DIRECTORY}"
+    if ! git diff --quiet; then
+        echo "One or more linters appear to have made changes to your code!" >&2
+        return 1
+    fi
+}
+
+# All the linters that we are going to run.
+readonly -a LINTERS=(
+    gofmt
+    git_status_is_clean  # This must the last linter.
+)
+
+failure=0
+for linter in "${LINTERS[@]}"; do
+    if ! (eval "${linter}"); then
+        failure=1
+    fi
+done
+
+if ((failure != 0)); then
+    echo "One or more linters failed." >&2
+    cd "${BUILD_WORKSPACE_DIRECTORY}"
+    git --no-pager diff || :
+    exit "${failure}"
+fi
+
+exit 0