4.11.5 Ruleset CI/CD Patterns

recommended

Ruleset CI/CD is the release gate for a public Bazel API. A ruleset is not ready to publish just because the current checkout builds locally. The tagged commit should prove that its public entry points, example workspaces, generated documentation, supported Bazel versions, and supported platforms still work together. The publishing step in 4.11.4 Publishing Rulesets should receive a green, already-tested release candidate, not discover compatibility problems while creating registry metadata.

Ruleset releases pass a contract gate before publishing
First prove public paths and the support matrix. Then rerun that combined contract on the exact tag before publishing.
Presubmit signals
Prove public paths
fast CI evidence
rule tests

API behavior still passes

examples

README paths still work

docs drift

Generated API docs match

Compatibility matrix
Prove support promise
versions and platforms
min Bazel

Oldest supported version

current LTS

Normal user baseline

rolling lanes

Upcoming breakage signal

Tag gate
Rerun on exact source
release candidate
same checks

No skipped presubmit layer

clean tree

No generated drift remains

artifacts

Downloads match tested code

Publishing handoff
Hand off only when green
publish-ready release
GitHub release

Artifacts and notes attach

BCR metadata

Registry PR finalizes

docs URL

Versioned API is readable

failed lane
Fix code, tests, or compatibility policy

A failing lane means the declared support promise and release candidate disagree.

green gate
Publish from tested source

Publishing automation receives evidence, not a new place to discover breakage.

Presubmit produces signals, matrix and tag gates prove the release candidate, then publishing receives a green handoff.

Treat CI As Part Of The Ruleset Surface

The official deployment guide points new ruleset authors to bazel-contrib/rules-template because it already includes API documentation generation and a CI/CD pipeline for distributing a ruleset.1 That is a useful default stance: a reusable ruleset should come with a predictable ci.yaml path for pull requests and main-branch changes, plus a tag-triggered release.yaml path for releases.2

The presubmit path should run the fast signals that protect contributors: unit-style rule tests, the integration fixtures from 4.5.2 Ruleset Integration Tests, representative examples, formatting or generated-file checks, and documentation generation. Keep this layer close to the commands maintainers run locally. A common entry point such as bazel test //... or a project test script, with independent suites parallelized, keeps the CI shape maintainable as coverage grows.3

pull request / main:
  bazel test //...
  examples smoke tests
  Stardoc or doc extraction targets
  generated-file drift checks, if the repo checks in generated docs

That list is not a generic CI checklist. It is the public ruleset contract. If the README tells users to load //mockascript:defs.bzl, register a toolchain, or copy an example module, CI should exercise those paths before a reviewer has to reason about them by inspection.

Make The Matrix Prove The Version Promise

The matrix is where a ruleset turns its compatibility policy into evidence. Bazel has LTS release tracks and rolling releases from HEAD, so a ruleset that promises compatibility across releases needs CI lanes that reflect those tracks instead of testing only the maintainer's current .bazelversion.4

At minimum, test the oldest supported Bazel version and one forward-looking version. The official rule-compatibility guidance says rules at HEAD should remain compatible with the latest Bazel LTS release and with Bazel at HEAD, either through the ruleset's own CI or Bazel downstream testing.5 A practical variant runs most CI on the latest release of the oldest supported major Bazel version, then keeps a separate job on last_green or a rolling-style version to catch upcoming breakages early.6

compatibility matrix:
  minimum supported Bazel / primary supported OS
  current or latest supported LTS / primary supported OS
  rolling, HEAD, or last_green / allow failure only if the policy says so
  selected OS/architecture lanes for platform-sensitive rules
  legacy WORKSPACE lane only while the ruleset still supports it

Do not let the matrix grow by habit. If a lane protects a declared support promise, keep it. If it only duplicates another lane with no additional signal, remove it or move it to scheduled CI. Platform lanes matter most when the ruleset publishes tools, uses toolchains, depends on native linking, or promises Windows/macOS/Linux support. Running parallel CI across operating systems and architectures is worth the cost when that is part of the compatibility story.7

Re-run The Gate On Tags

A release tag should not skip the checks that protected main. A well-built release workflow starts from the invariant that releases are fully automated by pushing a tag, then reruns tests, checks that the repository has no stray changes, runs a release preparation script, publishes GitHub release artifacts, and hands the release to publish-to-bcr.8 The important rule is that the tag identifies the exact source being released.

For rulesets that publish prebuilt tools, the release gate may also need platform-specific build jobs before publication. A tag-triggered workflow can build artifacts on different operating systems, collect them in the release job, insert integrity data into the archive, and verify that users of the released rules select the prebuilt toolchains rather than rebuilding the tools from source.9 That is CI/CD, not just packaging: the workflow proves that the release artifact matches the user experience the ruleset advertises.

Keep the boundary clear. 4.11.4 Publishing Rulesets explains the mechanics of archives, checksums, release notes, and BCR contribution. Before that handoff, the same build, test, example, compatibility, and docs signals must pass on the tagged source. Publishing automation should receive an already-tested release candidate.

Build Documentation Before Shipping

Documentation generation belongs in the same gate because .bzl documentation is part of the ruleset API. Stardoc's stardoc rule generates Markdown from exported Starlark definitions, and its deps attribute models loaded .bzl dependencies through bzl_library targets.10 The article on 4.5.4 Stardoc — API Documentation covers how to write those rule, provider, attr, function, and macro docs. The CI/CD concern is narrower: make the documentation target build when the API changes.

There are two common release shapes. Some rulesets check generated Markdown into the repository and use a diff test, such as a stardoc_with_diff_test, to catch drift. This is useful but can also make small contributor fixes fail until generated docs are refreshed.11 Newer BCR documentation flows can publish starlark_doc_extract outputs as release artifacts and point module metadata at them with docs_url, so the registry renders versioned API docs next to the module release.12

Either way, the release gate should answer the same question: does the public Starlark API still produce documentation that users can read for this version? If the answer is no, the release should stop before BCR metadata or GitHub release notes make the version look ready.

Read Failures As Compatibility Feedback

A red matrix lane is often a policy mismatch, not an infrastructure annoyance. Maybe the ruleset quietly stopped supporting the oldest Bazel version. Maybe a generated repository name changed. Maybe a test module still uses a legacy setup path that the README no longer recommends. Maybe the rolling lane caught an upcoming Bazel breakage that should become a bug report or downstream-testing issue.

When that happens, choose one of three outcomes: fix the ruleset, narrow the documented support policy in 4.11.6 Rule Compatibility & Bazel Version Policy, or quarantine the lane with an explicit issue and expiration. Silent skips are the dangerous option because they make the next tag look green while users still receive the broken combination.

key takeaway

Ruleset CI/CD is the operational proof of a ruleset's public contract. Presubmit keeps contributors honest, the compatibility matrix proves supported Bazel and platform combinations, tag workflows rerun the gate from the exact source being released, and documentation generation keeps the API surface publishable.

The release job should publish only after those signals pass. If the matrix fails, update the code, the tests, or the compatibility policy before handing the tag to the publishing workflow.

Check your understanding · 3 questions

1.What is the main job of a ruleset release gate?

Select one answer

2.Which lanes are reasonable parts of a ruleset compatibility matrix when they match the support policy?

Select all that apply

3.Match each CI/CD layer to the signal it should provide.

Drag each answer onto the matching prompt, or click an answer and then click a prompt

Answers
Presubmit
Compatibility matrix
Tag gate
Docs gate
0 of 3 answered

Footnotes

  1. Deploying Rules - recommendation to start from bazel-contrib/rules-template, which includes API documentation generation and a CI/CD pipeline.

  2. Deploying Rules - ci.yaml runs tests on pull requests and main, while release.yaml runs when a tag is pushed.

  3. Migrating to Bazel Modules (a.k.a. Bzlmod) - Maintaining Compatibility, Part 3 - common test entry points and parallelizable suites for local and CI compatibility testing.

  4. Release Model - Bazel's rolling and LTS release tracks.

  5. Rule Compatibility - rule authors should test against latest LTS and Bazel at HEAD, using their own CI or downstream testing.

  6. Migrating to Bazel Modules (a.k.a. Bzlmod) - Maintaining Compatibility, Part 3 - CI guidance to use the oldest supported major Bazel version and a last_green lane.

  7. Migrating to Bazel Modules (a.k.a. Bzlmod) - Maintaining Compatibility, Part 3 - running CI in parallel across operating systems and architectures.

  8. Releasing Bazel rulesets that publish tools - tag-triggered automated releases that rerun tests, prepare artifacts, publish GitHub releases, and rely on publish-to-bcr.

  9. Publishing Bazel rules that depend on tools: take 2 - per-platform release jobs, integrity injection, and release tests for prebuilt toolchains.

  10. Stardoc Documentation - stardoc generation, bzl_library dependencies, and output formats.

  11. Bazel Starlark Docs on the Registry - checked-in generated docs guarded by diff tests and the contributor cost of refreshing generated Markdown.

  12. Bazel Starlark Docs on the Registry - publishing starlark_doc_extract outputs as release artifacts and wiring docs_url for BCR-rendered API docs.