Practical Bazel: Using Rulesets from Non-Public GitHub Repositories
Practical Bazel bazel GitHub
Published: 2022-11-09
Practical Bazel: Using Rulesets from Non-Public GitHub Repositories

At work, we have a number of custom-written Bazel rulesets stored in organization repositories on GitHub1. This post explains how we use these non-public rulesets in our Bazel projects.

Update 2023-05-23: You may also want to read my blog post Practical Bazel: Downloading Private Release Assets from GitHub.

In order to download code from a GitHub private repository, one must provide authentication credentials as part of the request. The easiest way to do this is to create a GitHub personal access token (PAT) and use HTTP bearer authentication with this token.

A PAT is a 40-character string that looks something like gho_n2d.... PATs are typically set up in the GitHub UI or using the GitHub REST API, but a quick-and-dirty-way to get one is to install the GitHub CLI, authenticate using gh auth login, and retrieve the PAT that the CLI uses with gh auth token.

Once you have a PAT, it can be used with HTTP bearer authentication when making a request to GitHub. For example, imagine you have a ruleset rules_mylang that is stored in the GitHub organization myorg, and you want to download its release release-1.2.3. Here’s how this can be done with curl:

1
2
$ curl -H "Authorization: Bearer gho_n2d..." \
    https://github.com/myorg/rules_mylang/archive/refs/tags/release-1.2.3.tar.gz

The underlying HTTP request and response looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
GET /myorg/rules_mylang/archive/refs/tags/release-1.2.3.tar.gz HTTP/1.1
Host: github.com
Accept: */*
Authorization: Bearer gho_n2d...

HTTP/1.1 302 Found
Server: GitHub.com
Date: Thu, 10 Nov 2022 04:26:31 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame
Location: https://codeload.github.com/myorg/rules_mylang/tar.gz/refs/tags/release-1.2.3?token=...
Cache-Control: max-age=0, private
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Vary: Accept-Encoding, Accept, X-Requested-With
X-GitHub-Request-Id: 4B7F:5127:2B424F4:3FC9CFE:636C7D77

Next, we need to configure Bazel to add this Authorization header when retrieving the ruleset. Fortunately, this is quite easy when using http_archive().

First, add the following line to ~/.netrc:

1
2
3
# ~/.netrc
# gho_n2d... is the GitHub PAT generated above
machine github.com password gho_n2d...

Next, add an auth_patterns option in http_archive() as below:

1
2
3
4
5
6
7
8
9
# WORKSPACE
http_archive(
    name = "rules_mylang",
    auth_patterns = {
        "github.com": "Bearer <password>",
    },
    strip_prefix = "rules_mylang-release-1.2.3",
    urls = ["https://github.com/myorg/rules_mylang/archive/refs/tags/release-1.2.3.tar.gz"],
)

With these changes, using non-public rulesets in Bazel is quite straightforward!


  1. Hopefully they will be open sourced some day! ↩︎