Release Process for rules_typescript¶
Cutting a tag through to a Bazel Central Registry submission.
Nothing has been released yet: there are no git tags and no GitHub releases, so
every version number below (0.2.0, 0.2.1, …) shows the shape a release takes.
MODULE.bazel reads 0.2.0 and every install snippet on the site names it, so
that is the version a first release cuts. See
BCR Submission for current status.
Prerequisites¶
Before releasing, ensure:
-
All tests pass — the lane CI runs, named in
.bazelrc:e2e/andexamples/are separate workspaces, so they are separate invocations:cd e2e/basic && bazel test //..., thenbazel build //...in eachexamples/*directory. -
Determinism is verified — build one target from two empty output bases and compare, which is what the
determinismjob in.github/workflows/ci.ymldoes: -
Working tree is clean
-
Decide on version number (follow semantic versioning)
- Major version: Breaking changes
- Minor version: New features (backward compatible)
- Patch version: Bug fixes
-
Pre-release: X.Y.Z-rc.1, X.Y.Z-alpha, etc.
-
Fold the changelog — entries since the last release live in
changelog.d/, one file per PR, and are not inCHANGELOG.mduntil this runs:It inserts the assembled section above the newest release and deletes the fragments it consumed. It belongs here rather than after Step 1:bazel run //tools/changelog # preview bazel run //tools/changelog -- --version 0.2.0 --write # write and clear git add CHANGELOG.md changelog.d git commit -m "docs(changelog): assemble v0.2.0"//tools/releaserefuses to run against a dirty working tree, and the tag has to carry the changelog.
Step 1: Bump, Commit, Tag¶
bazel run //tools/release -- 0.2.0 --dry-run # prints every step, writes nothing
bazel run //tools/release -- 0.2.0
The tool acts on the checkout you ran bazel from (BUILD_WORKING_DIRECTORY)
and:
- Validates the version format
- Stops if the tag already exists or the working tree is dirty
- Rewrites the version inside
module()inMODULE.bazel— and only there, sobazel_depversions are untouched - Commits
MODULE.bazelaschore: release v0.2.0 - Creates the annotated tag
v0.2.0
It stops there. Everything downstream of the tag belongs to
.github/workflows/release.yml: it builds the tarball with git archive,
computes the SRI hash, publishes the GitHub release with a build-provenance
attestation, and opens the PR that fills in .bcr/source.json. A tarball built
locally is a different archive from the published one, and so carries a wrong
integrity hash.
Example Output¶
Repository: /home/you/src/rules_typescript
Release: v0.2.0
[1/3] MODULE.bazel: module version 0.1.0 -> 0.2.0
[2/3] commit MODULE.bazel
[3/3] tag v0.2.0
Nothing has been pushed. To publish:
git push origin v0.2.0
That starts .github/workflows/release.yml: tarball, GitHub release, and the
.bcr/source.json PR. To undo instead: git tag -d v0.2.0 && git reset --hard HEAD~1
Step 2: Push to GitHub¶
Pushing the tag starts the Release workflow:
bazel run //tools/release -- 0.2.0 --push does the bump, tag, and push in one
go.
Verify the tag is visible:
Step 3: Watch the Release Workflow¶
The push in Step 2 triggers .github/workflows/release.yml, which creates the
GitHub release, attaches the git archive tarball, and opens the
.bcr/source.json PR. Nothing here is manual:
The workflow publishes with prerelease: false, so mark the release as a
prerelease by hand if the version carries an -rc.N, -alpha.N, or -beta.N
suffix.
Step 4: Submit to Bazel Central Registry¶
This is the manual half, written out once in
BCR Submission: fork the registry, create
modules/rules_typescript/<version>/, copy .bcr/metadata.json,
.bcr/source.json and .bcr/presubmit.yml into it, push, open the PR. Follow
that page.
Check one thing before starting: the .bcr/source.json PR the release workflow
opened has merged, so the file you are copying carries the real integrity hash
and not the empty placeholder.
Step 5: Respond to BCR Feedback¶
The BCR maintainers will review your submission. They may:
- Request changes to metadata or configuration
- Verify the integrity hash by downloading and hashing the tarball
- Ask about compatibility with their build system
- Request documentation updates
Common issues:
- Integrity mismatch: Recalculate hash and update source.json
- Missing metadata: Add required fields to metadata.json
- Non-deterministic build: rerun the determinism check in Prerequisites and fix what differs
- Licensing: Ensure LICENSE file is included in tarball
Rollback and Fixes¶
If Something Goes Wrong Before Push¶
If you haven't pushed yet, you can undo:
# Undo the tag
git tag -d v0.2.0
# Undo the commit (the tool only ever touches MODULE.bazel)
git reset --hard HEAD~1
Then fix the issue and try again.
If Something Goes Wrong After Push¶
If you've already pushed:
- Don't delete the tag (others may have fetched it)
- Create a new patch release (e.g., v0.2.1)
- Document the issue in the v0.2.0 release notes
Example:
Pre-release Workflow¶
For testing before a major release, use pre-release versions:
bazel run //tools/release -- 0.2.0-rc.1
bazel run //tools/release -- 0.2.0-beta.1
bazel run //tools/release -- 0.2.0-alpha.1
These do not need BCR submission. release.yml publishes every tag with
prerelease: false, so tick "Set as a pre-release" on the GitHub release
afterwards.
Verification Checklist¶
Before declaring release complete:
- [ ]
bazel test --config=ci //...passes, and thee2e/andexamples/workspaces build - [ ] The determinism check in Prerequisites passes
- [ ] Git tag is created and pushed
- [ ] GitHub release is published with tarball
- [ ] Tarball is downloadable from GitHub
- [ ] SHA256 hash in source.json is correct
- [ ] BCR PR is created with metadata
- [ ] No uncommitted changes remain
- [ ] Version number is incremented in next development cycle
Development Workflow After Release¶
After releasing v0.2.0, prepare for v0.2.1:
-
Update MODULE.bazel to next development version:
-
Continue development normally
-
When ready for next release:
Resources¶
- BCR Contributing Guide: https://github.com/bazelbuild/bazel-central-registry/blob/main/CONTRIBUTING.md
- Semantic Versioning: https://semver.org/
- Bazel Module Specification: https://bazel.build/external/module_registry
- GitHub Releases Help: https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases
Troubleshooting¶
"Tag v0.2.0 already exists"¶
Someone has already released this version:
# Check existing tags
git tag -l | grep v0.2.0
# Create a patch version instead
bazel run //tools/release -- 0.2.1
"Integrity hash is different"¶
The tarball differs. Causes:
- Different git commit used
- Timestamps in generated files
- Environment-specific build artifacts
Solution:
# Verify determinism (see Prerequisites for the two-output-base sequence)
bazel build --config=determinism //tests/smoke:hello
# Check git status
git status
# Recalculate hash. The tarball name carries no `v` -- the workflow strips it
# from the tag before naming the archive.
sha256sum rules_typescript-0.2.0.tar.gz
"Module files are not valid YAML"¶
Your metadata.json or source.json has invalid syntax. Usual causes: a trailing comma, an unquoted string, a missing brace. A stdlib-only local check:
python3 -m json.tool .bcr/metadata.json > /dev/null
python3 -m json.tool .bcr/source.json > /dev/null
This is a maintainer's local convenience. No rule, action or toolchain in rules_typescript uses Python.
Next Steps¶
After BCR submission is approved, the module will be available:
Users can add this to their MODULE.bazel file and use rules_typescript.
For questions or issues, see CI_CD.md or the documentation index.