Bazel Central Registry (BCR) Submission Guide¶
Current status: nothing has been released. There are no git tags, no GitHub
releases, and .bcr/metadata.json still has an empty versions list, so
registry.bazel.build/modules/rules_typescript does not exist.
.bcr/source.json is a placeholder: its URL points at a tarball that was never
published and its integrity is empty. The release workflow fills both in when a
tag is pushed. Until then consumers pin the ruleset with a non-registry override,
per
Depending on rules_typescript.
Overview¶
Pushing a tag does everything up to and including the .bcr/source.json PR.
Getting that into the registry is a pull request a person opens by hand against
another repository.
- Release Workflow (
.github/workflows/release.yml) — automated - Triggered on git tag push (e.g.
git tag v0.2.0) - Builds the
git archivetarball, computes the SHA256 in hex and SRI form - Creates the GitHub release with a build-provenance attestation
-
Opens the PR that fills in
.bcr/source.json -
Publish to BCR Workflow (
.github/workflows/publish-to-bcr.yml) — a pre-flight check. It asserts that.bcr/metadata.json,.bcr/source.jsonand.bcr/presubmit.ymlexist and that the two JSON files parse (jq -e),HEADs the tarball URL (a warning, not a failure), prints the manual submission checklist, and uploads the three files as an artifact. On a release event it also rewrites that release's notes to point at the metadata. It opens no pull request against the registry. The manual route is Submission Steps below.
Release Process¶
1. Create a Release¶
Release versions follow semantic versioning: X.Y.Z
# Set version variable
VERSION="0.2.0"
# Create and push the tag by hand
git tag -a "v${VERSION}" -m "rules_typescript ${VERSION}"
git push origin "v${VERSION}"
Or use the release tool, which does the local half:
bazel run //tools/release -- 0.2.0 --dry-run # print every step, mutate nothing
bazel run //tools/release -- 0.2.0 --push # bump, commit, tag, push
It validates the version format, checks that the git working tree is clean, bumps
module(version) in MODULE.bazel, commits that, creates the annotated tag
v<version>, and with --push pushes it, which starts the Release workflow. It
builds no tarball and computes no integrity hash: an archive built locally is not
the archive GitHub publishes. Everything downstream of the tag — git archive,
the GitHub release, the SRI hash and the .bcr/source.json update — is
.github/workflows/release.yml.
2. GitHub Release Creation¶
When you push the tag, GitHub Actions automatically:
- Builds the release tarball
- Generates SLSA attestation for supply chain security
- Creates a GitHub Release
- Opens a PR updating
.bcr/source.json
The release workflow output includes:
- version: Semantic version (e.g., 0.2.0)
- tarball: Compressed archive (e.g., rules_typescript-0.2.0.tar.gz)
- sha256: The hash in hex, as sha256sum prints it
- integrity: The same hash in SRI format (sha256-<base64>), which is what
.bcr/source.json carries
3. Verify Release Artifacts¶
After the workflow completes:
- Check GitHub Releases: https://github.com/mikn/rules_typescript/releases
- Verify tarball download works
- Check SHA256 hash matches the build output
# Verify integrity
wget https://github.com/mikn/rules_typescript/releases/download/v0.2.0/rules_typescript-0.2.0.tar.gz
sha256sum rules_typescript-0.2.0.tar.gz
BCR Submission Process¶
Prerequisites¶
- Release tag exists on GitHub with tarball and attestation
- All CI checks pass (tests, validation, examples)
- MODULE.bazel version is updated
- .bcr/source.json has correct integrity hash
Submission Steps¶
The BCR submission must be done via GitHub PR to https://github.com/bazelbuild/bazel-central-registry
Copy the Metadata into a BCR Fork¶
-
Fork https://github.com/bazelbuild/bazel-central-registry
-
Clone your fork:
-
Create a feature branch:
-
Create the module directory:
-
Copy metadata files from rules_typescript repo:
-
Verify the files:
-
Commit and push:
-
Create PR on GitHub:
- Go to https://github.com/bazelbuild/bazel-central-registry
- Click "New Pull Request"
- Select your fork and branch
- Fill PR title: "Add rules_typescript 0.2.0"
- Fill PR description with details from release notes
The Pre-Flight Check¶
The steps above are the only submission route. This workflow validates what you are about to copy and prints the same checklist:
It also lists release: [published] as a trigger, but the release
release.yml creates does not fire it: GitHub starts no workflow run from an
event raised with the default GITHUB_TOKEN. A release published by hand does
fire it. See CI/CD.
BCR Metadata Files¶
.bcr/metadata.json¶
Contains module-level information (shared across all versions):
{
"homepage": "https://github.com/mikn/rules_typescript",
"maintainers": [
{
"name": "Your Name",
"email": "you@example.com",
"github": "your-github-handle"
}
],
"repository": ["github:mikn/rules_typescript"],
"versions": [],
"yanked_versions": {}
}
Note: The BCR system maintains the versions and yanked_versions arrays. Do not edit them by hand.
.bcr/source.json¶
Version-specific release information:
{
"url": "https://github.com/mikn/rules_typescript/releases/download/v0.2.0/rules_typescript-0.2.0.tar.gz",
"integrity": "sha256-<base64-hash>",
"strip_prefix": "rules_typescript-0.2.0"
}
Fields: - url: Direct link to release tarball (must be GitHub Releases) - integrity: SRI-format hash (sha256-base64) - strip_prefix: Top-level directory in tarball (removes prefix when extracting)
.bcr/presubmit.yml¶
Testing configuration for BCR's CI system:
bcr_test_module:
module_path: "e2e/basic"
matrix:
platform:
- debian11
- macos_arm64
bazel:
- "8.x"
- "9.x"
tasks:
run_tests:
build_targets:
- "//..."
test_targets:
- "//..."
build_flags:
- "--keep_going"
test_flags:
- "--test_output=short"
Defines: - module_path: Path to test module within the repository - matrix: Combinations of platforms and Bazel versions to test - tasks: Build and test targets, plus the flags each invocation gets
Adding SOURCE.md (Optional)¶
For complex build requirements, add SOURCE.md at the repository root, which is
where publish-to-bcr.yml looks for it:
# Building rules_typescript from source
## Prerequisites
- Bazel 9+
- Rust 1.98+
- Go 1.26+
## Build Instructions
### Building oxc_cli
The oxc Rust CLI requires the Rust toolchain. It's automatically built by Bazel's crate_universe extension.
Add this when the standard tarball extraction and build procedure needs documentation.
CI/CD Workflows¶
Release Workflow¶
File: .github/workflows/release.yml
Triggered by: Git tag push matching v*
Steps:
1. Extract version from tag
2. Build release tarball from git archive
3. Compute SHA256 hash (both hex and SRI format)
4. Generate SLSA build provenance attestation
5. Create GitHub Release with tarball
6. Upload release info for BCR workflow
7. Rewrite .bcr/source.json with the URL, integrity hash and strip_prefix
8. Create PR with the updated .bcr/source.json
Outputs: - GitHub Release with tarball and attestation - PR updating .bcr/source.json with correct hash
Publish to BCR Workflow¶
File: .github/workflows/publish-to-bcr.yml
Triggered by: - Manual workflow dispatch with version - Automatic on release publication
Steps:
1. Determine version (from workflow input or release tag)
2. Validate BCR metadata files exist
3. Validate JSON format of metadata files
4. Verify release exists on GitHub
5. Check tarball download availability
6. Generate submission summary and checklist
7. On a release event, replace the release notes with a line pointing at the BCR
metadata (gh release edit --notes), which overwrites the generated notes
8. Upload metadata artifacts for reference
Release Checklist¶
Before cutting a release:
- [ ] All commits are properly reviewed and merged
- [ ] CI tests pass (unit tests, E2E, examples)
- [ ] Type checking passes (validation)
- [ ] Determinism check passes
- [ ] Integration tests pass
- [ ] README is up-to-date
- [ ] CHANGELOG or release notes prepared
- [ ] MODULE.bazel version is in main branch (can be done by release script)
For the actual release:
- [ ] Tag version using
git tag v0.2.0orbazel run //tools/release -- 0.2.0 - [ ] Push tag:
git push origin v0.2.0 - [ ] Verify GitHub Actions workflows complete successfully
- [ ] Download tarball and verify integrity
- [ ] Check .bcr/metadata.json is correct
- [ ] Check .bcr/source.json has correct hash
- [ ] Submit to BCR following the steps above
For BCR submission:
- [ ] Fork bazel-central-registry
- [ ] Create feature branch
- [ ] Copy metadata files to correct location
- [ ] Verify file format and contents
- [ ] Commit and push
- [ ] Create PR with descriptive title and body
- [ ] Wait for BCR pre-submission tests to pass
- [ ] Respond to reviewer feedback if any
Troubleshooting¶
Release Workflow Fails¶
Check the workflow logs: - Go to Actions tab in GitHub - Click on the failed "Release" workflow - Check step output for error details
Common issues: - Module.bazel version mismatch: Ensure release script was run or version was manually updated - Tarball creation failed: Check git archive command and directory structure - Hash computation failed: Verify sha256sum and xxd are available (should be on Ubuntu)
BCR Metadata Issues¶
The BCR PR's own presubmit validates all three files and names the file and line it rejected. It is the authority. For a faster local check on the two JSON files, with nothing to install:
python3 -m json.tool .bcr/metadata.json > /dev/null
python3 -m json.tool .bcr/source.json > /dev/null
json.tool is stdlib, so any python3 will do. .bcr/presubmit.yml has no
stdlib equivalent; the presubmit covers that one.
This is a maintainer's local convenience. No rule, action or toolchain in rules_typescript uses Python.
Integrity Hash Mismatch¶
Recalculate the correct hash:
VERSION="0.2.0"
TARBALL="rules_typescript-${VERSION}.tar.gz"
# Download from GitHub release
wget https://github.com/mikn/rules_typescript/releases/download/v${VERSION}/${TARBALL}
# Calculate SHA256 hash in SRI format
SHA256_HEX=$(sha256sum ${TARBALL} | awk '{print $1}')
SHA256_BASE64=$(echo -n "${SHA256_HEX}" | xxd -r -p | base64 -w0)
echo "sha256-${SHA256_BASE64}"
Update .bcr/source.json with the correct integrity value.
BCR Submission Best Practices¶
- Use GitHub Releases: The tarball must be hosted on GitHub Releases, not arbitrary URLs
- Include attestation: Always generate SLSA provenance attestation for supply chain security
- Test before submission: Run the e2e/basic tests to ensure module works
- Clear descriptions: Provide detailed release notes and PR descriptions
- Respond quickly: BCR maintainers may request changes or clarifications
- Semantic versioning: Follow SemVer for version numbering (e.g., 0.2.0, not v0.2.0)
- Minimal files: Only include necessary files in tarball, exclude test artifacts and caches