有没有一种方法可以在每次bazel调用时使用local = True执行repository_rule?

时间:2020-05-22 12:59:21

标签: bazel

我有一个repository_rule,它正在查询以查看本地系统是否正在运行数据库并已完全迁移。

# impl
    result = ctx.execute(["mysql", "-u", "root", "--protocol", "tcp", "-e", "select * from %s.flyway_schema_history" % ctx.attr.dbname])

    ctx.file(
        "local_checksum",
        """
             {RETURN_CODE}
             {STDERR}
             {STDOUT}
             """.format(
            RETURN_CODE = result.return_code,
            STDERR = result.stderr,
            STDOUT = result.stdout,
        ),
    )
...

# Rule Def
local_database = repository_rule(
    implementation = _local_database,
    local = True,
    configure=True,
    attrs = {
        "datasource_configuration": attr.label(providers = [DataSourceConnectionInfo]),
        "dbname": attr.string(doc = """
        If omitted, will be the name of the repository.
        """),
        "migrations": attr.label_list(allow_files = True),
    },
)

只要依赖关系图发生更改(如文档https://docs.bazel.build/versions/master/skylark/repository_rules.html#when-is-the-implementation-function-executed中所述),就会重新计算local_checksum并执行其工作。

但是由于数据库不是由bazel管理的,是否有任何方法可以强制每次调用bazel以确保所有依赖项都可用时运行此特定规则?

1 个答案:

答案 0 :(得分:2)

睡了一会儿,我把一些东西弄碎了。仍在寻找更好的答案,我认为有一种一流的方法可以解决这个问题。

我在tools / bazel中创建了一个bazel包装器

#!/bin/bash

set -e

echo "`date`

Generated by tools/bazel" > .bazelexec.stamp

# from https://github.com/grpc/grpc/blob/master/tools/bazel
exec -a "$0" "${BAZEL_REAL}" "$@"

然后我在规则中添加了用于读取该文件的属性:

local_database = repository_rule(
    implementation = _local_database,
    local = True,
    configure=True,
    attrs = {
        "datasource_configuration": attr.label(providers = [DataSourceConnectionInfo]),
        "dbname": attr.string(doc = """
        If omitted, will be the name of the repository.
        """),
        "migrations": attr.label_list(allow_files = True),
        "recalculate_when": attr.label_list(allow_files = True, doc = """
        Files to watch which will trigger the repository to run when they change.

        You can add a tools/bazel script to your local repository, and write a file with a date
        every time bazel is executed in order to get the migrator to check each bazel run if
        someone changed the database.
        """),
    },

最后,我在规则中为这些文件创建路径,以便存储库认为其图已更改。

    # If you don't do something with the file, then the rule does not recalculate.
    [ctx.path(file) for file in ctx.attr.recalculate_when]

    # Total mysql hack for now... need java tool which dumps content of a table for different databases
    result = ctx.execute(
        ["mysql", "-u", "root", "--protocol", "tcp", "-e", "show databases"],
    )

    ctx.file(
        "local_database_checksum",
        """
             {RETURN_CODE}
             {STDERR}
             {STDOUT}
             """.format(
            RETURN_CODE = result.return_code,
            STDERR = result.stderr,
            STDOUT = result.stdout,
        ),
    )

现在,每次运行构建时,如果数据库更改,则local_checksum文件也会更改,并且可以触发其他规则来重新构建(在我的情况下,我正在生成jooq类,因此查询进入表中),如果数据库和表是稳定的,那么它不会触发重建。