| --- | |
| title: 'Deploying Rules' | |
| --- | |
| This page is for rule writers who are planning to make their rules available | |
| to others. | |
| We recommend you start a new ruleset from the template repository: | |
| https://github.com/bazel-contrib/rules-template | |
| That template follows the recommendations below, and includes API documentation generation | |
| and sets up a CI/CD pipeline to make it trivial to distribute your ruleset. | |
| ## Hosting and naming rules | |
| New rules should go into their own GitHub repository under your organization. | |
| Start a thread on [GitHub](https://github.com/bazelbuild/bazel/discussions) | |
| if you feel like your rules belong in the [bazelbuild](https://github.com/bazelbuild) | |
| organization. | |
| Repository names for Bazel rules are standardized on the following format: | |
| `$ORGANIZATION/rules_$NAME`. | |
| See [examples on GitHub](https://github.com/search?q=rules+bazel&type=Repositories). | |
| For consistency, you should follow this same format when publishing your Bazel rules. | |
| Make sure to use a descriptive GitHub repository description and `README.md` | |
| title, example: | |
| * Repository name: `bazelbuild/rules_go` | |
| * Repository description: *Go rules for Bazel* | |
| * Repository tags: `golang`, `bazel` | |
| * `README.md` header: *Go rules for [Bazel](https://bazel.build)* | |
| (note the link to https://bazel.build which will guide users who are unfamiliar | |
| with Bazel to the right place) | |
| Rules can be grouped either by language (such as Scala), runtime platform | |
| (such as Android), or framework (such as Spring). | |
| ## Repository content | |
| Every rule repository should have a certain layout so that users can quickly | |
| understand new rules. | |
| For example, when writing new rules for the (make-believe) | |
| `mockascript` language, the rule repository would have the following structure: | |
| ``` | |
| / | |
| LICENSE | |
| README | |
| MODULE.bazel | |
| mockascript/ | |
| constraints/ | |
| BUILD | |
| runfiles/ | |
| BUILD | |
| runfiles.mocs | |
| BUILD | |
| mockascript_library.bzl | |
| mockascript_binary.bzl | |
| tests/ | |
| BUILD | |
| some_test.sh | |
| another_test.py | |
| examples/ | |
| BUILD | |
| bin.mocs | |
| lib.mocs | |
| test.mocs | |
| ``` | |
| ### MODULE.bazel | |
| In the project's `MODULE.bazel`, you should define the name that users will use | |
| to reference your rules. If your rules belong to the | |
| [bazelbuild](https://github.com/bazelbuild) organization, you must use | |
| `rules_<lang>` (such as `rules_mockascript`). Otherwise, you should name your | |
| repository `<org>_rules_<lang>` (such as `build_stack_rules_proto`). Please | |
| start a thread on [GitHub](https://github.com/bazelbuild/bazel/discussions) | |
| if you feel like your rules should follow the convention for rules in the | |
| [bazelbuild](https://github.com/bazelbuild) organization. | |
| In the following sections, assume the repository belongs to the | |
| [bazelbuild](https://github.com/bazelbuild) organization. | |
| ``` | |
| module(name = "rules_mockascript") | |
| ``` | |
| ### README | |
| At the top level, there should be a `README` that contains a brief description | |
| of your ruleset, and the API users should expect. | |
| ### Rules | |
| Often times there will be multiple rules provided by your repository. Create a | |
| directory named by the language and provide your public rules and macros in | |
| individual `.bzl` files. This keeps your definitions granular and allows users | |
| to avoid loading every symbol if they only need a subset. Also include a `BUILD` | |
| file so the directory is a package. | |
| ``` | |
| / | |
| mockascript/ | |
| BUILD | |
| mockascript_binary.bzl | |
| mockascript_library.bzl | |
| ``` | |
| ### Constraints | |
| If your rule defines | |
| [toolchain](/extending/toolchains) rules, | |
| it's possible that you'll need to define custom `constraint_setting`s and/or | |
| `constraint_value`s. Put these into a `//<LANG>/constraints` package. Your | |
| directory structure will look like this: | |
| ``` | |
| / | |
| mockascript/ | |
| constraints/ | |
| BUILD | |
| BUILD | |
| mockascript_binary.bzl | |
| mockascript_library.bzl | |
| ``` | |
| Please read | |
| [github.com/bazelbuild/platforms](https://github.com/bazelbuild/platforms) | |
| for best practices, and to see what constraints are already present, and | |
| consider contributing your constraints there if they are language independent. | |
| Be mindful of introducing custom constraints, all users of your rules will | |
| use them to perform platform specific logic in their `BUILD` files (for example, | |
| using [selects](/reference/be/functions#select)). | |
| With custom constraints, you define a language that the whole Bazel ecosystem | |
| will speak. | |
| ### Runfiles library | |
| If your rule provides a standard library for accessing runfiles, it should be | |
| in the form of a library target located at `//<LANG>/runfiles` (an abbreviation | |
| of `//<LANG>/runfiles:runfiles`). User targets that need to access their data | |
| dependencies will typically add this target to their `deps` attribute. | |
| ### Repository rules | |
| #### Dependencies | |
| Your rules might have external dependencies, which you'll need to specify in | |
| your MODULE.bazel file. | |
| #### Registering toolchains | |
| Your rules might also register toolchains, which you can also specify in the | |
| MODULE.bazel file. | |
| Note that in order to resolve toolchains in the analysis phase Bazel needs to | |
| analyze all `toolchain` targets that are registered. Bazel will not need to | |
| analyze all targets referenced by `toolchain.toolchain` attribute. If in order | |
| to register toolchains you need to perform complex computation in the | |
| repository, consider splitting the repository with `toolchain` targets from the | |
| repository with `<LANG>_toolchain` targets. Former will be always fetched, and | |
| the latter will only be fetched when user actually needs to build `<LANG>` code. | |
| #### Release snippet | |
| In your release announcement provide a snippet that your users can copy-paste | |
| into their `MODULE.bazel` file. This snippet in general will look as follows: | |
| ``` | |
| bazel_dep(name = "rules_<LANG>", version = "<VERSION>") | |
| ``` | |
| ### Tests | |
| There should be tests that verify that the rules are working as expected. This | |
| can either be in the standard location for the language the rules are for or a | |
| `tests/` directory at the top level. | |
| ### Examples (optional) | |
| It is useful to users to have an `examples/` directory that shows users a couple | |
| of basic ways that the rules can be used. | |
| ## CI/CD | |
| Many rulesets use GitHub Actions. See the configuration used in the [rules-template](https://github.com/bazel-contrib/rules-template/tree/main/.github/workflows) repo, which are simplified using a "reusable workflow" hosted in the bazel-contrib | |
| org. `ci.yaml` runs tests on each PR and `main` comit, and `release.yaml` runs anytime you push a tag to the repository. | |
| See comments in the rules-template repo for more information. | |
| If your repository is under the [bazelbuild organization](https://github.com/bazelbuild), | |
| you can [ask to add](https://github.com/bazelbuild/continuous-integration/issues/new?template=adding-your-project-to-bazel-ci.md&title=Request+to+add+new+project+%5BPROJECT_NAME%5D&labels=new-project) | |
| it to [ci.bazel.build](http://ci.bazel.build). | |
| ## Documentation | |
| See the [Stardoc documentation](https://github.com/bazelbuild/stardoc) for | |
| instructions on how to comment your rules so that documentation can be generated | |
| automatically. | |
| The [rules-template docs/ folder](https://github.com/bazel-contrib/rules-template/tree/main/docs) | |
| shows a simple way to ensure the Markdown content in the `docs/` folder is always up-to-date | |
| as Starlark files are updated. | |
| ## FAQs | |
| ### Why can't we add our rule to the main Bazel GitHub repository? | |
| We want to decouple rules from Bazel releases as much as possible. It's clearer | |
| who owns individual rules, reducing the load on Bazel developers. For our users, | |
| decoupling makes it easier to modify, upgrade, downgrade, and replace rules. | |
| Contributing to rules can be lighter weight than contributing to Bazel - | |
| depending on the rules -, including full submit access to the corresponding | |
| GitHub repository. Getting submit access to Bazel itself is a much more involved | |
| process. | |
| The downside is a more complicated one-time installation process for our users: | |
| they have to add a dependency on your ruleset in their `MODULE.bazel` file. | |
| We used to have all of the rules in the Bazel repository (under | |
| `//tools/build_rules` or `//tools/build_defs`). We still have a couple rules | |
| there, but we are working on moving the remaining rules out. |