Bazel at Sourcegraph
Sourcegraph uses Bazel as its build system. Reach out on #ask-dev-experience for questions and support.
Overview
- General
- Context specific
- How-tos
📅 Timeline
- 2023-04-03 Bazel steps are required to pass on all PR builds.
- Run
bazel run //:gazelle-update-repos
if you changed thego.mod
. - Run
bazel configure
after making all your changes in the PR and commit the updated/addedBUILD.bazel
- Add
[no-bazel]
in your commit description if you want to bypass Bazel.
- Run
- 2023-04-06 Bazel steps are required to pass on main.
- Run
bazel run //:gazelle-update-repos
if you changed thego.mod
. - Run
bazel configure
after making all your changes in the PR and commit the updated/addedBUILD.bazel
- Add
[no-bazel]
in your commit description if you want to bypass Bazel.
- Run
- 2023-04-10 You cannot opt out of Bazel anymore
- 2023-05-02 Additonally, to normal container building process, container images are now also built with
rules_oci
and Wolfi for as base images.- Those new images are used by the new test targets under
//testing/...
that run the E2E tests and Backend Integration tests. - The new images are deployed on S2 (and only S2).
- See Slack thread
- Those new images are used by the new test targets under
- 2023-05-07 The new images are deployed on Dotcom.
- 2023-05-14 After the release cut and the beginning of the code freeze, all operations that are now migrated to Bazel will have their legacy counterpart removed.
Bazel for teammates in a hurry
Bazel vocabulary
- A rule is a function that stitches together parts of the graph.
- ex: build go code
- A target is a named rule invocation.
- ex: build the go code for
./app
- ex: run the unit tests for
./app
- ex: build the go code for
- A package is a a group of targets.
- ex: we only have one single package in the example above, the root one.
Bazel uses two types of files to define those:
WORKSPACE
, which sits at the root of a project and tells Bazel where to find the rules.- ex: get the Go rules from that repository on GitHub, in this exact version.
BUILD.bazel
, which sits in every folder that contains targets.
To reference them, the convention being used is the following: //pkg1/pkg2:my_target
and you can say things such as //pkg1/...
to reference all possible targets in a package.
Finally, let's say we have defined in our Bazel project some third party dependencies (a NPM module or a Go package), they will be referenced using the @
sign.
@com_github_keegancsmith_sqlf//:sqlf
Bazel cheat sheet
Keep in mind
- Do not commit file whose name include spaces, Bazel does not like it.
- Do not expect your tests to be executed inside the source tree and to be inside a git repository.
- They will be executed in the sandbox. Instead create a temp folder and init a git repo manually over there.
Building and testing things
bazel build [path-to-target]
builds a target.- ex
bazel build //lib/...
will build everything under the/lib/...
folder in the Sourcegraph repository.
- ex
bazel test [path-to-target]
tests a target.- ex
bazel test //lib/...
will run all tests under the/lib/...
folder in the Sourcegraph repository.
- ex
bazel configure
automatically inspect the source tree and update the buildfiles if needed.bazel run //:gazelle-update-repos
automatically inspect thego.mod
and update the third parties dependencies if needed.
Debugging buildfiles
bazel query "//[pkg]/..."
See all subpackages ofpkg
.bazel query "//[pkg]:*"
See all targets ofpkg
.bazel query //[pkg] --output location
prints where the buildfile forpkg
is.- ex:
bazel query @com_github_cloudflare_circl//dh/x448 --output location
which allows to inspect the autogenerated buildfile.
- ex:
bazel query "allpaths(pkg1, pkg2)"
list all knowns connections frompkg1
topkg2
- ex
bazel query "allpaths(//cmd/worker, @go_googleapis//google/api)"
- This is very useful when you want to understand what connects a given package to another.
- ex
sg start
Running bazel built services locally with For early adopters only.
First you need to have bazel
installed obviously, but also iBazel
which will watch your files and rebuild if needed. We use a tool called bazelisk
(which is also part of Bazel) to manage the version of bazel
. It inspects a bunch of files to determine what bazel
version to use for your repo.
If you want the setup automated run sg setup
, otherwise you can install it manually by executing the following commands:
brew install bazelisk
brew install ibazel
Then instead of running sg start oss
you can use the bazel
variant instead.
sg start oss-bazel
sg start enterprise-bazel
sg start codeintel-bazel
sg start enterprise-codeintel-bazel
How it works
When sg start
is booting up, the standard installation process will begin as usual for commands that are not built with Bazel, but you'll also see a new program running
[ bazel]
which will log the build process for all the targets required by your chosen commandset. Once it's done, these services will start and iBazel
will take the relay. It will watch the files that Bazel has indentified as having dependencies for your services, and rebuild them accordingly.
So when a change is detected, iBazel
will build the affected target and it will be restarted once the build finishes.
Caveats
- You still need to run
bazel configure
if you add/remove files or packages. - Error handling is not perfect, so if a build fails, that might stop the whole thing. We'll improve this in the upcoming days, as we gather feedback.