We use pulumi to do IaC and we use a monorepo with Bazel as the build tool. We have out modules set out as following

One of the requirements we have is to build a lambda module and then deploy it. The lambda module is a target being built by Bazel (golang, but shouldn't matter):

go_binary(
    name = "lambda_module",
    visibility = ["//visibility:public"],
)

We then have the iac module, which should get the built version of the above module, so that it can then upload it into lambda

go_binary(
    name = "iac",
    args = [
        "-lambda_module",
        "$(location //products/productA/module/lambda_module)",
    ],
    data = ["//products/productA/module/lambda_module"],
    visibility = ["//visibility:public"],
)

There are two key parameters here to note:

  • args: We generate the path to the target module using ` //products/productA/module/lambda_module)`
  • data: We use the data tag to ensure that the built output is included when building/running this target

We then need to use runfiles support within golang to be ablet to identify the correct location for the built binary. The reason this part is complex is to be able to support multiple operating systems. I should caveat that I have only got this working on Linux, but Mac/Win shouldn't be too different.

package main

import (
    _ "embed"
    "flag"
    "fmt"
    "github.com/bazelbuild/rules_go/go/runfiles"
    "path/filepath"
)

func main() {

    var webhookAuth = flag.String("webhook_auth", "", "bin for webhook_auth")
    flag.Parse()
    fmt.Printf("param : %s \n", *webhookAuth)

    path, err := runfiles.Rlocation(fmt.Sprintf("workspace_name/%s", *webhookAuth))
    fmt.Printf("rLoc path: %s, err: %v \n", path, err)

    symlinks, err := filepath.EvalSymlinks(path)
    fmt.Printf("evaluated path: %s, err: %v \n", symlinks, err)

}

We use the flag module to retrieve the path passed in as a runtime parameter

We use runfiles.Rlocation to pick up the "real" path to the file, prepending the workspace name to the start. You can define the workspace name in the root WORKSPACE file with workspace(name = "workspace_name")

Finally, resolve the Symlink to get the actual file path

References

There are similar mechanisms to find the rLocation in other languages, a couple of which are described in its design document

There is some documentation in rules_go around accessing go_binary from go_test which I referenced and updated to get the above example

I found the above link from a stackoverflow post about feeding bazel output to another bazel rule