rlsbl
v0.11.3
Published
Release orchestration and project scaffolding for npm, PyPI, and Go
Maintainers
Readme
rlsbl
Release orchestration and project scaffolding CLI for npm, PyPI, and Go. Pure Python, no dependencies.
Install
From PyPI:
uv tool install rlsblFrom npm (wrapper):
npm i -g rlsblQuick start
rlsbl scaffold # set up CI/CD, hooks, changelog
# ... develop, commit ...
rlsbl release minor # bump, tag, push, create GitHub Release
rlsbl watch <sha> # monitor CI for that releaseCommands
All commands auto-detect registries from project files (package.json, pyproject.toml, go.mod). Use --registry <npm|pypi|go> to target a specific one.
| Command | Description |
|---------|-------------|
| release [patch\|minor\|major] | Bump version, commit, tag, push, create GitHub Release |
| scaffold [--force] [--update] | Scaffold CI/CD, hooks, and release infrastructure |
| status | Show version, branch, last tag, changelog coverage, CI presence |
| check <name> | Check name availability on npm/PyPI/GitHub (parallel variant queries) |
| config [show\|init\|migrate\|status] | Manage project configuration and schema migrations |
| undo [--yes] | Revert the last release (tag, commit, GitHub Release) |
| discover [--mine] | List rlsbl ecosystem projects via GitHub topic search |
| watch [<sha>] | Monitor CI runs for a commit (parallel polling), print workflow audit summary, notify on completion |
| unreleased [--json] | List commits since last tag, report changelog coverage |
| prs | List open pull requests for the current repo |
| targets | List available release targets with detection status |
| record-gif | Record a demo GIF with vhs |
| pre-push-check | Verify CHANGELOG entry exists for the current version |
Global flags: --help, --version, --target <npm|pypi|go>, --registry <npm|pypi|go> (deprecated alias for --target), --no-tag.
Release flow
When you run rlsbl release [patch|minor|major]:
- Verifies
ghCLI is installed and authenticated - Checks working tree is clean
- Fetches origin and verifies local branch is not behind remote (use
--skip-remote-checkfor offline releases) - Reads the current version from the primary project file
- Computes the new version; confirms the tag does not already exist
- Validates
CHANGELOG.mdcontains a## <new-version>section - Runs
.rlsbl/hooks/pre-release.shif present (non-zero exit aborts; receivesRLSBL_VERSION) - Acquires advisory lockfile (
.rlsbl/lock) to prevent concurrent operations - Writes the new version to all detected project files and
.rlsbl/version - Adds
rlsblkeyword to manifests if ecosystem tagging is enabled - Verifies no unexpected files were modified (race condition guard)
- Commits the version bump (uses
safegitif available) - Tags and pushes to
origin - Creates a GitHub Release with the changelog entry as notes
- Adds
rlsbltopic to the GitHub repo (if tagging enabled) - Runs secondary release targets (e.g., docs via selfdoc); use
--include/--excludeto control - Runs
.rlsbl/hooks/post-release.shif present (non-fatal; receivesRLSBL_VERSION) - Prints
Watch CI: rlsbl watch <sha>
Use --dry-run to preview without changes. Use --yes for non-interactive mode (CI, AI agents). Use --skip-remote-check for offline releases.
Multi-target releases: Secondary targets (e.g., docs) run automatically during release. Control which targets run with --include <target> and --exclude <target> (comma-separated). Configure defaults in .rlsbl/config.json via the release_targets list. Use rlsbl targets to see all available targets.
Documentation: Use selfdoc for documentation generation. rlsbl auto-triggers selfdoc during releases when selfdoc.json is detected.
First release: if the current version has never been tagged, release publishes it as-is (bump type is ignored).
Pre-release versions (e.g. 1.0.0-beta.1) are supported.
Scaffold
rlsbl scaffold # create CI/CD for all detected registries
rlsbl scaffold --update # three-way merge template updates with user customizations
rlsbl scaffold --force # overwrite managed files (user-owned files still preserved)
rlsbl scaffold --no-commit # skip auto-commit of scaffolded filesCreated files are committed automatically by default.
| File | Purpose |
|------|---------|
| .github/workflows/ci.yml | CI workflow (lint, test) |
| .github/workflows/publish.yml | Publish on GitHub Release (OIDC) |
| CHANGELOG.md | Version changelog |
| LICENSE | MIT license (author and year filled in) |
| .gitignore | Standard ignores for the ecosystem |
| CLAUDE.md | AI assistant instructions |
| .claude/settings.json | Claude Code settings |
| .rlsbl/hooks/pre-release.sh | User-customizable pre-release validation |
| .rlsbl/hooks/post-release.sh | User-customizable post-release actions |
| .git/hooks/pre-push | One-liner: exec rlsbl pre-push-check "$@" |
| .rlsbl/bases/ | Three-way merge bases for --update |
Three-way merge (--update): Bases are stored at scaffold time. On --update, user customizations and template updates merge via git merge-file. Conflicts get git-style conflict markers.
User-owned files (CHANGELOG.md, LICENSE, hooks) are never overwritten, even with --force.
Runs config migrations when .rlsbl/config-schema.json exists.
Config management
Schema-driven configuration migration system for projects that ship user-facing config files.
rlsbl config init # scaffold config migration infrastructure
rlsbl config migrate # run pending migrations
rlsbl config status # show migration status
rlsbl config show # show resolved project configurationconfig init creates .rlsbl/config-schema.json and a defaults/ directory. Migrations support deep merge, flat merge, and list-by-key merge strategies with versioned schema tracking and atomic writes.
Library API
from rlsbl.lib import ConfigMigrator, load_schema, migrate
# One-liner: load schema and run all pending migrations
result = migrate(".") # returns {filename: was_written} or NoneUndo
rlsbl undo # interactive: confirms before each destructive step
rlsbl undo --yes # non-interactive: auto-confirms, auto-pushesReverts the last release:
- Deletes the GitHub Release
- Deletes the git tag (remote + local)
- Reverts the version bump commit (if HEAD matches the tag)
- Pushes the revert commit (with confirmation, or automatic with
--yes)
On partial failure, prints a structured summary table with remediation commands for each failed step.
Pre-push hook
The .git/hooks/pre-push hook calls rlsbl pre-push-check, which:
- Detects project type (
package.json,pyproject.toml, orVERSION) - Extracts the current version
- Checks that
CHANGELOG.mdcontains a## <version>heading - Blocks the push if the entry is missing
To reinstall manually:
echo '#!/bin/sh' > .git/hooks/pre-push && echo 'exec rlsbl pre-push-check "$@"' >> .git/hooks/pre-push && chmod +x .git/hooks/pre-pushEcosystem tagging
scaffold and release add an "rlsbl" keyword to project manifests and set the rlsbl topic on the GitHub repository, making projects discoverable via rlsbl discover.
To disable:
| Method | Scope |
|--------|-------|
| --no-tag flag | Single invocation |
| {"tag": false} in .rlsbl/config.json | This project |
| {"tag": false} in ~/.rlsbl/config.json | All projects |
Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| RLSBL_PUSH_TIMEOUT | 120 | Timeout in seconds for git push operations |
| RLSBL_VERSION | -- | Set when running pre-release and post-release hooks; contains the version being released |
| GITHUB_TOKEN | -- | Used by gh CLI for GitHub API calls; discover works unauthenticated for public repos |
First publish
| Registry | Setup | Then |
|----------|-------|------|
| npm | Add NPM_TOKEN secret to GitHub repo (Settings > Secrets > Actions) | CI publishes on GitHub Release |
| PyPI | Run uv publish once, then set up Trusted Publishing | CI publishes via OIDC |
| Go | Push tag -- Go modules are published by the tag itself | pkg.go.dev indexes automatically |
Requirements
- Python 3.11+
- GitHub CLI (
gh), installed and authenticated - git
- Node 24+ (for npm CI/publish templates)
License
MIT
