Skip to content

馃 wip feat!: publish to BCR as rilla_rules_tf - #29

Draft
dominics wants to merge 8 commits into
mainfrom
dominics/bcr-publishing
Draft

dominics wants to merge 8 commits into
mainfrom
dominics/bcr-publishing

Conversation

@dominics

@dominics dominics commented Sep 6, 2026

Copy link
Copy Markdown
Contributor
馃 LLM generated description follows

Builds everything needed to publish this fork to the Bazel Central Registry, without publishing anything. There is no workflow that calls publish-to-bcr, and the registry PR is opened by hand.

Why a new name

The BCR already carries rules_tf, filed by upstream with repository: ["github:yanndegat/rules_tf"]. Three separate mechanisms stop a fork publishing under it: the source-URL check rejects an archive hosted anywhere else, the existing maintainer would have to approve the PR, and the registry is add-only with no "inactive upstream" escape hatch available (upstream is active). BCR's own maintainer playbook prescribes the remedy - prepend the org, so nobody mistakes a fork for the community standard ruleset.

Only the registry identity moves. repo_name stays rules_tf, which is the name the module calls itself, so all 61 internal @rules_tf// references are untouched and no .bzl file changes in this PR. That matters more than convenience: several of those references are templated into generated toolchain repositories, where a relative // label would resolve to the generated repo rather than to us.

Consumers do change. They must rename the module in bazel_dep and move labels to @rilla_rules_tf//. Passing repo_name = "rules_tf" to bazel_dep keeps the old labels resolving, which lets core-infra and webrtc-sim land the label change separately from the dependency change if they want to. That escape hatch is deliberately not in the README, which shows one canonical form.

Why a release asset

The BCR grades archive stability by URL path alone: on github.com only a /releases/download/ asset counts, and the tarball GitHub generates for a tag is flagged unstable regardless of its bytes. Publishing without an asset means asking a reviewer to waive that check on every version bump. release.yml now builds one with git archive and attaches it. The prefix matches GitHub's own for the same tag, so strip_prefix stays valid either way, and .gitattributes decides what the archive omits.

Why the presubmit target list is not //...

The registry builds a module as a dependency of a synthesized root module, and two things that hold locally stop holding there: dev_dependency modules are not resolved, and --deleted_packages (which hides the child modules under tests/) lives in .bazelrc, which Bazel reads only for a root workspace.

This was verified rather than guessed, by reproducing that setup locally - an empty module depending on this one through archive_override, pointed at the built release archive. @rilla_rules_tf//... fails on rules_shell; the four listed scopes plus two exclusions build 34 targets clean. The two exclusions are aliases into the dev-only multitool hub. Removing the git toolchain (below) is why this needs two exclusion lines rather than upstream's -//tf/toolchains/git:* carve-out.

Scope note

The first commit removes tf/toolchains/git as well as tf/releasing. The git toolchain existed solely to serve the releasing package - its only consumers were tf/releasing/git.bzl and its own implementation files, and MODULE.bazel registered it dev-only with a comment naming //tf/releasing as the reason. Removing one without the other would leave a toolchain, an extension and a registration block with nothing to serve. Neither known consumer references either package at origin/main.

Sequencing

This is expected to land after #18, #19, #26 and #27. It edits tests/bcr*/MODULE.bazel, which those branches are actively reshaping, so conflicts there are expected and should be resolved in favour of their fixture changes plus this PR's two-line rename.

2.2.0 is a placeholder. Nothing is released here; confirm the number when the tag is actually cut.

Follow-ups, not in this PR

  • Consumer migration in core-infra and webrtc-sim.
  • Cutting the tag and hand-opening the registry PR. A first entry needs a BCR maintainer to apply presubmit-auto-run and approve, plus CLA signing.
  • Attestations. BCR marks them experimental, and only accepts source-archive attestations produced by bazel-contrib/.github's release_ruleset.yaml, which would mean restructuring release.yml around a hard-coded script path and a draft-then-finalize dance. Not worth it for a first entry.

Test plan

  • bazel test //... (15 pass), bazel test //tests:integration_tests (4 pass), bazel test //tests:facts_test, bazel run //lint:buildifier.check, //.github:actionlint.
  • purl compared across the change: pkg:bazel/rules_tf on main, pkg:bazel/rules_tf@2.2.0 here.
  • Archive built from branch HEAD (not an existing tag - git archive reads export-ignore from the tree being archived, so an older tag would prove nothing): .github excluded, tests/bcr/MODULE.bazel and patches/ retained, root MODULE.bazel byte-identical to the checked-in one.
  • tests/bcr builds 56 targets and passes 14 tests from inside the extracted archive, confirming its local_path_override(path = "../..") resolves there.

馃 Generated with Claude Code

dominics and others added 8 commits September 7, 2026 10:53
tf/releasing carried release-notes tooling inherited from the Bazel
project -- print_rel_notes.py and git_changelog_private.py, wrapped in
py_binary targets its own BUILD file marked "experimental and subject to
change" as of 2021-06-28. Nothing in this repository, or in either known
consumer, ever called it.

tf/toolchains/git existed solely to serve it: a git toolchain type, a
system-git autoconfiguration extension, and a missing-git fallback, whose
only consumers were tf/releasing/git.bzl and the toolchain's own
implementation files. MODULE.bazel registered it dev-only with a comment
naming //tf/releasing as the reason, so removing the package it served
leaves nothing to register.

Both are the same abandoned bazelbuild convention as the standard_package
filegroups removed in a57b862 -- the halves that were carried across from
upstream without the halves that drove them.

The NOTICE paragraph attributing Bazel-derived code went with them: it
scoped itself to these two trees, and no Bazel-derived portions remain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Bazel Central Registry grades a source archive's stability by URL
path alone: on github.com only a /releases/download/ asset is treated as
stable, and the tarball GitHub generates for a tag is flagged unstable
regardless of its contents. Publishing there without an asset means
asking a BCR reviewer to waive that check on every single version bump.

Build the archive with `git archive` and attach it to the release. The
prefix matches what GitHub generates for the same tag, so a consumer can
move between the two without changing strip_prefix.

.gitattributes decides what the archive omits. It stays deliberately
short: the archive is what the registry consumes, so anything the BCR
presubmit builds has to survive it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The module has never declared one. A registry entry needs it -- the
Bazel Central Registry validates the version in the archive's
MODULE.bazel against the one the entry is filed under -- but it is
already load-bearing here: //:package_metadata builds its purl from
module_version(), which is empty for an unversioned module, so the
package URL emitted for this repository was `pkg:bazel/rules_tf` with
no version at all. It is now `pkg:bazel/rules_tf@2.2.0`.

2.2.0 continues the existing tag series. Bump it with each release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Bazel Central Registry already carries rules_tf, filed by upstream
with an allowlist pinning its source archives to yanndegat/rules_tf. A
fork cannot publish under that name: the source URL check rejects it, the
existing maintainer would have to approve it, and the registry is
add-only. BCR's own guidance is to prepend the org, so that nobody
mistakes a fork for the community standard ruleset.

Only the registry identity changes. repo_name stays "rules_tf", which is
what the module calls itself, so the 61 internal @rules_tf// references
are untouched -- including the ones that cannot be made relative at all,
because they are templated into generated toolchain repositories where
// would resolve to the generated repo rather than to us. No .bzl file
changes.

The child modules under tests/ keep repo_name too, so their fixtures are
untouched; only the name they resolve changes. Their lockfiles record the
canonical repository name, which derives from the module name rather than
from repo_name, so the two checked-in lock files move to
@@rilla_rules_tf+.

BREAKING CHANGE: consumers must rename the module in their bazel_dep and
move their labels from @rules_tf// to @rilla_rules_tf//. Passing
repo_name = "rules_tf" to bazel_dep keeps the old labels working, which
lets the label change land separately from the dependency change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The license block credited The Bazel Authors and pointed readers at
NOTICE for the detail. Removing tf/releasing and tf/toolchains/git took
the last Bazel-derived code with it, and NOTICE no longer mentions them,
so the credit now points at nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
These are the three files the registry entry is generated from, in the
layout bazel-contrib/publish-to-bcr expects. Nothing here publishes
anything: there is no workflow calling publish-to-bcr, so the entry is
still opened by hand.

The presubmit target list is deliberately not //.... The registry builds
a module as a dependency of a synthesized root module, and two things
that hold locally stop holding there: dev_dependency modules are not
resolved, so tests/ and lint/ cannot load; and --deleted_packages, which
hides the child modules under tests/, lives in .bazelrc, which Bazel
reads only for a root workspace. The two excluded tools targets are
aliases into the dev-only multitool hub.

The targets are written against the module name rather than the repo
name, because the synthesized root module does no repo_name remapping.

Verified by reproducing that setup locally -- an empty module depending
on this one through archive_override, pointed at the release archive --
where //... fails on rules_shell and the listed targets build clean.

Maintainers are recorded by github handle and numeric user id, the id
being what survives a rename. The schema requires neither name nor
email, and neither adds anything the handle does not already carry, so
the entry publishes no contact details that would then have to be kept
current. Three maintainers rather than one: approval rights on the
entry are per-maintainer, so a version bump does not wait on any single
person.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The install snippet told readers to pin a git ref, and pinned 1.0.0
against a repository whose tags had reached 2.1.0. Replace it with a
plain bazel_dep, and move the labels in every example to the module's
published name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nothing in the repository named a way to reach anyone, which is thin for
a module about to be consumable by strangers from a public registry.
opensource@rilla.network is the address for that, and it points at a
group rather than a person, so it outlives any individual maintainer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dominics
dominics force-pushed the dominics/bcr-publishing branch from ecd1d9a to 83c6ab6 Compare September 8, 2026 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant