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/Dockerfile b/build/Dockerfile
index 37d59cd..cbd1712 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -23,7 +23,8 @@
which \
swtpm-tools \
rsync \
- qemu-system-x86-core
+ qemu-system-x86-core \
+ postgresql
# Workaround for a binutils bugs in F30, which generates invalid ELF binaries
# when linking statically with musl.
diff --git a/build/sqlboiler/BUILD b/build/sqlboiler/BUILD
new file mode 100644
index 0000000..e9ec548
--- /dev/null
+++ b/build/sqlboiler/BUILD
@@ -0,0 +1,4 @@
+exports_files([
+ "dbconfig.yml",
+ "sqlboiler.toml",
+])
diff --git a/build/sqlboiler/README.md b/build/sqlboiler/README.md
new file mode 100644
index 0000000..bb61463
--- /dev/null
+++ b/build/sqlboiler/README.md
@@ -0,0 +1,59 @@
+##SQLboiler
+
+This rule allows to generate sqlboiler models and ORM code for golang from a stack of SQL migrations.
+
+It uses `sql-migrate`, `sqlboiler` and `sqlboiker-crdb`.
+
+###How to use
+
+Create a package and create a `0_initial.sql` file with the following template:
+
+```
+-- +migrate Up
+
+Your initial SQL goes here
+
+-- +migrate Down
+
+```
+
+Then create a `BUILD` file with the following rules:
+
+```
+load("//build/sqlboiler:sqlboiler.bzl", "go_sqlboiler_library", "sqlboiler")
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+# gazelle:ignore .
+
+sqlboiler(
+ name = "sqlboiler",
+ srcs = glob(["*.sql"]),
+ tables = [
+ <your table names>
+ ],
+)
+
+go_sqlboiler_library(
+ name = "sqlboiler_lib",
+ importpath = "git.monogon.dev/source/nexantic.git/<target>",
+ sqlboiler = ":sqlboiler",
+)
+
+go_library(
+ name = "go_default_library",
+ embed = [":sqlboiler_lib"],
+ importpath = "git.monogon.dev/source/nexantic.git/<target>",
+ visibility = ["//visibility:public"],
+)
+
+```
+
+Replace `target` with your intended importpath and add all created tables to the `tables` argument of the sqlboiler rule.
+
+Running the tasks will apply the migrations to a temporary database using `sql-migrate` and generate sqlboiler code from it.
+The code will be importable from the specified `importpath`.
+
+When making changes to the schema please generate new migrations using the `<n>_<description>.sql` pattern for file names.
+The migrations will automatically be applied and the models updated.
+
+Make sure to also update the `tables` argument when creating new tables in migrations.
diff --git a/build/sqlboiler/dbconfig.yml b/build/sqlboiler/dbconfig.yml
new file mode 100644
index 0000000..8a2d3b4
--- /dev/null
+++ b/build/sqlboiler/dbconfig.yml
@@ -0,0 +1,5 @@
+development:
+ dialect: postgres
+ datasource: dbname=_dbname_ sslmode=disable port=26257 user=root
+ dir: migrations
+ table: migrations
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"),
+ ],
+ ),
+ },
+)
diff --git a/build/sqlboiler/sqlboiler.toml b/build/sqlboiler/sqlboiler.toml
new file mode 100644
index 0000000..551ce5e
--- /dev/null
+++ b/build/sqlboiler/sqlboiler.toml
@@ -0,0 +1,9 @@
+[crdb]
+ dbname = "_dbname_"
+ host = "localhost"
+ port = 26257
+ user = "root"
+ pass = ""
+ sslmode = "disable"
+ schema = "public"
+ blacklist = ["migrations"]