From time to time, it is worth cleaning up old Bazel stuff in your repositories. This is especially useful before a major Bazel upgrade, because it reduces the amount of migration noise you need to deal with. Most of these cleanups are not difficult, but they make the codebase a little easier to deal with.

The suggestions below are relevant if you are on Bazel 8.1.0 or newer.

Sets

Starting with Bazel 8.1, Starlark has native support for sets, which removes the need to use sets from bazel_skylib.

So instead of:

sets.make([1, 2, 3])

you can write:

set([1, 2, 3])

Native sets support the usual set algebra, such as union, intersection, difference, and symmetric difference, so this should cover most use cases where you previously reached for bazel_skylib.

Remove function_transition_allowlist when creating transitions

The conventional wisdom used to be that you needed to create a private _allowlist_function_transition attribute for Starlark transitions to work.

That is no longer necessary in modern Bazel versions, so you can remove:

"_allowlist_function_transition": attr.label(
    default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),

repo_name is usually no longer worth keeping

Historically, many repositories used reverse-DNS-style names for external dependencies because that was the common WORKSPACE convention. With Bzlmod, the module name is usually the better default.

For example:

bazel_dep(name = "rules_swift", version = "3.6.1", repo_name = "build_bazel_rules_swift")

can become:

bazel_dep(name = "rules_swift", version = "3.6.1")

This makes labels and load statements shorter and easier to write by hand.

Just make sure you update any remaining references to the old apparent repository name, such as @build_bazel_rules_swift, before removing repo_name.

Start using REPO.bazel

I already wrote about this in my article about dropping .bazelignore and in suppressing warnings in external Swift repositories, so I encourage reading those if you want more details.

The short version is that REPO.bazel gives you a better place to express repository-wide behavior. It marks a repository boundary and lets you set repository-level attributes in a way that fits better with modern Bazel.

compatibility_level is a no-op

If you are a rules author, do not spend time tuning compatibility_level. Starting with Bazel 8.6.0 and 9.1.0, both compatibility_level and max_compatibility_level are no-ops.

This makes me extremely happy because this thing often created more pain for users than it solved. If you introduce a breaking change, it is better to provide clear error messages and an actionable migration path instead of relying on Bazel module version selection to protect users.

A word about flags

In every major Bazel version, there are flags that get removed, become no-ops, or get flipped.

I do not recommend tracking all of that manually. There is a good chance you will miss something, or sometimes get it wrong. The better approach is to use bazelrc-preset.bzl, which applies version-appropriate flags for the Bazel version you are using.

Conclusion

There is probably more cleanup work that I am missing. However, these are low-hanging improvements that are usually easy to apply and easy to review.