app/mailman-web: create

There's a lot of ugly hacks here, but this has been the state of prod
for months now, so we should reflect that.
Also, this bumps a bunch of workspace deps.

Change-Id: I744e0d3aff27036cfed73416cf442c7d62444a8b
Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1473
Reviewed-by: q3k <q3k@hackerspace.pl>
diff --git a/app/mailman-web/BUILD b/app/mailman-web/BUILD
new file mode 100644
index 0000000..f79e0e3
--- /dev/null
+++ b/app/mailman-web/BUILD
@@ -0,0 +1,150 @@
+load("@pydeps//:requirements.bzl", "requirement")
+load("@rules_python//python:defs.bzl", "py_binary")
+load("@io_bazel_rules_docker//python:image.bzl", "py_layer")
+load("@io_bazel_rules_docker//python3:image.bzl", "py3_image")
+load("@io_bazel_rules_docker//container:container.bzl", "container_layer", "container_image")
+load("@io_bazel_rules_docker//docker/util:run.bzl",  "container_run_and_extract", "container_run_and_commit_layer")
+load("@io_bazel_rules_docker//docker/package_managers:download_pkgs.bzl", "download_pkgs")
+load("@io_bazel_rules_docker//docker/package_managers:install_pkgs.bzl", "install_pkgs")
+
+# - - base docker stuff - -
+
+download_pkgs(
+    name = "apt_py_is_py3",
+    image_tar = "@python-debian//image",
+    packages = [
+        # rules_docker python wants /usr/bin/python
+        "python-is-python3",
+    ],
+)
+
+install_pkgs(
+    name = "base_image",
+    output_image_name = "base_image",
+    image_tar = "@python-debian//image",
+    installables_tar = ":apt_py_is_py3.tar",
+    installation_cleanup_commands = "rm -rf /var/lib/apt/lists/* /usr/share/doc && apt remove -y libbluetooth3 mariadb-common tk && apt autoremove -y",
+)
+
+BASE_IMAGE = ":base_image"
+
+# overkill rube goldberg setup to build static files begins
+#  - - - -
+
+container_run_and_extract(
+    name = "static_pack",
+    commands = [
+        "tar cpJvf /out.tar.xz -C /opt/mailman/web/static ./",
+    ],
+    extract_file = "/out.tar.xz",
+    image = ":static_build_image.tar",
+)
+
+container_image(
+    name = "static_build_image",
+    layers = [":static_build_layer"],
+    base = BASE_IMAGE,
+)
+
+# this will also contain .pyc files, but the python binary will be the same
+# on prod, so it's fine
+container_run_and_commit_layer(
+    name = "static_build_layer",
+    commands = [
+        "./app/mailman-web/manage collectstatic",
+        "./app/mailman-web/manage compress",
+        # gettext is cursed, TODO make this work
+        #"./app/mailman-web/manage compilemessages",
+    ],
+    image = ":build_container.tar",
+    docker_run_flags = ["--entrypoint="],
+)
+
+py3_image(
+    name = "build_container",
+    srcs = [":manage"],
+    main = "manage.py",
+    base = ":build_tools_container",
+    layers = [":deps_layer"],
+    # this doesn't work for some reason - this is always rebuilt, unless
+    # you pass --nostamp globally
+    stamp = 0,
+)
+
+download_pkgs(
+    name = "build_tools",
+    image_tar = "@python-debian//image",
+    packages = [
+        "sassc",
+        "gettext",
+    ],
+)
+
+install_pkgs(
+    name = "build_tools_container",
+    output_image_name = "build_tools_container",
+    image_tar = BASE_IMAGE + '.tar',
+    installables_tar = ":build_tools.tar",
+    installation_cleanup_commands = "rm -rf /var/lib/apt/lists/* /usr/share/doc",
+)
+
+#  - - - -
+# overkill rube goldberg setup to build static files ends
+
+
+# - - python stuff - -
+
+# this is purely a build optimization - put the pip deps into a separate layer
+py_layer(
+    name = "deps_layer",
+    deps = [
+        requirement("Django"),
+        requirement("postorius"),
+        requirement("hyperkitty"),
+        requirement("gunicorn"),
+        requirement("psycopg2-binary"),
+    ],
+)
+
+py_library(
+    name = "django_base",
+    srcs = ["settings.py", "urls.py"]
+        + glob(["upstream_settings/*.py"]),
+    deps = [
+        requirement("Django"),
+        requirement("postorius"),
+        requirement("hyperkitty"),
+        requirement("gunicorn"),
+        requirement("psycopg2-binary"),
+    ],
+)
+
+py_binary(
+    name = "manage",
+    srcs = ["manage.py"],
+    deps = [":django_base"],
+)
+
+py_binary(
+    name = "serve",
+    srcs = ["serve.py"],
+    deps = [":django_base"],
+)
+
+# prod docker image
+
+py3_image(
+    name = "mailman-web",
+    srcs = ["container_main.py"],
+    deps = [
+        ":django_base",
+        ":manage",
+        ":serve",
+    ],
+    layers = [
+        ":deps_layer",
+    ],
+    main = "container_main.py",
+    #base = ":base_container"
+    base = ":static_build_image",
+)