rlsbl 0.8.3 → 0.9.0

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.
Files changed (37) hide show
  1. package/package.json +3 -5
  2. package/rlsbl/__init__.py +0 -247
  3. package/rlsbl/__main__.py +0 -4
  4. package/rlsbl/commands/__init__.py +0 -0
  5. package/rlsbl/commands/check.py +0 -229
  6. package/rlsbl/commands/config.py +0 -67
  7. package/rlsbl/commands/discover.py +0 -198
  8. package/rlsbl/commands/init_cmd.py +0 -518
  9. package/rlsbl/commands/pre_push_check.py +0 -46
  10. package/rlsbl/commands/record_gif.py +0 -92
  11. package/rlsbl/commands/release.py +0 -287
  12. package/rlsbl/commands/status.py +0 -76
  13. package/rlsbl/commands/undo.py +0 -74
  14. package/rlsbl/commands/watch.py +0 -125
  15. package/rlsbl/config.py +0 -57
  16. package/rlsbl/registries/__init__.py +0 -5
  17. package/rlsbl/registries/go.py +0 -123
  18. package/rlsbl/registries/npm.py +0 -119
  19. package/rlsbl/registries/pypi.py +0 -171
  20. package/rlsbl/tagging.py +0 -207
  21. package/rlsbl/templates/go/VERSION.tpl +0 -1
  22. package/rlsbl/templates/go/ci.yml.tpl +0 -18
  23. package/rlsbl/templates/go/goreleaser.yml.tpl +0 -25
  24. package/rlsbl/templates/go/publish.yml.tpl +0 -25
  25. package/rlsbl/templates/merged/publish.yml.tpl +0 -30
  26. package/rlsbl/templates/npm/ci.yml.tpl +0 -22
  27. package/rlsbl/templates/npm/publish.yml.tpl +0 -22
  28. package/rlsbl/templates/pypi/ci.yml.tpl +0 -20
  29. package/rlsbl/templates/pypi/publish.yml.tpl +0 -18
  30. package/rlsbl/templates/shared/CHANGELOG.md.tpl +0 -5
  31. package/rlsbl/templates/shared/CLAUDE.md.tpl +0 -20
  32. package/rlsbl/templates/shared/LICENSE.tpl +0 -21
  33. package/rlsbl/templates/shared/claude-settings.json.tpl +0 -3
  34. package/rlsbl/templates/shared/gitignore.tpl +0 -14
  35. package/rlsbl/templates/shared/hooks/post-release.sh.tpl +0 -8
  36. package/rlsbl/templates/shared/hooks/pre-release.sh.tpl +0 -31
  37. package/rlsbl/utils.py +0 -131
@@ -1,25 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- permissions:
8
- contents: write
9
-
10
- jobs:
11
- goreleaser:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v6
15
- with:
16
- fetch-depth: 0
17
- - uses: actions/setup-go@v6
18
- with:
19
- go-version-file: go.mod
20
- - uses: goreleaser/goreleaser-action@v7
21
- with:
22
- version: "~> v2"
23
- args: release --clean
24
- env:
25
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -1,30 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- permissions:
8
- contents: read
9
- id-token: write
10
-
11
- jobs:
12
- npm:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@v6
16
- - uses: actions/setup-node@v6
17
- with:
18
- node-version: 24
19
- registry-url: https://registry.npmjs.org
20
- - run: npm publish --provenance --access public
21
- env:
22
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
23
-
24
- pypi:
25
- runs-on: ubuntu-latest
26
- steps:
27
- - uses: actions/checkout@v6
28
- - uses: astral-sh/setup-uv@v7
29
- - run: uv build
30
- - uses: pypa/gh-action-pypi-publish@release/v1
@@ -1,22 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- pull_request:
7
- branches: [main]
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- node-version: [20, 22, 24]
15
- steps:
16
- - uses: actions/checkout@v6
17
- - uses: actions/setup-node@v6
18
- with:
19
- node-version: ${{ matrix.node-version }}
20
- - run: node -e "require('./package.json')"
21
- - run: npm test --if-present
22
- - run: npm audit --audit-level=moderate || true
@@ -1,22 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- permissions:
8
- contents: read
9
- id-token: write
10
-
11
- jobs:
12
- publish:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@v6
16
- - uses: actions/setup-node@v6
17
- with:
18
- node-version: 24
19
- registry-url: https://registry.npmjs.org
20
- - run: npm publish --provenance --access public
21
- env:
22
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,20 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- pull_request:
7
- branches: [main]
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- python-version: ["3.12", "3.13", "3.14"]
15
- steps:
16
- - uses: actions/checkout@v6
17
- - uses: astral-sh/setup-uv@v7
18
- - run: uv python install ${{ matrix.python-version }}
19
- - run: uv sync
20
- - run: uv run python -c "import {{importName}}"
@@ -1,18 +0,0 @@
1
- name: Publish
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- permissions:
8
- contents: read
9
- id-token: write
10
-
11
- jobs:
12
- publish:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@v6
16
- - uses: astral-sh/setup-uv@v7
17
- - run: uv build
18
- - uses: pypa/gh-action-pypi-publish@release/v1
@@ -1,5 +0,0 @@
1
- # Changelog
2
-
3
- ## {{version}}
4
-
5
- - Initial release
@@ -1,20 +0,0 @@
1
- # {{name}}
2
-
3
- ## Release workflow
4
-
5
- This project uses [rlsbl](https://github.com/smm-h/rlsbl) for release orchestration.
6
-
7
- - Update CHANGELOG.md with a `## X.Y.Z` entry describing changes
8
- - Run `rlsbl release [patch|minor|major]` to bump version and create a GitHub Release
9
- - CI handles publishing automatically via the publish workflow
10
- - Never publish manually — always use `rlsbl release`
11
- - {{publishSetup}}
12
- - Use `rlsbl release --dry-run` to preview a release without making changes
13
-
14
- ## Conventions
15
-
16
- - No tokens or secrets in command-line arguments (use env vars or config files)
17
- - All file writes to shared state should be atomic (write to tmp, then rename)
18
- - External calls (APIs, CLI tools) must have timeouts and graceful fallbacks
19
- - Use `npm link` (npm) or `uv pip install -e .` (Python) for local development
20
- - CI runs smoke tests on every push; manual testing for UI/UX changes
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) {{year}} {{author}}
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,3 +0,0 @@
1
- {
2
- "hooks": {}
3
- }
@@ -1,14 +0,0 @@
1
- node_modules/
2
- __pycache__/
3
- *.pyc
4
- *.log
5
- .DS_Store
6
- coverage/
7
- dist/
8
- *.egg-info/
9
- .rlsbl-notes-*.tmp
10
- .credentials.json
11
- .*-cache.json
12
- .env
13
- .env.local
14
- *.local-only
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Post-release hook. Runs after a successful release (non-fatal).
3
- # Environment: RLSBL_VERSION is set to the released version.
4
- # Customize this for your project (e.g., local install, deploy, notify).
5
-
6
- set -euo pipefail
7
-
8
- echo "Post-release: v$RLSBL_VERSION"
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Pre-release validation hook.
3
- # Runs before rlsbl creates a release. Exit non-zero to abort.
4
- # Detects project type and runs appropriate checks automatically.
5
-
6
- set -euo pipefail
7
-
8
- echo "Running pre-release checks..."
9
-
10
- if [ -f go.mod ]; then
11
- echo " Go: vet + build + test"
12
- go vet ./...
13
- go build ./...
14
- go test ./... -race -short -count=1
15
- fi
16
-
17
- if [ -f pyproject.toml ]; then
18
- echo " Python: pytest"
19
- if command -v uv &>/dev/null; then
20
- uv run pytest
21
- elif command -v pytest &>/dev/null; then
22
- pytest
23
- fi
24
- fi
25
-
26
- if [ -f package.json ] && node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)" 2>/dev/null; then
27
- echo " npm: test"
28
- npm test
29
- fi
30
-
31
- echo "Pre-release checks passed."
package/rlsbl/utils.py DELETED
@@ -1,131 +0,0 @@
1
- """Git helpers, version bump, changelog extraction, and other shared utilities."""
2
-
3
- import os
4
- import re
5
- import shutil
6
- import subprocess
7
- import sys
8
-
9
-
10
- def run(cmd, args=None, timeout=120, env=None):
11
- """Run a command with args, return trimmed stdout. Raise on failure."""
12
- full_cmd = [cmd] + (args or [])
13
- result = subprocess.run(full_cmd, capture_output=True, text=True, check=True, timeout=timeout, env=env)
14
- return result.stdout.strip()
15
-
16
-
17
-
18
- def is_clean_tree():
19
- """Returns True if the git working tree is clean (no uncommitted changes)."""
20
- status = run("git", ["status", "--porcelain"])
21
- return len(status) == 0
22
-
23
-
24
- def get_current_branch():
25
- """Returns the current git branch name."""
26
- return run("git", ["rev-parse", "--abbrev-ref", "HEAD"])
27
-
28
-
29
- def get_push_timeout():
30
- """Return the push timeout in seconds, from RLSBL_PUSH_TIMEOUT or default 120."""
31
- raw = os.environ.get("RLSBL_PUSH_TIMEOUT")
32
- if raw is None:
33
- return 120
34
- try:
35
- val = int(raw)
36
- if val <= 0:
37
- raise ValueError
38
- return val
39
- except ValueError:
40
- print(f'Warning: invalid RLSBL_PUSH_TIMEOUT="{raw}", using default 120s', file=sys.stderr)
41
- return 120
42
-
43
-
44
- def push_if_needed(branch):
45
- """Push the branch to origin if local is ahead of remote."""
46
- timeout = get_push_timeout()
47
- local = run("git", ["rev-parse", branch])
48
- try:
49
- remote = run("git", ["rev-parse", f"origin/{branch}"])
50
- except subprocess.CalledProcessError:
51
- # Remote branch doesn't exist yet; push it
52
- run("git", ["push", "-u", "origin", branch], timeout=timeout)
53
- return
54
-
55
- if local != remote:
56
- run("git", ["push", "origin", branch], timeout=timeout)
57
-
58
-
59
- def extract_changelog_entry(changelog_path, version):
60
- """Extract a changelog entry for a specific version.
61
-
62
- Looks for a heading like '## 1.2.3' and captures everything
63
- until the next heading or EOF.
64
- """
65
- with open(changelog_path, "r", encoding="utf-8") as f:
66
- content = f.read()
67
-
68
- escaped_version = re.escape(version)
69
- header_pattern = re.compile(r"^## " + escaped_version + r"\s*$", re.MULTILINE)
70
- match = header_pattern.search(content)
71
- if not match:
72
- return None
73
-
74
- # Start after the matched header line
75
- start_idx = match.end()
76
- # Find the next "## " heading or use end of string
77
- next_heading_idx = content.find("\n## ", start_idx)
78
- end_idx = len(content) if next_heading_idx == -1 else next_heading_idx
79
- entry = content[start_idx:end_idx].strip()
80
- return entry or None
81
-
82
-
83
- def check_gh_installed():
84
- """Check that the gh CLI is installed."""
85
- try:
86
- run("gh", ["--version"])
87
- return True
88
- except (subprocess.CalledProcessError, FileNotFoundError):
89
- return False
90
-
91
-
92
- def check_gh_auth():
93
- """Check that the gh CLI is authenticated."""
94
- try:
95
- run("gh", ["auth", "status"])
96
- return True
97
- except (subprocess.CalledProcessError, FileNotFoundError):
98
- return False
99
-
100
-
101
- def find_commit_tool():
102
- """Detect safegit or fall back to git for committing.
103
-
104
- Returns "safegit" if available on PATH, otherwise "git".
105
- """
106
- if shutil.which("safegit"):
107
- return "safegit"
108
- return "git"
109
-
110
-
111
- def bump_version(version, bump_type):
112
- """Bump a semver version string by the given type (patch, minor, major).
113
-
114
- Returns the new version string.
115
- """
116
- parts = version.split(".")
117
- if len(parts) != 3:
118
- raise ValueError(f'Invalid semver version: "{version}"')
119
- try:
120
- major, minor, patch = (int(p) for p in parts)
121
- except ValueError:
122
- raise ValueError(f'Invalid semver version: "{version}"')
123
-
124
- if bump_type == "major":
125
- return f"{major + 1}.0.0"
126
- elif bump_type == "minor":
127
- return f"{major}.{minor + 1}.0"
128
- elif bump_type == "patch":
129
- return f"{major}.{minor}.{patch + 1}"
130
- else:
131
- raise ValueError(f'Invalid bump type: "{bump_type}". Use patch, minor, or major.')