Bazel IntelliJ plugin support

This eliminates the need for manually synchronizing generated files.

The plugin authors advise against checking in the .iwjb directory,
which we resolutely ignore. The recommended method is to provide a
template .bazelproject file that everyone needs to manually import and
update. However, checking in the directory is supported and no different
than checking in .idea. This allows us to version things like watchers
and run configurations, at the expense of requiring everyone to use
the same IntelliJ and Bazel plugin versions.

How it works:

- Source code and execroot paths are identical inside and outside the
  container. This requires a bind mount. To avoid conflicts with a
  local Bazel instance, a separate directory is used.

  The wrapper script injects a --output_user_root startup parameter.
  We cannot set this in .bazelrc since we cannot substitute the
  user home. This means that running bazel inside the container,
  without the wrapper, will no longer work/blow up the overlayfs.

  Did anyone do this?

- The tmpfs and other caches are eliminated.
  Forcing it hasn't been ideal anyway due to
  the excessive memory usage, and it can still be accomplished
  by mounting a tmpfs to `~/.cache/bazel-nxt` or symlinking it to
  `/dev/shm` or similar (set proper permissions!).

- The plugin configures a custom local repository that has helper
  scripts. Since we need to be on the same IntelliJ version, we can
  simply hardcode the path and bind mount it (read only).

  The alternative would be to copy the files into the container and
  override the command line option using sync_flags
  (https://github.com/bazelbuild/intellij/issues/397), but bind
  mounting seems muche easier at no disadvantage.

- IntelliJ needs a somewhat obscure custom startup option (see README)
  for BEP temp files (https://github.com/bazelbuild/intellij/issues/407).

Test Plan:
- Running tests works:

  {F16996}

- Full and partial sync works:

  {F17000}

- Updating a protobuf file triggered the watcher, which rebuilt the
  generated files. After triggering an source sync, the changes
  are visible in the IDE (I suspect that IntelliJ does not inotify-
  watch the generated files since they are outside the project directory.

X-Origin-Diff: phab/D263
GitOrigin-RevId: 39c50665575c2a0131c492385b0981b7ee2588d8
diff --git a/README.md b/README.md
index 6aadcd7..9321fd6 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,9 @@
 
 ## Environment
 
-All builds should be executed using the shipped `nexantic-dev` container which is automatically built by the create
-script.
+We assume a Fedora 30 or 31 host system provisioned using rW, and IntelliJ as the IDE.
 
-The container contains all necessary dependencies and env configurations necessary to get started right away.
+For better reproducibility, all builds are executed in containers.
 
 #### Usage
 
@@ -15,7 +14,36 @@
 
 Spinning down: `scripts/destroy_container.sh` 
 
-Running commands: `scripts/run_in_container.sh @`
+Running commands: `scripts/run_in_container.sh <...>`
 
-Using bazel: `scripts/bin/bazel @`
+Using bazel using a wrapper script: `scripts/bin/bazel <...>` (add to your local $PATH for convenience)
  
+#### IntelliJ
+
+This repository is compatible with the IntelliJ Bazel plugin. All commands run inside the container, and
+necessary paths are mapped into the container.
+
+We check the entire .ijwb project directory into the repository, which requires everyone to use the latest
+version of both IntelliJ and the Bazel plugin, but eliminates manual setup steps.
+
+The following steps are necessary:
+
+- Install Google's official Bazel plugin in IntelliJ.
+
+- Add the absolute path to your ~/.cache/bazel-nxt folder to your idea64.vmoptions (Help → Edit Custom VM Options)
+  and restart IntelliJ:
+
+  `-Dbazel.bep.path=/home/leopold/.cache/bazel-nxt`
+  
+- Set "*Bazel Binary Location*" in Other Settings → Bazel Settings to the absolute path of scripts/bin/bazel.
+  This is a wrapper that will execute Bazel inside the container.
+
+- Open the `.ijwb` folder as IntelliJ project.
+  
+- Disable Vgo support for the project.
+
+- Run a non-incremental sync in IntelliJ 
+
+The plugin will automatically resolve paths for generated files.
+
+If you do not use IntelliJ, you need to use the scripts/bazel_copy_generated_for_ide.sh script to copy files locally.
diff --git a/scripts/bin/bazel b/scripts/bin/bazel
index c0bd7e4..0773669 100755
--- a/scripts/bin/bazel
+++ b/scripts/bin/bazel
@@ -1,5 +1,4 @@
 #!/bin/bash
 set -euo pipefail
 
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-$DIR/../run_in_container.sh bazel $@
+exec podman exec -it nexantic-dev bazel --output_user_root ${HOME}/.cache/bazel-nxt $@
diff --git a/scripts/create_container.sh b/scripts/create_container.sh
index 449bdb1..a2a5d61 100755
--- a/scripts/create_container.sh
+++ b/scripts/create_container.sh
@@ -30,14 +30,25 @@
 
 podman pod create --name nexantic
 
-# TODO(leo): mount .cache/bazel on a volume (waiting for podman issue to be fixed)
-# https://github.com/containers/libpod/issues/4318
+# Mount bazel root to identical paths inside and outside the container.
+# This caches build state even if the container is destroyed, and
+BAZEL_ROOT=${HOME}/.cache/bazel-nxt
+
+# The Bazel plugin injects a Bazel repository into the sync command line.
+# Look up the latest copy of it in either the user config folder
+# or the Jetbrains Toolbox dir (for non-standard setups).
+ASPECT_PATH=$(
+  dirname $(
+    find ~/.IntelliJIdea*/config/plugins/ijwb/* ~/.local/share/JetBrains \
+    -name intellij_info_impl.bzl -printf "%T+\t%p\n" | sort | tail -n 1))
+
+mkdir -p ${BAZEL_ROOT}
+
 podman run -it -d \
-    -v $(pwd):/work \
-    -v smalltown-gopath:/user/go/pkg \
-    -v smalltown-gobuildcache:/user/.cache/go-build \
-    -v smalltown-bazelcache:/user/.cache/bazel/_bazel_root/cache \
-    --tmpfs=/user/.cache/bazel:exec \
+    -v $(pwd):$(pwd) \
+    -w $(pwd) \
+    --volume=${BAZEL_ROOT}:${BAZEL_ROOT} \
+    -v ${ASPECT_PATH}:${ASPECT_PATH}:ro \
     --device /dev/kvm \
     --privileged \
     --pod nexantic \
diff --git a/scripts/rebuild_generated.sh b/scripts/rebuild_generated.sh
deleted file mode 100755
index 8edcf65..0000000
--- a/scripts/rebuild_generated.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-bazel build core/api/... && scripts/bazel_copy_generated_for_ide.sh