treewide: remove usage of global tags between build configs

Change-Id: Ie7c4714d30f8c3342a97451d58e14cfb43087586
Reviewed-on: https://review.monogon.dev/c/monogon/+/3776
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/build/go/BUILD.bazel b/build/go/BUILD.bazel
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/build/go/BUILD.bazel
diff --git a/build/go/def.bzl b/build/go/def.bzl
new file mode 100644
index 0000000..c696564
--- /dev/null
+++ b/build/go/def.bzl
@@ -0,0 +1,67 @@
+load("@bazel_skylib//lib:paths.bzl", "paths")
+
+def _build_with_tag_transition_impl(settings, attr):
+    """
+    Transition that enables pure, static build of Go binaries.
+    """
+    tags = settings["@io_bazel_rules_go//go/config:tags"]
+
+    return {
+        "@io_bazel_rules_go//go/config:tags": tags + attr.gotags,
+    }
+
+build_with_tag_transition = transition(
+    implementation = _build_with_tag_transition_impl,
+    inputs = [
+        "@io_bazel_rules_go//go/config:tags",
+    ],
+    outputs = [
+        "@io_bazel_rules_go//go/config:tags",
+    ],
+)
+
+def _go_binary_with_tag_impl(ctx):
+    # We need to forward the DefaultInfo provider from the underlying rule.
+    # Unfortunately, we can't do this directly, because Bazel requires that the executable to run
+    # is actually generated by this rule, so we need to symlink to it, and generate a synthetic
+    # forwarding DefaultInfo.
+
+    result = []
+    binary = ctx.attr.binary[0]
+
+    default_info = binary[DefaultInfo]
+    new_executable = None
+    original_executable = default_info.files_to_run.executable
+
+    if not original_executable:
+        fail("Cannot transition a 'binary' that is not executable")
+
+    # In order for the symlink to have the same basename as the original
+    # executable (important in the case of proto plugins), put it in a
+    # subdirectory named after the label to prevent collisions.
+    new_executable = ctx.actions.declare_file(paths.join(ctx.label.name, original_executable.basename))
+    ctx.actions.symlink(
+        output = new_executable,
+        target_file = original_executable,
+        is_executable = True,
+    )
+
+    result.append(
+        DefaultInfo(
+            files = depset(direct = [new_executable]),
+            executable = new_executable,
+        ),
+    )
+
+    return result
+
+go_binary_with_tag = rule(
+    implementation = _go_binary_with_tag_impl,
+    attrs = {
+        "binary": attr.label(
+            mandatory = True,
+            cfg = build_with_tag_transition,
+        ),
+        "gotags": attr.string_list(),
+    },
+)