DEV Community

Gustavo Gordillo
Gustavo Gordillo

Posted on • Edited on

Setup a GO Bazel Monorepo (using bzlmod)

In this article, we’ll walk through setting up your own Bazel repository using bzlmod, the new external dependency system introduced in Bazel 5 and later. We’ll also add a small Go “Hello, World!” project to demonstrate how to include additional projects in a monorepo.

Bazel logo

Getting Started

  1. Create a new directory for your Bazel project. For this example, we’ll call it bazel-intro.

  2. Inside the bazel-intro directory, create two files: MODULE.bazel and BUILD.

Directory structure so far:

bazel-intro

├─ MODULE.bazel
├─ BUILD

About the MODULE.bazel File

According to the official Bazel docs on bzlmod, the MODULE.bazel file should be at the root of your workspace (where the WORKSPACE file would normally be). Unlike WORKSPACE, you do not list all transitive dependencies here—only direct dependencies. Bazel will automatically process the MODULE.bazel files of your dependencies to find any transitive dependencies. In this example, we don’t need a WORKSPACE file.

Editing MODULE.bazel for Go Support

Since we’re going to use Go, we need to specify the necessary Bazel dependencies for Go:

bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_go", version = "0.48.1")

Enter fullscreen mode Exit fullscreen mode
  • gazelle: A build file generator that automatically creates or updates BUILD files for Go projects.
  • rules_go: Provides rules to build Go code with Bazel.

You can find more recent versions of these dependencies on the Bazel Registry.

Adding Go Extensions

According to the rules_go and gazelle docs, add the following lines to MODULE.bazel to set up the Go SDK:

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

# Download a suitable Go SDK.
go_sdk.download(version = "1.20.3")

Enter fullscreen mode Exit fullscreen mode

Adding Gazelle Integration and Dependencies

Next, integrate Gazelle:

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")

use_repo(go_deps,
         "com_github_gofiber_fiber_v2", 
)

Enter fullscreen mode Exit fullscreen mode

Here’s what we did:

  • go_deps.from_file(go_mod = "//:go.mod"): Points Gazelle to our Go module file.
  • use_repo(go_deps, "com_github_gofiber_fiber_v2"): Registers a Go dependency (github.com/gofiber/fiber/v2) that we’ll use in our example HTTP server.

Note: If you need more dependencies, you can simply list them inside use_repo:

use_repo(go_deps, 
         "com_github_gofiber_fiber_v2", 
         "com_github_joho_godotenv"
)
Enter fullscreen mode Exit fullscreen mode

Updating the BUILD File

Now let’s populate the top-level BUILD file to integrate Gazelle:

load("@gazelle//:def.bzl", "gazelle")

gazelle(name = "gazelle")
Enter fullscreen mode Exit fullscreen mode

This sets up Gazelle at the root of our workspace.

Creating a Sample Go Project

Next, we’ll create a simple Go project within our repository to test everything.

Updated directory structure:

bazel-intro

├─ MODULE.bazel
├─ BUILD
└─ services
└─ app
└─ main.go

Steps:

  1. Inside bazel-intro, create a services directory.
  2. Inside services, create an app directory.
  3. In the app directory, create a main.go file with the following code:
package main

import (
    "log"
    "github.com/gofiber/fiber/v2"
)

func main() {
    app := fiber.New()

    app.Get("/", func(c *fiber.Ctx) error {
        return c.SendString("Hello, World!")
    })

    log.Fatal(app.Listen(":3000"))
}
Enter fullscreen mode Exit fullscreen mode

Initializing Go Modules

In your terminal, navigate to bazel-intro and initialize a Go module:

go mod init bazel-intro/services
go mod tidy
Enter fullscreen mode Exit fullscreen mode

This creates a go.mod and a go.sum file in the root. Gazelle will use these to understand and update dependencies.

Running Gazelle and Building the Project

  1. Run Gazelle to generate BUILD files for Go code:
bazel run //:gazelle
Enter fullscreen mode Exit fullscreen mode
  1. Build all targets:
bazel build //...
Enter fullscreen mode Exit fullscreen mode
  1. Run the application:
bazel run services/app
Enter fullscreen mode Exit fullscreen mode

If everything goes correctly, you should see the Fiber HTTP server running on port 3000. Open your browser and navigate to http://localhost:3000 to see the “Hello, World!” message.

Go fiber http server running

Conclusion

You’ve successfully set up a Bazel repository using bzlmod, integrated Go support, and created a small service using Fiber. From here, you can add more services, dependencies, and tooling to expand your monorepo.

Happy coding! 🎉

Top comments (0)