This is the example project for the Bzlmod Migration Bootcamp workshop. It demonstrates how to migrate Bazel projects using the legacy WORKSPACE system for configuring external dependencies to the new Bazel modules system, a.k.a. Bzlmod.
It also shows how to:
- Solve common problems that arise when migrating to newer Bazel versions
- Implement the "hub repo" pattern to better encapsulate toolchains and their dependencies
- Maintain compatibility with a wide range of Bazel versions and dependency versions
- Write and run tests to validate rule behaviors, including failure behaviors
- Write and run tests to validate version compatibility contracts
This is the video of the Bzlmod Migration Bootcamp v1.0.0 presented at BazelCon in Atlanta, GA on 2025-11-09:
See the Releases page for official releases of the accompanying slides in PDF format.
This is how the versioned slides stay in sync with the corresponding code:
-
Each official release will correspond to a version tag for this repository of the form
v[Major].[minor].[patch]. -
Each example project milestone for that release will have its own versioned tag name of the form
v[Major].[minor].[patch]-[milestone]. -
The slides will contain links to commit lists and source files that include the versioned tag name of the relevant milestone. This way each release of the slides will contain stable links to the corresponding version of the example repo.
Bzlmod is available in Bazel 7 and 8, and is the only system available in the
upcoming Bazel 9 release. In fact, the latest rolling releases of
Bazel have already removed legacy WORKSPACE support, so projects
must already fully support Bzlmod to use them.
Note: Bzlmod is available to a limited extent in Bazel 6, but it's missing several important features, such as use_repo_rule. It's worth migrating to at least Bazel 7 before using it.
This Git repository contains two separate Bazel repositories:
- bootcamp: A repository that depends upon
rules_magic - rules_magic: A rule set repository reminiscent of FrobozzCo International products
Run your IDE from the root of this bzlmod-bootcamp Git repository. However,
Bazel commands for this workshop will run in the bootcamp Bazel
repository.
The top level Bzlmod Migration Bootcamp agenda consists of:
- Bzlmod vs. legacy WORKSPACE
- Module extensions
- Bzlmod migration plan
- Repository name handling
- Patching dependencies
- Encapsulating toolchains
- Testing
- Dependency version compatibility
and the Bzlmod migration plan section specifically consists of:
- Review essential documentation, clarify priorities & decisions
- Migrate to Bazel 7 first (Bazel 6 Bzlmod support is incomplete)
- Optional: Fix everything on a branch, open a separate pull request for each fix (rebase after merging each PR into main)
- Optional: Migrate to Bazel 8 first, remove own repo references
- Keep legacy
WORKSPACEbuilding; enable Bzlmod at the end - Inspiration + evidence: bazel-contrib/rules_scala#1482
This workshop is not an exhaustive survey of all potential Bzlmod related issues and migration solutions. It will not cover every item in the official Bzlmod migration guide, including (but not limited to):
However, it is a survey of the most common Bzlmod migration obstacles, and insights, strategies, and techniques for overcoming them. It will borrow heavily from:
- EngFlow's Bzlmod blog series
- rules_scala and the rules_scala Bzlmodification journey
- the official Bazel documentation
This foundation will hopefully prove useful for solving specific challenges in your own projects, however unique the details of those challenges may be.
-
Familiarity with Bazel
-
Some familarity with the legacy
WORKSPACEexternal dependency configuration system and how it compares to Bzlmod- The Bootcamp covers this, but it's good to prepare in advance.
-
All the necessary tools already installed on the development machine:
- git
- git-for-windows on Windows, as this project requires Bash
- the Bazelisk wrapper for launching specific Bazel versions
- a C/C++ compiler or development suite, e.g. gcc or clang on Linux, Xcode on macOS, or msvc or clang on Windows
- an IDE of choice, such as Visual Studio Code (ideally with Vim keybindings)
- git
Git branches and tags identify significant points throughout the migration process whereby a subset of changes within the overall history achieves a specific outcome. We call those points and the branches and tags that identify them "milestones."
-
Milestone branches are subject to change at any time as the course evolves. The
mainbranch corresponds to the latest development version of thecompatibilitymilestone. -
Milestone tags have the form
v[Major].[minor].[patch]-[milestone]. They will remain stable to ensure links from the corresponding slide deck version remain intact.
While many of the changes throughout the commit history could happen in any
order, milestones help put specific collections of commits within context. For
example, the commits after the bazel-7 milestone and including the bazel-8
milestone specifically demonstrate Bazel 8 compatibility issues and fixes.
The table below illustrates how the migration process makes the project
compatible with newer Bazels, and eventually Bzlmod, without sacrificing
backward compatibility. The milestones comprising the process appear in reverse
chronological order, as they would appear in git log. Each milestone builds on
the milestone below it, with one exception:
-
The
bzlmod-client-patchesmilestone is based on theown-repo-namesmilestone, the same asbzlmod. -
bzlmodshows how to update the rules_magic rule set repository to make it Bzlmod compatible. This is the preferred migration path. -
bzlmod-client-patchesshows how to update the bootcamp repository to make it Bzlmod compatible whenrules_magicis not itself Bzlmod compatible. This involves creating patches and module extensions forrules_magicwithin thebootcamprepository/Bazel module. This is not the preferred migration path, but demonstrates how a client repository can adapt a non-Bzlmod compatible dependency to build under Bzlmod.
| Milestone | Bazel versions | Legacy WORKSPACE |
Bzlmod |
|---|---|---|---|
compatibility |
6, 7, 8, rolling, last_green |
✅ | ✅ |
toolchains |
6, 7, 8, rolling, last_green |
✅ | ✅ |
bazel-9 |
6, 7, 8, rolling, last_green |
✅ | ✅ |
bzlmod-client-patches |
6, 7, 8 | ✅ | ✅ |
bzlmod |
6, 7, 8 | ✅ | ✅ |
own-repo-names |
6, 7, 8 | ✅ | |
bazel-8 |
6, 7, 8 | ✅ | |
bazel-7 |
6, 7 | ✅ | |
bazel-6 |
6 | ✅ |
It's helpful to view the commit history in your Git commit history viewer of choice, such as gitk or tig. The summary lines in the commit history list provide a good overview of the migration process and the individual steps involved. Each full commit message contains extensive descriptions, explanations, and relevant links for that particular migration step.
