Add sqlboiler bazel rules

This implements a bazel rule to build sqlboiler models from sql migration stacks. It also launches a cockroachdb container in `create_container` and puts it in one pod with the nexantic-dev container.

Currently gazelle overwrites the `go_library` rule. I still need to find a way to properly exclude it.

Test Plan: Built a sample set of sql models

X-Origin-Diff: phab/D226
GitOrigin-RevId: ff24f07bb0b3da9994c52a74f48b54e1e2bea726
diff --git a/build/sqlboiler/sqlboiler.bzl b/build/sqlboiler/sqlboiler.bzl
new file mode 100644
index 0000000..602c73c
--- /dev/null
+++ b/build/sqlboiler/sqlboiler.bzl
@@ -0,0 +1,163 @@
+#  Copyright 2020 The Monogon Project Authors.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+load("@bazel_gazelle//:deps.bzl", "go_repository")
+load(
+    "@io_bazel_rules_go//go/private:rules/rule.bzl",
+    "go_rule",
+)
+load(
+    "@io_bazel_rules_go//go:def.bzl",
+    "GoLibrary",
+    "go_context",
+)
+
+# Default files generated by the sqlboiler + cockroach module
+SQLBOILER_FILES = [
+    "boil_main_test.go",
+    "boil_queries.go",
+    "boil_queries_test.go",
+    "boil_suites_test.go",
+    "boil_table_names.go",
+    "boil_types.go",
+    "crdb_main_test.go",
+    "crdb_suites_test.go",
+    "crdb_upsert.go",
+]
+
+def _sqlboiler_impl(ctx):
+    """Generate sqlboiler models from sql-migrate migrations"""
+
+    filesn = []
+    filesn += SQLBOILER_FILES
+
+    for table in ctx.attr.tables:
+        filesn += [
+            "{}.go".format(table),
+            "{}_test.go".format(table),
+        ]
+
+    outs = []
+    for file in filesn:
+        outs += [ctx.actions.declare_file(file)]
+
+    # run_shell does not so set -euo pipefail
+    command = "set -euo pipefail\n"
+
+    # Create random db name
+    command += "TMP_DB=$(cat /dev/urandom | tr -dc 'a-z' | fold -w 12 | head -n 1 ; echo)\n"
+    command += "echo DB name: $TMP_DB\n"
+
+    # Create DB and template configs
+    command += "/usr/bin/psql --host localhost --port 26257 --user root -c \"CREATE DATABASE $TMP_DB;\"\n"
+
+    command += "ln -s \"{}\" . \n".format(ctx.file.migrate_config.path)
+    command += "sed -i \"s/_dbname_/$TMP_DB/g\" \"{}\" \n".format(ctx.file.migrate_config.basename)
+
+    command += "ln -s {} . \n".format(ctx.file.boiler_config.path)
+    command += "sed -i \"s/_dbname_/$TMP_DB/g\" \"{}\" \n".format(ctx.file.boiler_config.basename)
+
+    # Copy in all sql files
+    command += "mkdir migrations\n"
+    for f in ctx.files.srcs:
+        command += "cp \"{}\" migrations/\n".format(f.path)
+
+    # Copy in adapter
+    command += "cp \"{}\" .\n".format(ctx.file.adapter.path)
+
+    # Apply sql-migrate
+    command += "{} up --config \"{}\" \n".format(ctx.file.migrate.path, ctx.file.migrate_config.basename)
+
+    # Run sqlboiler
+    command += "{} --output \"{}\" --config \"{}\" --wipe crdb \n".format(
+        ctx.file.boiler.path,
+        outs[0].dirname,
+        ctx.file.boiler_config.basename,
+    )
+
+    ctx.actions.run_shell(
+        inputs = ctx.files.srcs + [
+            ctx.file.migrate_config,
+            ctx.file.boiler,
+            ctx.file.adapter,
+            ctx.file.migrate,
+            ctx.file.boiler_config,
+        ],
+        outputs = outs,
+        command = command,
+    )
+
+    return [DefaultInfo(files = depset(outs))]
+
+sqlboiler = rule(
+    implementation = _sqlboiler_impl,
+    attrs = {
+        "srcs": attr.label_list(mandatory = True, allow_files = [".sql"]),
+        "tables": attr.string_list(default = []),
+        "migrate_config": attr.label(allow_single_file = True, default = Label("@//build/sqlboiler:dbconfig.yml")),
+        "boiler_config": attr.label(allow_single_file = True, default = Label("@//build/sqlboiler:sqlboiler.toml")),
+        "boiler": attr.label(allow_single_file = True, default = Label("@com_github_volatiletech_sqlboiler//:sqlboiler")),
+        "adapter": attr.label(allow_single_file = True, default = Label("@com_github_glerchundi_sqlboiler_crdb//:sqlboiler-crdb")),
+        "migrate": attr.label(allow_single_file = True, default = Label("@com_github_rubenv_sql_migrate//sql-migrate:sql-migrate")),
+    },
+)
+
+def _sqlboiler_go_impl(ctx):
+    go = go_context(ctx)
+
+    source_files = []
+
+    # Don't include test files as they cannot be processed by go_library
+    for file in ctx.attr.sqlboiler.files.to_list():
+        if not "test" in file.path:
+            source_files += [file]
+
+    library = go.new_library(
+        go,
+        srcs = source_files,
+    )
+    source = go.library_to_source(go, ctx.attr, library, False)
+    providers = [library, source]
+    output_groups = {
+        "go_generated_srcs": source_files,
+    }
+
+    return providers + [OutputGroupInfo(**output_groups)]
+
+go_sqlboiler_library = go_rule(
+    _sqlboiler_go_impl,
+    attrs = {
+        "sqlboiler": attr.label(providers = [DefaultInfo]),
+        "importpath": attr.string(),
+        "deps": attr.label_list(
+            providers = [GoLibrary],
+            default = [
+                Label("@com_github_friendsofgo_errors//:go_default_library"),
+                Label("@com_github_lib_pq//:go_default_library"),
+                Label("@com_github_pkg_errors//:go_default_library"),
+                Label("@com_github_spf13_viper//:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//boil:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//drivers:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//queries:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//queries/qm:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//randomize:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//strmangle:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//types:go_default_library"),
+                Label("@com_github_volatiletech_sqlboiler//queries/qmhelper:go_default_library"),
+            ],
+        ),
+    },
+)