Merge "Document how to add new NPM binaries"
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index 04f749d..8b4bece 100644
--- a/Documentation/dev-bazel.txt
+++ b/Documentation/dev-bazel.txt
@@ -417,6 +417,92 @@
 details. Users should watch the cache sizes and clean them manually if
 necessary.
 
+[[npm-binary]]
+== NPM Binaries
+
+Parts of the PolyGerrit build require running NPM-based JavaScript programs as
+"binaries". We don't attempt to resolve and download NPM dependencies at build
+time, but instead use pre-built bundles of the NPM binary along with all its
+dependencies. Some packages on
+link:https://docs.npmjs.com/misc/registry[registry.npmjs.org] come with their
+dependencies bundled, but this is the exception rather than the rule. More
+commonly, to add a new binary to this list, you will need to bundle the binary
+yourself.
+
+[NOTE]
+We can only use binaries that meet certain licensing requirements, and that do
+not include any native code.
+
+Start by checking that the license and file types of the bundle are acceptable:
+[source,bash]
+----
+  gerrit_repo=/path/to/gerrit
+  package=some-npm-package
+  version=1.2.3
+
+  npm install -g license-checker && \
+  rm -rf /tmp/$package-$version && mkdir -p /tmp/$package-$version && \
+  cd /tmp/$package-$version && \
+  npm install $package@$version && \
+  license-checker | grep licenses: | sort -u
+----
+
+This will output a list of the different licenses used by the package and all
+its transitive dependencies. We can only legally distribute a bundle via our
+storage bucket if the licenses allow us to do so. As long as all of the listed
+license are allowed by
+link:https://opensource.google.com/docs/thirdparty/licenses/[Google's
+standards]. Any `by_exception_only`, commercial, prohibited, or unlisted
+licenses are not allowed; otherwise, it is ok to distribute the source. If in
+doubt, contact a maintainer who is a Googler.
+
+Next, check the file types:
+[source,bash]
+----
+  cd /tmp/$package-$version
+  find . -type f | xargs file | grep -v 'ASCII\|UTF-8\|empty$'
+----
+
+If you see anything that looks like a native library or binary, then we can't
+use the bundle.
+
+If everything looks good, create the bundle, and note the SHA-1:
+[source,bash]
+----
+  $gerrit_repo/tools/js/npm_pack.py $package $version && \
+  sha1sum $package-$version.tgz
+----
+
+This creates a file named `$package-$version.tgz` in your working directory.
+
+Any project maintainer can upload this file to the
+link:https://console.cloud.google.com/storage/browser/gerrit-maven/npm-packages[storage
+bucket].
+
+Finally, add the new binary to the build process:
+----
+  # WORKSPACE
+  npm_binary(
+      name = "some-npm-package",
+      repository = GERRIT,
+  )
+
+  # lib/js/npm.bzl
+  NPM_VERSIONS = {
+    ...
+    "some-npm-package": "1.2.3",
+  }
+
+  NPM_SHA1S = {
+    ...
+    "some-npm-package": "<sha1>",
+  }
+----
+
+To use the binary from the Bazel build, you need to use the `run_npm_binary.py`
+wrapper script. For an example, see the use of `crisper` in `tools/bzl/js.bzl`.
+
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/WORKSPACE b/WORKSPACE
index 96f3903..e490c63 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -946,6 +946,10 @@
 
 load("//tools/bzl:js.bzl", "bower_archive", "npm_binary")
 
+# NPM binaries bundled along with their dependencies.
+#
+# For full instructions on adding new binaries to the build, see
+# http://gerrit-review.googlesource.com/Documentation/dev-bazel.html#npm-binary
 npm_binary(
     name = "bower",
 )
diff --git a/tools/js/npm_pack.py b/tools/js/npm_pack.py
index d817701..f14262a 100755
--- a/tools/js/npm_pack.py
+++ b/tools/js/npm_pack.py
@@ -15,8 +15,8 @@
 
 """This downloads an NPM binary, and bundles it with its dependencies.
 
-This is used to assemble a pinned version of crisper, hosted on the
-Google storage bucket ("repository=GERRIT" in WORKSPACE).
+For full instructions on adding new binaries to the build, see
+http://gerrit-review.googlesource.com/Documentation/dev-bazel.html#npm-binary
 """
 
 from __future__ import print_function