-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathversion
More file actions
executable file
·154 lines (122 loc) · 4.75 KB
/
version
File metadata and controls
executable file
·154 lines (122 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
"""Version management for the plugin.
Show, bump, commit, and tag versions. Pure stdlib — no dependencies.
Usage:
./version # show current version
./version bump # bump patch (0.1.0 → 0.1.1)
./version bump --minor # bump minor (0.1.1 → 0.2.0)
./version bump --major # bump major (0.2.0 → 1.0.0)
./version bump --no-tag # bump + commit but skip the git tag
"""
import argparse
import json
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent
PLUGIN_JSON = REPO_ROOT / ".claude-plugin" / "plugin.json"
# All files that contain the version. Each entry is (path, reader, writer).
# Add new entries here when version appears in more places.
VERSION_FILES = [PLUGIN_JSON]
def _read_version() -> str:
"""Read current version from plugin.json."""
data = json.loads(PLUGIN_JSON.read_text())
return data["version"]
def _write_version(new_version: str) -> list[Path]:
"""Write new version to all version files. Returns files modified."""
modified = []
for path in VERSION_FILES:
if path == PLUGIN_JSON:
data = json.loads(path.read_text())
if data.get("version") != new_version:
data["version"] = new_version
path.write_text(json.dumps(data, indent=2) + "\n")
modified.append(path)
return modified
def _parse_version(v: str) -> tuple[int, int, int]:
parts = v.split(".")
if len(parts) != 3:
print(f"Error: version '{v}' is not semver (expected X.Y.Z)")
sys.exit(1)
try:
return int(parts[0]), int(parts[1]), int(parts[2])
except ValueError:
print(f"Error: version '{v}' contains non-numeric parts")
sys.exit(1)
def _bump(major: int, minor: int, patch: int, level: str) -> str:
if level == "major":
return f"{major + 1}.0.0"
elif level == "minor":
return f"{major}.{minor + 1}.0"
else:
return f"{major}.{minor}.{patch + 1}"
def cmd_show(args):
print(_read_version())
def cmd_bump(args):
old = _read_version()
major, minor, patch = _parse_version(old)
if args.major:
level = "major"
elif args.minor:
level = "minor"
else:
level = "patch"
new = _bump(major, minor, patch, level)
print(f"{old} → {new}")
modified = _write_version(new)
if not modified:
print("No files changed — version was already correct?")
sys.exit(1)
# Stage and commit
for path in modified:
rel = path.relative_to(REPO_ROOT)
subprocess.run(["git", "add", str(rel)], cwd=REPO_ROOT, check=True)
subprocess.run(
["git", "commit", "-m", f"Bump version to {new}"],
cwd=REPO_ROOT, check=True,
)
if not args.no_tag:
subprocess.run(
["git", "tag", "-a", f"v{new}", "-m", f"Release v{new}"],
cwd=REPO_ROOT, check=True,
)
print(f"Tagged v{new}")
else:
print("Skipped tag (--no-tag)")
tag = f"v{new}"
name = json.loads(PLUGIN_JSON.read_text()).get("name", "claude-coding-plugin")
mp = "../claude-plugins/.claude-plugin/marketplace.json"
print(f"\nNext steps:")
print(f" 1. Push this repo:")
print(f" git push origin main --tags")
print(f"")
print(f" 2. Update marketplace ref:")
print(f" cd ../claude-plugins")
print(f' sed -i \'\' \'/"name": "{name}"/,/"ref":/ s/"ref": "[^"]*"/"ref": "{tag}"/\' .claude-plugin/marketplace.json')
print(f" # Or manually: set \"ref\": \"{tag}\" for the {name} entry in .claude-plugin/marketplace.json")
print(f" git add -A && git commit -m 'Update {name} to {tag}' && git push")
print(f"")
print(f" 3. Install/update:")
print(f" claude plugin marketplace update")
print(f" claude plugin install {name}")
def main():
parser = argparse.ArgumentParser(
description="Show or bump the plugin version.",
)
sub = parser.add_subparsers(dest="command")
# Default (no subcommand) shows version
sub.add_parser("show", help="Show current version")
p_bump = sub.add_parser("bump", help="Bump version, commit, and tag")
level = p_bump.add_mutually_exclusive_group()
level.add_argument("--major", action="store_true", help="Bump major (X.0.0)")
level.add_argument("--minor", action="store_true", help="Bump minor (0.X.0)")
# patch is the default — no flag needed
p_bump.add_argument("--no-tag", action="store_true",
help="Commit but don't create a git tag")
args = parser.parse_args()
if args.command is None or args.command == "show":
cmd_show(args)
elif args.command == "bump":
cmd_bump(args)
if __name__ == "__main__":
main()