feat: depend on devserver binaries

Depend on devserver binaries instead of compiling from source. This
won't require compilation of the go compiler when we start the dev
server.

Closes #347

PiperOrigin-RevId: 225265288
diff --git a/BUILD.bazel b/BUILD.bazel
index d52ad79..997940e 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -20,6 +20,7 @@
 # gazelle:exclude node_modules
 load("@bazel_gazelle//:def.bzl", "gazelle")
 load("@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "js_library")
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 # ts_library defaults to this label in the top-level package.
 # Point to where the file actually lives.
@@ -70,3 +71,24 @@
     templated_args = ["--node_options=--expose-gc"],
     visibility = ["//visibility:public"],
 )
+
+# Produces the release we publish to GitHub. Users download this starlark package
+# to get the @build_bazel_rules_typescript workspace.
+# It's the companion of the @bazel/typescript, @bazel/karma, etc npm packages.
+pkg_tar(
+    name = "release",
+    extension = "tgz",
+    srcs = [
+      "BUILD.bazel",
+      "AUTHORS",
+      "defs.bzl",
+      "LICENSE",
+      "package.bzl",
+      "WORKSPACE",
+    ],
+    deps = [
+      "//devserver:package",
+      "//internal:package",
+      "//third_party/github.com/bazelbuild/bazel/src/main/protobuf:package",
+    ],
+)
diff --git a/README.md b/README.md
index 803d0a3..a1a344b 100644
--- a/README.md
+++ b/README.md
@@ -345,5 +345,9 @@
 1. `npm config set tag-version-prefix ''`
 1. `npm version minor -m 'rel: %s'` (replace `minor` with `patch` if no breaking changes)
 1. Build npm packages and publish them: `bazel run //internal:npm_package.publish && bazel run //internal/karma:npm_package.publish`
+1. `bazel build :release`
 1. `git push && git push --tags`
+1. (Manual for now) go to the [releases] page, edit the new release, and attach the `bazel-bin/release.tgz` file
 1. (Temporary): submit a google3 CL to update the versions in package.bzl and package.json
+
+[releases]: https://github.com/bazelbuild/rules_typescript/releases
diff --git a/devserver/BUILD.bazel b/devserver/BUILD.bazel
index 54fe5ea..7b83af1 100644
--- a/devserver/BUILD.bazel
+++ b/devserver/BUILD.bazel
@@ -1,4 +1,7 @@
+package(default_visibility = ["//visibility:public"])
+
 load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 go_library(
     name = "go_default_library",
@@ -16,3 +19,79 @@
     embed = [":go_default_library"],
     visibility = ["//visibility:public"],
 )
+
+config_setting(
+    name = "darwin_amd64",
+    constraint_values = [
+        "@bazel_tools//platforms:osx",
+        "@bazel_tools//platforms:x86_64",
+    ]
+)
+
+config_setting(
+    name = "linux_amd64",
+    constraint_values = [
+        "@bazel_tools//platforms:linux",
+        "@bazel_tools//platforms:x86_64",
+    ]
+)
+
+config_setting(
+    name = "windows_amd64",
+    constraint_values = [
+        "@bazel_tools//platforms:windows",
+        "@bazel_tools//platforms:x86_64",
+    ]
+)
+
+filegroup(
+    name = "server",
+    srcs = select({
+        ":darwin_amd64": ["devserver-darwin_amd64"],
+        ":linux_amd64": ["devserver-linux_amd64"],
+        ":windows_amd64": ["devserver-windows_amd64.exe"],
+    }),
+    # Don't build on CI
+    tags = ["manual"],
+)
+
+go_binary(
+    name = "devserver-windows",
+    goarch = "amd64",
+    goos = "windows",
+    pure = "on",
+    out = "devserver-windows_amd64.exe",
+    embed = [":go_default_library"],
+    visibility = ["//visibility:public"],
+)
+
+go_binary(
+    name = "devserver-darwin",
+    goarch = "amd64",
+    goos = "darwin",
+    pure = "on",
+    out = "devserver-darwin_amd64",
+    embed = [":go_default_library"],
+    visibility = ["//visibility:public"],
+)
+
+go_binary(
+    name = "devserver-linux",
+    goarch = "amd64",
+    goos = "linux",
+    pure = "on",
+    out = "devserver-linux_amd64",
+    embed = [":go_default_library"],
+    visibility = ["//visibility:public"],
+)
+
+pkg_tar(
+    name = "package",
+    srcs = [
+        ":devserver-windows",
+        ":devserver-darwin",
+        ":devserver-linux",
+        "BUILD.bazel",
+    ],
+    package_dir = "devserver",
+)
diff --git a/internal/BUILD.bazel b/internal/BUILD.bazel
index 4d3b30e..eb0fb54 100644
--- a/internal/BUILD.bazel
+++ b/internal/BUILD.bazel
@@ -26,6 +26,7 @@
 
 load("//internal:defaults.bzl", "ts_library")
 load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "jasmine_node_test", "npm_package")
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 # Vanilla typescript compiler: run the tsc.js binary distributed by TypeScript
 nodejs_binary(
@@ -150,3 +151,42 @@
         ":worker_protocol_copy",
     ],
 )
+
+pkg_tar(
+  name = "tsc_wrapped_pkg",
+  srcs = glob([
+    "tsc_wrapped/**",
+  ]),
+  package_dir = "tsc_wrapped",
+)
+
+pkg_tar(
+    name = "common_pkg",
+    srcs = [
+        "common/compilation.bzl",
+        "common/json_marshal.bzl",
+        "common/module_mappings.bzl",
+        "common/tsconfig.bzl",
+    ],
+    package_dir = "common",
+)
+
+pkg_tar(
+  name = "package",
+  srcs = [
+    "build_defs.bzl",
+    "ts_config.bzl",
+    "ts_repositories.bzl",
+    "BUILD.bazel",
+    "yarn.lock",
+    "package.json",
+  ],
+  package_dir = "internal",
+  deps = [
+    ":tsc_wrapped_pkg",
+    ":common_pkg",
+    "//internal/karma:package",
+    "//internal/protobufjs:package",
+    "//internal/devserver:package",
+  ]
+)
diff --git a/internal/devserver/BUILD b/internal/devserver/BUILD
index bddd412..0f72ac3 100644
--- a/internal/devserver/BUILD
+++ b/internal/devserver/BUILD
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
+
 licenses(["notice"])  # Apache 2.0
 
 package(default_visibility = [
@@ -27,3 +29,30 @@
     name = "source_tree",
     srcs = glob(["**/*"]),
 )
+
+# Do a simple replacement needed to make the local development differ from how
+# our release is used.
+# NB: doesn't work on Windows, so we have to release from Mac/Linux for now.
+genrule(
+    name = "patched_devserver_bzl",
+    srcs = ["ts_devserver.bzl"],
+    outs = ["patched/ts_devserver.bzl"],
+    cmd = """sed 's#"//devserver:devserver"#"//devserver:server"#' < $< > $@""",
+)
+
+# Remove the "patched/" directory prefix so that the ts_devserver.bzl ends up in
+# the same path in the final tar as it had in our local repo.
+pkg_tar(
+    name = "strip_workaround",
+    srcs = [":patched_devserver_bzl"],
+)
+
+pkg_tar(
+    name = "package",
+    srcs = [
+        "BUILD",
+    ],
+    package_dir = "devserver",
+    deps = ["strip_workaround"],
+    visibility = ["//internal:__pkg__"],
+)
diff --git a/internal/devserver/README.md b/internal/devserver/README.md
index 86e920d..7000c25 100644
--- a/internal/devserver/README.md
+++ b/internal/devserver/README.md
@@ -6,4 +6,4 @@
 
 This devserver includes the "concatjs" bundling strategy. If you use a different
 frontend server, you should port this library to whatever language you run in.
-Contributions of such libraries are welcome.
+
diff --git a/internal/devserver/ts_devserver.bzl b/internal/devserver/ts_devserver.bzl
index b8fc54d..1cafabf 100644
--- a/internal/devserver/ts_devserver.bzl
+++ b/internal/devserver/ts_devserver.bzl
@@ -164,7 +164,12 @@
         ),
         "_requirejs_script": attr.label(allow_single_file = True, default = Label("@build_bazel_rules_typescript_devserver_deps//node_modules/requirejs:require.js")),
         "_devserver": attr.label(
-            default = Label("//devserver"),
+            # For local development in rules_typescript, we build the devserver from sources.
+            # This requires that we have the go toolchain available.
+            # NB: this value is replaced by "//devserver:server" in the packaged distro
+            # //devserver:server is the pre-compiled binary.
+            # That means that our users don't need the go toolchain.
+            default = Label("//devserver:devserver"),
             executable = True,
             cfg = "host",
         ),
diff --git a/internal/karma/BUILD.bazel b/internal/karma/BUILD.bazel
index 2c5bb4a..1726465 100644
--- a/internal/karma/BUILD.bazel
+++ b/internal/karma/BUILD.bazel
@@ -1,4 +1,5 @@
 package(default_visibility = ["//visibility:public"])
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 exports_files([
     "test-main.js",
@@ -69,3 +70,15 @@
         ":license_copy",
     ],
 )
+
+pkg_tar(
+  name = "package",
+  srcs = [
+    "ts_web_test.bzl",
+    "BUILD.bazel",
+    "yarn.lock",
+    "package.json",
+  ],
+  package_dir = "karma"
+)
+
diff --git a/internal/protobufjs/BUILD.bazel b/internal/protobufjs/BUILD.bazel
index 8cb2f77..60085a7 100644
--- a/internal/protobufjs/BUILD.bazel
+++ b/internal/protobufjs/BUILD.bazel
@@ -1,6 +1,7 @@
 package(default_visibility = ["//visibility:public"])
 
 load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 exports_files([
     "node_modules/protobufjs/dist/minimal/protobuf.min.js",
@@ -53,3 +54,15 @@
     entry_point = "protobufjs/bin/pbts",
     install_source_map_support = False,
 )
+
+pkg_tar(
+  name = "package",
+  srcs = [
+    "ts_proto_library.bzl",
+    "BUILD.bazel",
+    "yarn.lock",
+    "package.json",
+  ],
+  package_dir = "protobufjs"
+)
+
diff --git a/third_party/github.com/bazelbuild/bazel/src/main/protobuf/BUILD.bazel b/third_party/github.com/bazelbuild/bazel/src/main/protobuf/BUILD.bazel
index 69a478b..3b835fd 100644
--- a/third_party/github.com/bazelbuild/bazel/src/main/protobuf/BUILD.bazel
+++ b/third_party/github.com/bazelbuild/bazel/src/main/protobuf/BUILD.bazel
@@ -1,5 +1,8 @@
+package(default_visibility = ["//:__pkg__"])
+
 load("@io_bazel_rules_go//go:def.bzl", "go_library")
 load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 licenses(["notice"])  # Apache 2.0
 
@@ -25,3 +28,13 @@
     importpath = "github.com/bazelbuild/rules_typescript/third_party/github.com/bazelbuild/bazel/src/main/protobuf",
     visibility = ["//visibility:public"],
 )
+
+pkg_tar(
+  name = "package",
+  srcs = [
+    "BUILD.bazel",
+    "worker_protocol.proto",
+  ],
+  package_dir = "third_party/github.com/bazelbuild/bazel/src/main/protobuf",
+)
+