rlsbl 0.5.1 → 0.5.2
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/package.json +1 -1
- package/rlsbl/__init__.py +41 -9
- package/rlsbl/commands/check.py +16 -7
- package/rlsbl/commands/discover.py +2 -0
- package/rlsbl/commands/init_cmd.py +7 -1
- package/rlsbl/registries/go.py +1 -0
- package/rlsbl/registries/npm.py +1 -0
- package/rlsbl/registries/pypi.py +1 -0
- package/templates/go/ci.yml.tpl +2 -2
- package/templates/go/publish.yml.tpl +4 -4
- package/templates/merged/publish.yml.tpl +3 -3
- package/templates/npm/ci.yml.tpl +2 -2
- package/templates/npm/publish.yml.tpl +2 -2
- package/templates/pypi/ci.yml.tpl +1 -1
- package/templates/pypi/publish.yml.tpl +1 -1
- package/templates/shared/CLAUDE.md.tpl +1 -1
- package/templates/shared/record-gif.sh.tpl +1 -1
package/package.json
CHANGED
package/rlsbl/__init__.py
CHANGED
|
@@ -3,11 +3,40 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
|
|
7
|
+
def _detect_version():
|
|
8
|
+
"""Detect package version, preferring pyproject.toml over installed metadata.
|
|
9
|
+
|
|
10
|
+
Order: pyproject.toml in the source tree (accurate during editable installs)
|
|
11
|
+
-> importlib.metadata (works for regular installs) -> "unknown".
|
|
12
|
+
"""
|
|
13
|
+
# Try reading version from pyproject.toml next to the package source
|
|
14
|
+
try:
|
|
15
|
+
pyproject_path = os.path.realpath(
|
|
16
|
+
os.path.join(os.path.dirname(__file__), "..", "pyproject.toml")
|
|
17
|
+
)
|
|
18
|
+
if os.path.isfile(pyproject_path):
|
|
19
|
+
try:
|
|
20
|
+
import tomllib
|
|
21
|
+
except ModuleNotFoundError:
|
|
22
|
+
import tomli as tomllib # type: ignore[no-redef]
|
|
23
|
+
with open(pyproject_path, "rb") as f:
|
|
24
|
+
data = tomllib.load(f)
|
|
25
|
+
return data["project"]["version"]
|
|
26
|
+
except Exception:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
# Fall back to installed dist-info metadata
|
|
30
|
+
try:
|
|
31
|
+
from importlib.metadata import version as _get_version
|
|
32
|
+
return _get_version("rlsbl")
|
|
33
|
+
except Exception:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
return "unknown"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
__version__ = _detect_version()
|
|
11
40
|
|
|
12
41
|
REGISTRIES = ("npm", "pypi", "go")
|
|
13
42
|
COMMANDS = ("release", "status", "scaffold", "check", "config", "undo", "discover")
|
|
@@ -145,14 +174,17 @@ def main():
|
|
|
145
174
|
sys.exit(1)
|
|
146
175
|
|
|
147
176
|
if command == "check":
|
|
148
|
-
# check: if registry given, check that one; otherwise check
|
|
177
|
+
# check: if registry given, check that one; otherwise check npm and pypi.
|
|
178
|
+
# Go is excluded from the default set because Go modules use repository
|
|
179
|
+
# paths (e.g. github.com/user/repo), not a flat claimable namespace, so
|
|
180
|
+
# "available" would be misleading. Pass --registry go explicitly to check.
|
|
149
181
|
if registry:
|
|
150
182
|
handler.run_cmd(registry, args, flags)
|
|
151
183
|
else:
|
|
152
|
-
|
|
153
|
-
for i, r in enumerate(
|
|
184
|
+
default_registries = ["npm", "pypi"]
|
|
185
|
+
for i, r in enumerate(default_registries):
|
|
154
186
|
handler.run_cmd(r, args, flags)
|
|
155
|
-
if i < len(
|
|
187
|
+
if i < len(default_registries) - 1:
|
|
156
188
|
print("")
|
|
157
189
|
elif command == "scaffold":
|
|
158
190
|
if registry:
|
package/rlsbl/commands/check.py
CHANGED
|
@@ -168,35 +168,44 @@ def _check_name_pypi(name):
|
|
|
168
168
|
def check_go_availability(name):
|
|
169
169
|
"""Check if a Go module path exists on pkg.go.dev.
|
|
170
170
|
|
|
171
|
-
Returns {"status": "
|
|
171
|
+
Returns {"status": "not_found"|"exists"|"error", "message"?: str, "note"?: str}.
|
|
172
|
+
|
|
173
|
+
Go modules use repository paths (e.g. github.com/user/repo), not a flat
|
|
174
|
+
claimable namespace, so we report "not found" / "exists" rather than the
|
|
175
|
+
"available" / "taken" language used for npm and PyPI.
|
|
172
176
|
"""
|
|
173
177
|
url = f"https://pkg.go.dev/{name}"
|
|
174
178
|
try:
|
|
175
179
|
req = urllib.request.Request(url, method="GET")
|
|
176
180
|
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
177
181
|
if resp.status == 200:
|
|
178
|
-
return {"status": "
|
|
182
|
+
return {"status": "exists"}
|
|
179
183
|
return {"status": "error", "message": f"Unexpected status {resp.status}"}
|
|
180
184
|
except urllib.error.HTTPError as e:
|
|
181
185
|
if e.code == 404:
|
|
182
|
-
return {
|
|
186
|
+
return {
|
|
187
|
+
"status": "not_found",
|
|
188
|
+
"note": "Go modules use repository paths, not a central registry.",
|
|
189
|
+
}
|
|
183
190
|
return {"status": "error", "message": f"Unexpected status {e.code}"}
|
|
184
191
|
except Exception as e:
|
|
185
192
|
return {"status": "error", "message": str(e) or "Network error"}
|
|
186
193
|
|
|
187
194
|
|
|
188
195
|
def _check_name_go(name):
|
|
189
|
-
"""Check Go module path
|
|
196
|
+
"""Check Go module path on pkg.go.dev."""
|
|
190
197
|
print(f'Checking pkg.go.dev for "{name}"...')
|
|
191
198
|
|
|
192
199
|
result = check_go_availability(name)
|
|
193
200
|
if result["status"] == "error":
|
|
194
201
|
print(f"Error checking pkg.go.dev: {result['message']}", file=sys.stderr)
|
|
195
202
|
sys.exit(1)
|
|
196
|
-
if result["status"] == "
|
|
197
|
-
print(f'"{name}"
|
|
203
|
+
if result["status"] == "not_found":
|
|
204
|
+
print(f'"{name}" not found on pkg.go.dev.')
|
|
198
205
|
else:
|
|
199
|
-
print(f'"{name}"
|
|
206
|
+
print(f'"{name}" exists on pkg.go.dev.')
|
|
207
|
+
if result.get("note"):
|
|
208
|
+
print(f" Note: {result['note']}")
|
|
200
209
|
|
|
201
210
|
|
|
202
211
|
def run_cmd(registry, args, flags):
|
|
@@ -133,6 +133,8 @@ def run_cmd(registry, args, flags):
|
|
|
133
133
|
repos = _fetch_all_repos(token)
|
|
134
134
|
except urllib.error.HTTPError as e:
|
|
135
135
|
print(f"Error: GitHub API returned {e.code}: {e.reason}", file=sys.stderr)
|
|
136
|
+
if e.code == 403:
|
|
137
|
+
print("Hint: run 'gh auth login' to increase API rate limits (60/hr unauthenticated → 5000/hr).", file=sys.stderr)
|
|
136
138
|
sys.exit(1)
|
|
137
139
|
except urllib.error.URLError as e:
|
|
138
140
|
print(f"Error: could not reach GitHub API: {e.reason}", file=sys.stderr)
|
|
@@ -177,13 +177,19 @@ def process_mappings(template_dir, mappings, vars_dict, force, update=False,
|
|
|
177
177
|
existing_lines = {
|
|
178
178
|
line.strip() for line in existing.split("\n") if line.strip()
|
|
179
179
|
}
|
|
180
|
+
# Normalize by stripping trailing slashes so e.g.
|
|
181
|
+
# "*.egg-info/" matches "*.egg-info" and vice versa.
|
|
182
|
+
existing_normalized = {
|
|
183
|
+
line.rstrip("/") for line in existing_lines
|
|
184
|
+
}
|
|
180
185
|
new_lines = [
|
|
181
186
|
line.strip() for line in content.split("\n") if line.strip()
|
|
182
187
|
]
|
|
183
188
|
# Only merge non-comment entries that are missing from the existing file
|
|
184
189
|
missing = [
|
|
185
190
|
line for line in new_lines
|
|
186
|
-
if line not in
|
|
191
|
+
if line.rstrip("/") not in existing_normalized
|
|
192
|
+
and not line.startswith("#")
|
|
187
193
|
]
|
|
188
194
|
if missing:
|
|
189
195
|
with open(target, "a", encoding="utf-8") as f:
|
package/rlsbl/registries/go.py
CHANGED
package/rlsbl/registries/npm.py
CHANGED
package/rlsbl/registries/pypi.py
CHANGED
package/templates/go/ci.yml.tpl
CHANGED
|
@@ -13,8 +13,8 @@ jobs:
|
|
|
13
13
|
matrix:
|
|
14
14
|
go-version: ["1.22", "1.23", "1.24"]
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
- uses: actions/setup-go@
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: actions/setup-go@v6
|
|
18
18
|
with:
|
|
19
19
|
go-version: ${{ matrix.go-version }}
|
|
20
20
|
- run: go test ./...
|
|
@@ -11,15 +11,15 @@ jobs:
|
|
|
11
11
|
goreleaser:
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@v6
|
|
15
15
|
with:
|
|
16
16
|
fetch-depth: 0
|
|
17
|
-
- uses: actions/setup-go@
|
|
17
|
+
- uses: actions/setup-go@v6
|
|
18
18
|
with:
|
|
19
19
|
go-version-file: go.mod
|
|
20
|
-
- uses: goreleaser/goreleaser-action@
|
|
20
|
+
- uses: goreleaser/goreleaser-action@v7
|
|
21
21
|
with:
|
|
22
|
-
version:
|
|
22
|
+
version: "~> v2"
|
|
23
23
|
args: release --clean
|
|
24
24
|
env:
|
|
25
25
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -12,8 +12,8 @@ jobs:
|
|
|
12
12
|
npm:
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
16
|
-
- uses: actions/setup-node@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
- uses: actions/setup-node@v6
|
|
17
17
|
with:
|
|
18
18
|
node-version: 22
|
|
19
19
|
registry-url: https://registry.npmjs.org
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
pypi:
|
|
25
25
|
runs-on: ubuntu-latest
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v6
|
|
28
28
|
- uses: astral-sh/setup-uv@v7
|
|
29
29
|
- run: uv build
|
|
30
30
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
package/templates/npm/ci.yml.tpl
CHANGED
|
@@ -13,8 +13,8 @@ jobs:
|
|
|
13
13
|
matrix:
|
|
14
14
|
node-version: [18, 20, 22]
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
- uses: actions/setup-node@
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: actions/setup-node@v6
|
|
18
18
|
with:
|
|
19
19
|
node-version: ${{ matrix.node-version }}
|
|
20
20
|
- run: node -e "require('./package.json')"
|
|
@@ -8,7 +8,7 @@ This project uses [rlsbl](https://github.com/smm-h/rlsbl) for release orchestrat
|
|
|
8
8
|
- Run `rlsbl release [patch|minor|major]` to bump version and create a GitHub Release
|
|
9
9
|
- CI handles publishing automatically via the publish workflow
|
|
10
10
|
- Never publish manually — always use `rlsbl release`
|
|
11
|
-
-
|
|
11
|
+
- {{publishSetup}}
|
|
12
12
|
- Use `rlsbl release --dry-run` to preview a release without making changes
|
|
13
13
|
|
|
14
14
|
## Conventions
|