1

I am trying to create Bazel rule which would execute docker-compose command and spin up all docker images from docker-compose.yaml file. I was able to get this going but my next step is to make my rule depend on another container_image target from my build files.

I would like to first run this container_image target and then my own rule. I need to run container_image rule as that is the only way the rule will actually load built image to docker. I need to do this as I am planing to inject the name of this newly built image to my docker-compose.yaml file.

Code for my rule is:

def _dcompose_up_impl(ctx):
    toolchain_info = ctx.toolchains["@com_unfold_backend//rules:toolchain_type"].dc_info

    test_image = ctx.attr.test_image
    docker_up = ctx.actions.declare_file(ctx.label.package + "-" + ctx.label.name + ".yaml")
    image_name = "bazel/%s:%s" % (test_image.label.package, test_image.label.name)
    ctx.actions.expand_template(
        output = docker_up,
        template = ctx.file.docker_compose,
        substitutions = {"{IMAGE}": image_name},
    )
    out = ctx.actions.declare_file(ctx.label.name + ".out")
    ctx.actions.run(executable = ctx.executable.test_image, outputs = [out])

    runfiles = ctx.runfiles(files = ctx.files.data + [docker_up, out])
    cmd = """echo Running docker compose for {file}
    {dockerbin} -f {file} up -d
    """.format(file = docker_up.short_path, dockerbin = toolchain_info.path)
    exe = ctx.actions.declare_file("docker-up.sh")
    ctx.actions.write(exe, cmd)

    return [DefaultInfo(
        executable = exe,
        runfiles = runfiles,
    )]

dcompose_up = rule(
    implementation = _dcompose_up_impl,
    attrs = {
        "docker_compose": attr.label(allow_single_file = [".yaml", ".yml"], mandatory = True),
        "data": attr.label_list(allow_files = True),
        "test_image": attr.label(
            executable = True,
            cfg = "exec",
            mandatory = True,
        ),
    },
    toolchains = ["//rules:toolchain_type"],
    executable = True,
)

Problem is out file I create when running container_image task test_image. I get error from Bazel Loaded image ID: sha256:c15a1b44d84dc5d3f1ba5be852e6a5dfbdc11e24ff42615739e348bdb0522813 Tagging c15a1b44d84dc5d3f1ba5be852e6a5dfbdc11e24ff42615739e348bdb0522813 as bazel/images/test:image_test ERROR: /monogit/test/BUILD:18:22: output '/test/integration.up.out' was not created ERROR: /monogit/test/BUILD:18:22: Action test/integration.up.out failed: not all outputs were created or valid

If I remove out file from runfiles for my docker-compose execution then my test_image does not get loaded to docker. In the first example it gets loaded but docker-compose then fails.

It is obvious to me that container_image rule does not create output files. In that case, how could I make Bazel run, not just build, container_image executable and then my executable?

0 Answers0