Setup a GO Bazel Monorepo (using bzlmod)
Published: 2024-06-28 00:29:30

In this article I will describe how to set up your own Bazel repository. Using the bzlmod the new external dependency system introduced in Bazel 5+.

Also I will add a GO hello world project to show how could you add other projects to the monorepo.

![Bazel logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2xxnakweao9kdawu75jb.png)


## Let's start

The first thing you need to do is create a new directory. I will call it bazel-intro.

Inside the bazel-intro directory create a MODULE.bazel and a BUILD file: 

* **MODULE.bazel**: According to the official [docs](https://bazel.build/external/overview#bzlmod) The MODULE.bazel file should be located at the root of the workspace directory (next to the WORKSPACE file). Unlike with the WORKSPACE file, you don’t need to specify your transitive dependencies; instead, you should only specify direct dependencies, and the MODULE.bazel files of your dependencies will be processed to discover transitive dependencies automatically. We are not going to add the WORKSPACE file.

**Folder structure:**

- bazel-intro
    - MODULE.bazel
    - BUILD

## Fill MODULE.bazel file

Since we are going to use GO, we need to add this lines to our MODULE.bazel file: 

```MODULE.bazel
bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_go", version = "0.48.1")

```

The **gazelle** "dependency" enables us to use gazelle, which is a build file generator that helps us to create/update BUILDS files for every project inside our monorepo. And **rules_go** enables us to build GO code in bazel. You can find the more recent versions [here](https://registry.bazel.build/search?q=go).


According to the rules_go and gazelle [docs](https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/bzlmod.md) you need to add to your MODULE.bazel file:  

### GO extensions

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

# Download an SDK for the host OS & architecture as well as common remote execution platforms.
go_sdk.download(version = "1.20.3")
```

### Gazelle 

```MODULE.bazel
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", 
)
```

In the last line you may see that we add to the **rule** use_repo: 
 - **com_github_gofiber_fiber_v2**: I add this dependency here because we will setup a Fiber http server later (our GO project). 

**Important:** If you need to add more dependecies you could do it   here. For example: 

#### Adding more deps example: 

Lets say we want to add com_github_joho_godotenv to our project

```
use_repo(go_deps, 
         "com_github_gofiber_fiber_v2", 
         "com_github_joho_godotenv" 
)
```
### Filling BUILD file

Remember the build file we create at the begining? We are going to populate it with the next lines of code. In your top-level BUILD file add:

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

```

This will add gazelle.

### Creating a project

#### Folder structure:

- bazel-intro
    - services
        - app 
            - main.go
    - MODULE.bazel
    - BUILD


#### Create a project is simple. 

1. Create a directory called services. 
2. Inside services folder create a folder called app.
3. Inside app folder create a main.go file. 
4. Add the next code to your main.go file: 

```GO
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"))
}
```

### Creating go.mod and go.sum

In your terminal type `go mod init something`:

**For example:**

```bash
go mod init bazel-intro/services

```
and then `go mod tidy`. 

##  Let's gazelle and build :) 

Run in your terminal: 

```bash
bazel run //:gazelle
```
then 

```bash
bazel build //...
```

and finally 

```bash
bazel run services/app
```

And that is all! 🎉🎉
You should see the fiber http server running 


![Go fiber http server running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awbd30bcekik19oamw4v.png)