Combine scouting webserver and scouting web pages

This patch adds a new `//scouting` target that runs the webserver and
points it at our web pages. This will be the target that folks can use
to run the entire scouting application.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I62acfb271b856f9d238b17ecc3573f31a07bab41
diff --git a/scouting/BUILD b/scouting/BUILD
index 836e5c3..9b8adee 100644
--- a/scouting/BUILD
+++ b/scouting/BUILD
@@ -1,4 +1,5 @@
 load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
+load("//tools/build_rules:js.bzl", "turn_files_into_runfiles")
 
 go_binary(
     name = "sql_demo",
@@ -15,3 +16,31 @@
     visibility = ["//visibility:private"],
     deps = ["@com_github_mattn_go_sqlite3//:go-sqlite3"],
 )
+
+turn_files_into_runfiles(
+    name = "main_bundle_compiled_runfiles",
+    files = "//scouting/www:main_bundle_compiled",
+)
+
+sh_binary(
+    name = "scouting",
+    srcs = [
+        "scouting.sh",
+    ],
+    data = [
+        ":main_bundle_compiled_runfiles",
+        "//scouting/webserver",
+        "//scouting/www:index.html",
+        "//scouting/www:zonejs_copy",
+    ],
+)
+
+py_test(
+    name = "scouting_test",
+    srcs = [
+        "scouting_test.py",
+    ],
+    data = [
+        ":scouting",
+    ],
+)
diff --git a/scouting/README.md b/scouting/README.md
new file mode 100644
index 0000000..4c43a2a
--- /dev/null
+++ b/scouting/README.md
@@ -0,0 +1,15 @@
+Scouting web server
+================================================================================
+
+The `//scouting` target runs the webserver and hosts all the web pages. Run it
+like so:
+
+    $ bazel run //scouting
+
+You can customize the port like so:
+
+    $ bazel run //scouting -- --port 1234
+
+See all options like this:
+
+    $ bazel run //scouting -- --help
diff --git a/scouting/scouting.sh b/scouting/scouting.sh
new file mode 100755
index 0000000..669cf22
--- /dev/null
+++ b/scouting/scouting.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script runs the webserver and asks it to host all the web pages.
+
+exec \
+    scouting/webserver/webserver_/webserver \
+    -directory scouting/www/ \
+    "$@"
diff --git a/scouting/scouting_test.py b/scouting/scouting_test.py
new file mode 100644
index 0000000..3b62224
--- /dev/null
+++ b/scouting/scouting_test.py
@@ -0,0 +1,38 @@
+# TODO(phil): Delete this and replace it with a selenium test. Preferably
+# written in either Javascript or Go.
+
+import socket
+import subprocess
+import time
+import unittest
+import urllib.request
+
+class TestDebugCli(unittest.TestCase):
+
+    def setUp(self):
+        self.webserver = subprocess.Popen(["scouting/scouting"])
+
+        # Wait for the server to respond to requests.
+        while True:
+            try:
+                connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+                connection.connect(("localhost", 8080))
+                connection.close()
+                break
+            except ConnectionRefusedError:
+                connection.close()
+                time.sleep(0.01)
+
+    def tearDown(self):
+        self.webserver.terminate()
+        self.webserver.wait()
+
+    def test_index_html(self):
+        """Makes sure that we the scouting server is serving our main index.html file."""
+        with urllib.request.urlopen("http://localhost:8080/") as file:
+            html = file.read().decode("utf-8")
+        self.assertIn("<my-app></my-app>", html)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/scouting/www/BUILD b/scouting/www/BUILD
index c22ea38..aa2ad7b 100644
--- a/scouting/www/BUILD
+++ b/scouting/www/BUILD
@@ -3,6 +3,10 @@
 load("@npm//@bazel/concatjs:index.bzl", "concatjs_devserver")
 load("@npm//@babel/cli:index.bzl", "babel")
 
+exports_files([
+    "index.html",
+])
+
 ts_library(
     name = "app",
     srcs = glob([
@@ -46,14 +50,29 @@
         "@npm//@angular/compiler-cli",
     ],
     output_dir = True,
+    visibility = ["//visibility:public"],
+)
+
+# Create a copy of zone.js here so that we can have a predictable path to
+# source it from on the webserver.
+genrule(
+    name = "zonejs_copy",
+    srcs = [
+        "@npm//:node_modules/zone.js/dist/zone.min.js",
+    ],
+    outs = [
+        "npm/node_modules/zone.js/dist/zone.min.js",
+    ],
+    cmd = "cp $(SRCS) $(OUTS)",
+    visibility = ["//visibility:public"],
 )
 
 concatjs_devserver(
     name = "devserver",
     serving_path = "/main_bundle.js",
     static_files = [
-        ":index.html",
-        "@npm//:node_modules/zone.js/dist/zone.min.js",
+        "index.html",
+        ":zonejs_copy",
     ],
     deps = [":main_bundle_compiled"],
 )