treewide: migrate external rules to bzlmod

This is a huge one as it was very annoying to migrate them separately. This migrates rules_go, gazelle, rust_rust, protobuf to bzlmod

Change-Id: If39591d43ed4c2afa2979ee5915e9d1cfa1574a9
Reviewed-on: https://review.monogon.dev/c/monogon/+/3234
Tested-by: Jenkins CI
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/build/ci/jenkins-presubmit.groovy b/build/ci/jenkins-presubmit.groovy
index c5d6aa7..3b9e719 100644
--- a/build/ci/jenkins-presubmit.groovy
+++ b/build/ci/jenkins-presubmit.groovy
@@ -49,7 +49,6 @@
                         sh "git clean -fdx -e '/bazel-*'"
                         sh "JENKINS_NODE_COOKIE=dontKillMe tools/bazel --bazelrc=.bazelrc.ci mod deps --lockfile_mode=update"
                         sh "JENKINS_NODE_COOKIE=dontKillMe tools/bazel --bazelrc=.bazelrc.ci run //:go -- mod tidy"
-                        sh "JENKINS_NODE_COOKIE=dontKillMe tools/bazel --bazelrc=.bazelrc.ci run //:gazelle-update-repos"
                         sh "JENKINS_NODE_COOKIE=dontKillMe tools/bazel --bazelrc=.bazelrc.ci run //:gazelle -- update"
 
                         script {
@@ -61,7 +60,7 @@
                                     Please run:
 
                                        \$ bazel mod deps --lockfile_mode=update
-                                       \$ bazel run //:gazelle-update-repos
+                                       \$ bazel run //:go -- mod tidy
                                        \$ bazel run //:gazelle -- update
 
                                     In your git checkout and amend the resulting diff to this changelist.
diff --git a/build/print-workspace-status.py b/build/print-workspace-status.py
index 2838730..9eb551f 100755
--- a/build/print-workspace-status.py
+++ b/build/print-workspace-status.py
@@ -147,57 +147,44 @@
 
 # Special treatment for Kubernetes, which uses these stamp values in its build
 # system. We populate the Kubernetes version from whatever is in
-# //third_party/go/repositories.bzl.
-def parse_repositories_bzl(path: str) -> dict[str, str]:
+# //go.mod.
+def parse_go_mod(path: str) -> dict[str, str]:
     """
-    Shoddily parse a Gazelle-created repositories.bzl into a map of
-    name->version.
+    Shoddily parse a go.mod into a map of name->version.
 
-    This relies heavily on repositories.bzl being correctly formatted and
+    This relies heavily on go.mod being correctly formatted and
     sorted.
 
-    If this breaks, it's probably best to try to use the actual Python parser
-    to deal with this, eg. by creating a fake environment for the .bzl file to
-    be parsed.
+    If this breaks, it's probably best to try to port this to Go
+    and parse it using golang.org/x/mod/modfile, shell out to
+    "go mod edit -json", or similar.
     """
 
-    # Main parser state: None where we don't expect a version line, set to some
-    # value otherwise.
-    name: Optional[str] = None
+    # Just a copied together regex to find the url followed by a semver.
+    NAME_VERSION_REGEX = r"([-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*) v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)"
 
     res = {}
     for line in open(path):
-        line = line.strip()
-        if line == "go_repository(":
-            name = None
+        matches = re.findall(NAME_VERSION_REGEX, line)
+        if not matches:
             continue
-        if line.startswith("name ="):
-            if name is not None:
-                raise Exception("parse error in repositories.bzl: repeated name?")
-            if line.count('"') != 2:
-                raise Exception(
-                    "parse error in repositories.bzl: invalid name line: " + name
-                )
-            name = line.split('"')[1]
+
+        [name, version] = matches[0][0].strip().split(" ")
+
+        # If we already saw a package, skip it.
+        if name in res:
             continue
-        if line.startswith("version ="):
-            if name is None:
-                raise Exception("parse error in repositories.bzl: version before name")
-            if line.count('"') != 2:
-                raise Exception(
-                    "parse error in repositories.bzl: invalid name line: " + name
-                )
-            version = line.split('"')[1]
-            res[name] = version
-            name = None
+
+        res[name] = version
+
     return res
 
 
-# Parse repositories.bzl.
-go_versions = parse_repositories_bzl("third_party/go/repositories.bzl")
+# Parse go.mod.
+go_versions = parse_go_mod("go.mod")
 
 # Find Kubernetes version.
-kubernetes_version: str = go_versions.get("io_k8s_kubernetes")
+kubernetes_version: str = go_versions.get("k8s.io/kubernetes")
 if kubernetes_version is None:
     raise Exception("could not figure out Kubernetes version")
 kubernetes_version_parsed = re.match(
diff --git a/build/proto_docs/proto_docs.bzl b/build/proto_docs/proto_docs.bzl
index d929649..ecbcdc0 100644
--- a/build/proto_docs/proto_docs.bzl
+++ b/build/proto_docs/proto_docs.bzl
@@ -20,12 +20,12 @@
 
     for src in transitive_sources.to_list():
         # Due to the built-in import path for well-known types (see AddDefaultProtoPaths
-        # in @com_google_protobuf//src/google/protobuf/compiler:command_line_interface.cc)
+        # in @protobuf//src/google/protobuf/compiler:command_line_interface.cc)
         # in protoc the Bazel-generated well-known protos are considered to contain
         #  "duplicate" types.
         # Since generating documentation for well-known types is not that useful just
         # skip them.
-        if src.path.find("/bin/external/com_github_protocolbuffers_protobuf/_virtual_imports/") != -1:
+        if src.path.find("/external/protobuf~/") != -1:
             continue
         args.append(src.path)
 
@@ -51,7 +51,7 @@
             default = [],
         ),
         "_protoc": attr.label(
-            default = Label("@com_google_protobuf//:protoc"),
+            default = Label("@protobuf//:protoc"),
             cfg = "exec",
             executable = True,
             allow_files = True,
diff --git a/build/rust/BUILD.bazel b/build/rust/BUILD.bazel
index ffc1682..7459c33 100644
--- a/build/rust/BUILD.bazel
+++ b/build/rust/BUILD.bazel
@@ -14,7 +14,7 @@
     prost_plugin = "@crate_index//:protoc-gen-prost__protoc-gen-prost",
     prost_runtime = ":prost_runtime_efi",
     prost_types = "@crate_index_efi//:prost-types",
-    proto_compiler = "@com_google_protobuf//:protoc",
+    proto_compiler = "@protobuf//:protoc",
     # This defaults to a non-empty value, which triggers an error that not all
     # tonic flags are set. We do not want tonic, so explicitly set this to
     # an empty string.