rlsbl 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -112
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,161 +4,156 @@
|
|
|
4
4
|
|
|
5
5
|
# rlsbl
|
|
6
6
|
|
|
7
|
-
Release orchestration and project scaffolding CLI for npm, PyPI, and Go.
|
|
7
|
+
Release orchestration and project scaffolding CLI for npm, PyPI, and Go. Pure Python, no dependencies.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
From
|
|
11
|
+
From PyPI:
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
|
|
14
|
+
uv tool install rlsbl
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
From
|
|
17
|
+
From npm (wrapper):
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
|
|
20
|
+
npm i -g rlsbl
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Quick start
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
rlsbl scaffold
|
|
27
|
-
|
|
26
|
+
rlsbl scaffold # set up CI/CD, hooks, changelog
|
|
27
|
+
# ... develop, commit ...
|
|
28
|
+
rlsbl release minor # bump, tag, push, create GitHub Release
|
|
29
|
+
rlsbl watch <sha> # monitor CI for that release
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
## Commands
|
|
31
33
|
|
|
32
|
-
All commands
|
|
34
|
+
All commands auto-detect registries from project files (`package.json`, `pyproject.toml`, `go.mod`). Use `--registry <npm|pypi|go>` to target a specific one.
|
|
35
|
+
|
|
36
|
+
| Command | Description |
|
|
37
|
+
|---------|-------------|
|
|
38
|
+
| `release [patch\|minor\|major]` | Bump version, commit, tag, push, create GitHub Release |
|
|
39
|
+
| `scaffold [--force] [--update]` | Scaffold CI/CD, hooks, and release infrastructure |
|
|
40
|
+
| `status` | Show version, branch, last tag, changelog coverage, CI presence |
|
|
41
|
+
| `check <name>` | Check name availability on npm/PyPI (parallel variant queries) |
|
|
42
|
+
| `config [show\|init\|migrate\|status]` | Manage project configuration and schema migrations |
|
|
43
|
+
| `undo [--yes]` | Revert the last release (tag, commit, GitHub Release) |
|
|
44
|
+
| `discover [--mine]` | List rlsbl ecosystem projects via GitHub topic search |
|
|
45
|
+
| `watch [<sha>]` | Monitor CI runs for a commit (parallel polling), notify on completion |
|
|
46
|
+
| `unreleased [--json]` | List commits since last tag, report changelog coverage |
|
|
47
|
+
| `prs` | List open pull requests for the current repo |
|
|
48
|
+
| `record-gif` | Record a demo GIF with vhs |
|
|
49
|
+
| `pre-push-check` | Verify CHANGELOG entry exists for the current version |
|
|
50
|
+
|
|
51
|
+
Global flags: `--help`, `--version`, `--registry <npm|pypi|go>`, `--no-tag`.
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
## Release flow
|
|
35
54
|
|
|
36
|
-
|
|
55
|
+
When you run `rlsbl release [patch|minor|major]`:
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
57
|
+
1. Verifies `gh` CLI is installed and authenticated
|
|
58
|
+
2. Checks working tree is clean
|
|
59
|
+
3. Reads the current version from the primary project file
|
|
60
|
+
4. Computes the new version; confirms the tag does not already exist
|
|
61
|
+
5. Validates `CHANGELOG.md` contains a `## <new-version>` section
|
|
62
|
+
6. Runs `.rlsbl/hooks/pre-release.sh` if present (non-zero exit aborts; receives `RLSBL_VERSION`)
|
|
63
|
+
7. Acquires advisory lockfile (`.rlsbl/lock`) to prevent concurrent operations
|
|
64
|
+
8. Writes the new version to all detected project files and `.rlsbl/version`
|
|
65
|
+
9. Adds `rlsbl` keyword to manifests if ecosystem tagging is enabled
|
|
66
|
+
10. Verifies no unexpected files were modified (race condition guard)
|
|
67
|
+
11. Commits the version bump (uses `safegit` if available)
|
|
68
|
+
12. Tags and pushes to `origin`
|
|
69
|
+
13. Creates a GitHub Release with the changelog entry as notes
|
|
70
|
+
14. Adds `rlsbl` topic to the GitHub repo (if tagging enabled)
|
|
71
|
+
15. Runs `.rlsbl/hooks/post-release.sh` if present (non-fatal; receives `RLSBL_VERSION`)
|
|
72
|
+
16. Prints `Watch CI: rlsbl watch <sha>`
|
|
44
73
|
|
|
45
|
-
|
|
74
|
+
Use `--dry-run` to preview without changes. Use `--yes` for non-interactive mode (CI, AI agents).
|
|
46
75
|
|
|
47
|
-
|
|
48
|
-
|---|---|
|
|
49
|
-
| `CLAUDE.md` | Appends rlsbl sections if the marker is not present |
|
|
50
|
-
| `.gitignore` | Merges missing entries from the template |
|
|
51
|
-
| `.github/workflows/ci.yml` | Preserves existing file, prints a note to review manually |
|
|
52
|
-
| All others | Skipped |
|
|
76
|
+
First release: if the current version has never been tagged, `release` publishes it as-is (bump type is ignored).
|
|
53
77
|
|
|
54
|
-
|
|
78
|
+
Pre-release versions (e.g. `1.0.0-beta.1`) are supported.
|
|
55
79
|
|
|
56
|
-
|
|
80
|
+
## Scaffold
|
|
57
81
|
|
|
58
82
|
```
|
|
59
|
-
rlsbl
|
|
60
|
-
rlsbl
|
|
83
|
+
rlsbl scaffold # create CI/CD for all detected registries
|
|
84
|
+
rlsbl scaffold --update # three-way merge template updates with user customizations
|
|
85
|
+
rlsbl scaffold --force # overwrite managed files (user-owned files still preserved)
|
|
86
|
+
rlsbl scaffold --no-commit # skip auto-commit of scaffolded files
|
|
61
87
|
```
|
|
62
88
|
|
|
63
|
-
|
|
89
|
+
Created files are committed automatically by default.
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
| File | Purpose |
|
|
92
|
+
|------|---------|
|
|
93
|
+
| `.github/workflows/ci.yml` | CI workflow (lint, test) |
|
|
94
|
+
| `.github/workflows/publish.yml` | Publish on GitHub Release (OIDC) |
|
|
95
|
+
| `CHANGELOG.md` | Version changelog |
|
|
96
|
+
| `LICENSE` | MIT license (author and year filled in) |
|
|
97
|
+
| `.gitignore` | Standard ignores for the ecosystem |
|
|
98
|
+
| `CLAUDE.md` | AI assistant instructions |
|
|
99
|
+
| `.claude/settings.json` | Claude Code settings |
|
|
100
|
+
| `.rlsbl/hooks/pre-release.sh` | User-customizable pre-release validation |
|
|
101
|
+
| `.rlsbl/hooks/post-release.sh` | User-customizable post-release actions |
|
|
102
|
+
| `.git/hooks/pre-push` | One-liner: `exec rlsbl pre-push-check "$@"` |
|
|
103
|
+
| `.rlsbl/bases/` | Three-way merge bases for `--update` |
|
|
66
104
|
|
|
67
|
-
|
|
105
|
+
**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.
|
|
68
106
|
|
|
69
|
-
|
|
107
|
+
**User-owned files** (CHANGELOG.md, LICENSE, hooks) are never overwritten, even with `--force`.
|
|
70
108
|
|
|
71
|
-
|
|
72
|
-
rlsbl status
|
|
73
|
-
rlsbl status --registry pypi
|
|
74
|
-
```
|
|
109
|
+
**Runs config migrations** when `.rlsbl/config-schema.json` exists.
|
|
75
110
|
|
|
76
|
-
|
|
111
|
+
## Config management
|
|
77
112
|
|
|
78
|
-
|
|
113
|
+
Schema-driven configuration migration system for projects that ship user-facing config files.
|
|
79
114
|
|
|
80
115
|
```
|
|
81
|
-
rlsbl
|
|
82
|
-
rlsbl
|
|
116
|
+
rlsbl config init # scaffold config migration infrastructure
|
|
117
|
+
rlsbl config migrate # run pending migrations
|
|
118
|
+
rlsbl config status # show migration status
|
|
119
|
+
rlsbl config show # show resolved project configuration
|
|
83
120
|
```
|
|
84
121
|
|
|
85
|
-
|
|
122
|
+
`config 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.
|
|
86
123
|
|
|
87
|
-
###
|
|
124
|
+
### Library API
|
|
88
125
|
|
|
89
|
-
|
|
126
|
+
```python
|
|
127
|
+
from rlsbl.lib import ConfigMigrator, load_schema, migrate
|
|
90
128
|
|
|
129
|
+
# One-liner: load schema and run all pending migrations
|
|
130
|
+
result = migrate(".") # returns {filename: was_written} or None
|
|
91
131
|
```
|
|
92
|
-
rlsbl discover
|
|
93
|
-
rlsbl discover --mine # only your repos
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Uses GitHub token if available (higher rate limit). Works unauthenticated for public repos.
|
|
97
132
|
|
|
98
|
-
|
|
133
|
+
## Undo
|
|
99
134
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| Method | Scope |
|
|
105
|
-
|---|---|
|
|
106
|
-
| `--no-tag` flag | Single invocation |
|
|
107
|
-
| `{"tag": false}` in `.rlsbl/config.json` | This project |
|
|
108
|
-
| `{"tag": false}` in `~/.rlsbl/config.json` | All your projects |
|
|
109
|
-
|
|
110
|
-
Precedence: CLI flag > project config > user config > default (enabled).
|
|
111
|
-
|
|
112
|
-
Global flags: `--help`, `--version`.
|
|
135
|
+
```
|
|
136
|
+
rlsbl undo # interactive: confirms before each destructive step
|
|
137
|
+
rlsbl undo --yes # non-interactive: auto-confirms, auto-pushes
|
|
138
|
+
```
|
|
113
139
|
|
|
114
|
-
|
|
140
|
+
Reverts the last release:
|
|
115
141
|
|
|
116
|
-
|
|
142
|
+
1. Deletes the GitHub Release
|
|
143
|
+
2. Deletes the git tag (remote + local)
|
|
144
|
+
3. Reverts the version bump commit (if HEAD matches the tag)
|
|
145
|
+
4. Pushes the revert commit (with confirmation, or automatic with `--yes`)
|
|
117
146
|
|
|
118
|
-
|
|
119
|
-
2. Checks that the git working tree is clean
|
|
120
|
-
3. Reads the current version from the primary project file
|
|
121
|
-
4. Computes the new version and confirms the git tag does not already exist
|
|
122
|
-
5. Validates that `CHANGELOG.md` contains a `## <new-version>` section
|
|
123
|
-
6. Runs `.rlsbl/hooks/pre-release.sh` if present (non-zero exit aborts)
|
|
124
|
-
7. Writes the new version to the primary project file
|
|
125
|
-
8. Syncs the new version to all other detected project files
|
|
126
|
-
9. Commits the version bump (uses `safegit` if available, otherwise `git`)
|
|
127
|
-
10. Pushes the branch to `origin`
|
|
128
|
-
11. Creates a GitHub Release tagged `v<new-version>` with the changelog entry as notes
|
|
129
|
-
12. The GitHub Release triggers `publish.yml`, which publishes to the registry
|
|
130
|
-
13. Runs `.rlsbl/hooks/post-release.sh` if present (non-fatal -- the release is already complete). The `RLSBL_VERSION` env var is set to the released version. Useful for local install (`go install ./cmd/myapp/`), deploy, or notifications.
|
|
131
|
-
14. Spawns a background process that watches CI via `gh run watch`. When CI finishes, it prints the result to stderr (so AI agents can read it) and sends a desktop notification (`notify-send` on Linux, `osascript` on macOS). On CI failure, it also prints the GitHub Actions run URL. This happens automatically -- no configuration needed.
|
|
132
|
-
|
|
133
|
-
## What scaffold creates
|
|
134
|
-
|
|
135
|
-
| File | Source | Purpose |
|
|
136
|
-
|---|---|---|
|
|
137
|
-
| `.github/workflows/ci.yml` | Registry-specific | CI workflow (lint, test) |
|
|
138
|
-
| `.github/workflows/publish.yml` | Registry-specific | Publish on GitHub Release (OIDC) |
|
|
139
|
-
| `CHANGELOG.md` | Shared | Version changelog |
|
|
140
|
-
| `LICENSE` | Shared | MIT license (author and year filled in) |
|
|
141
|
-
| `.gitignore` | Shared | Standard ignores for the ecosystem |
|
|
142
|
-
| `CLAUDE.md` | Shared | AI assistant instructions |
|
|
143
|
-
| `.claude/settings.json` | Shared | Claude Code settings |
|
|
144
|
-
| `.rlsbl/hooks/pre-release.sh` | Shared | User-customizable pre-release validation |
|
|
145
|
-
| `.rlsbl/hooks/post-release.sh` | Shared | User-customizable post-release actions |
|
|
146
|
-
| `.git/hooks/pre-push` | Shared | One-liner that calls `rlsbl pre-push-check` |
|
|
147
|
-
|
|
148
|
-
Hook files are made executable automatically. The `record-gif` and `pre-push-check` functionality is provided as built-in subcommands (`rlsbl record-gif`, `rlsbl pre-push-check`) rather than scaffolded scripts.
|
|
149
|
-
|
|
150
|
-
The scaffolded `.gitignore` includes a `*.local-only` pattern. Create a `.local-only/` directory or rename files with a `.local-only` suffix to keep them out of version control -- useful for local-only assets, experiments, and keeping the working tree clean for tools that check `git status`.
|
|
147
|
+
On partial failure, prints a structured summary table with remediation commands for each failed step.
|
|
151
148
|
|
|
152
149
|
## Pre-push hook
|
|
153
150
|
|
|
154
|
-
The
|
|
155
|
-
|
|
156
|
-
How it works:
|
|
151
|
+
The `.git/hooks/pre-push` hook calls `rlsbl pre-push-check`, which:
|
|
157
152
|
|
|
158
153
|
1. Detects project type (`package.json`, `pyproject.toml`, or `VERSION`)
|
|
159
154
|
2. Extracts the current version
|
|
160
|
-
3. Checks that `CHANGELOG.md` contains a
|
|
161
|
-
4. Blocks the push
|
|
155
|
+
3. Checks that `CHANGELOG.md` contains a `## <version>` heading
|
|
156
|
+
4. Blocks the push if the entry is missing
|
|
162
157
|
|
|
163
158
|
To reinstall manually:
|
|
164
159
|
|
|
@@ -166,30 +161,40 @@ To reinstall manually:
|
|
|
166
161
|
echo '#!/bin/sh' > .git/hooks/pre-push && echo 'exec rlsbl pre-push-check "$@"' >> .git/hooks/pre-push && chmod +x .git/hooks/pre-push
|
|
167
162
|
```
|
|
168
163
|
|
|
169
|
-
##
|
|
164
|
+
## Ecosystem tagging
|
|
170
165
|
|
|
171
|
-
|
|
166
|
+
`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`.
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
|---|---|---|
|
|
175
|
-
| npm | Add an `NPM_TOKEN` secret to your GitHub repo (Settings > Secrets > Actions), then push a release | CI handles subsequent publishes |
|
|
176
|
-
| PyPI | Run `uv publish` | Set up [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) on pypi.org |
|
|
177
|
-
| Go | Push to GitHub and create a release -- Go modules are published by the tag itself | No secrets needed; `pkg.go.dev` indexes automatically |
|
|
168
|
+
To disable:
|
|
178
169
|
|
|
179
|
-
|
|
170
|
+
| Method | Scope |
|
|
171
|
+
|--------|-------|
|
|
172
|
+
| `--no-tag` flag | Single invocation |
|
|
173
|
+
| `{"tag": false}` in `.rlsbl/config.json` | This project |
|
|
174
|
+
| `{"tag": false}` in `~/.rlsbl/config.json` | All projects |
|
|
180
175
|
|
|
181
176
|
## Environment variables
|
|
182
177
|
|
|
183
178
|
| Variable | Default | Description |
|
|
184
179
|
|----------|---------|-------------|
|
|
185
|
-
| `RLSBL_PUSH_TIMEOUT` | `120` | Timeout in seconds for `git push` operations
|
|
186
|
-
| `RLSBL_VERSION` | -- | Set
|
|
180
|
+
| `RLSBL_PUSH_TIMEOUT` | `120` | Timeout in seconds for `git push` operations |
|
|
181
|
+
| `RLSBL_VERSION` | -- | Set when running pre-release and post-release hooks; contains the version being released |
|
|
182
|
+
| `GITHUB_TOKEN` | -- | Used by `gh` CLI for GitHub API calls; `discover` works unauthenticated for public repos |
|
|
183
|
+
|
|
184
|
+
## First publish
|
|
185
|
+
|
|
186
|
+
| Registry | Setup | Then |
|
|
187
|
+
|----------|-------|------|
|
|
188
|
+
| npm | Add `NPM_TOKEN` secret to GitHub repo (Settings > Secrets > Actions) | CI publishes on GitHub Release |
|
|
189
|
+
| PyPI | Run `uv publish` once, then set up [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) | CI publishes via OIDC |
|
|
190
|
+
| Go | Push tag -- Go modules are published by the tag itself | `pkg.go.dev` indexes automatically |
|
|
187
191
|
|
|
188
192
|
## Requirements
|
|
189
193
|
|
|
190
|
-
-
|
|
194
|
+
- Python 3.11+
|
|
191
195
|
- [GitHub CLI](https://cli.github.com) (`gh`), installed and authenticated
|
|
192
196
|
- git
|
|
197
|
+
- Node 24+ (for npm CI/publish templates)
|
|
193
198
|
|
|
194
199
|
## License
|
|
195
200
|
|