-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrelease
More file actions
executable file
·117 lines (98 loc) · 3.54 KB
/
Copy pathrelease
File metadata and controls
executable file
·117 lines (98 loc) · 3.54 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
#!/usr/bin/env python3
"""Release script: ./release <version> (e.g. ./release 0.0.5)"""
import re
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).parent
DATA = ROOT / "ai_prompt_auto_commit" / "data"
CLAUDE_SETTINGS = ROOT / ".claude" / "settings.json"
ASSISTANT_GUIDELINES = ROOT / ".github" / "assistant-guidelines.md"
def die(msg: str) -> None:
print(f"error: {msg}", file=sys.stderr)
sys.exit(1)
def replace_in_file(path: Path, pattern: str, replacement: str) -> None:
text = path.read_text(encoding="utf-8")
new_text, count = re.subn(pattern, replacement, text)
if count == 0:
die(f"pattern {pattern!r} not found in {path}")
path.write_text(new_text, encoding="utf-8")
print(f" {path.relative_to(ROOT)}: {count} replacement(s)")
def main() -> None:
if len(sys.argv) != 2:
die(f"usage: {sys.argv[0]} <version>")
version = sys.argv[1]
if version.startswith("v"):
die(f"version must not start with 'v', got: {version!r}")
# ensure we're on main
branch = subprocess.run(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=ROOT,
).stdout.strip()
if branch != "main":
die(f"must be on main branch, currently on: {branch!r}")
print(f"releasing {version}")
# pyproject.toml
replace_in_file(
ROOT / "pyproject.toml",
r'(?m)^version = ".*?"',
f'version = "{version}"',
)
# README.md — rev: v<old>
replace_in_file(
ROOT / "README.md",
r"rev: v[\d.]+",
f"rev: v{version}",
)
# data files
# claude_settings.json - "version": "0.0.8"
replace_in_file(
CLAUDE_SETTINGS,
r'"version"\s*:\s*"[\d.]+"',
f"\"version\": \"{version}\"",
)
# assistant-guidelines.md - version: "0.0.8"
replace_in_file(
ASSISTANT_GUIDELINES,
r"version: \"[\d.]+\"",
f"version: \"{version}\"",
)
# CHANGES.md — insert new version heading only if not already present
changes = ROOT / "CHANGES.md"
text = changes.read_text(encoding="utf-8")
if f"## v{version}" not in text:
new_section = f"## v{version}\n\n- (fill in)\n\n"
new_text = re.sub(r"(## v)", new_section + r"\1", text, count=1)
if new_text == text:
die("could not find a version heading in CHANGES.md to insert before")
changes.write_text(new_text, encoding="utf-8")
print(f" CHANGES.md: inserted v{version} section")
else:
print(f" CHANGES.md: v{version} already present, skipping")
# copy data files
print(" Updating bundled data files...")
shutil.copyfile(CLAUDE_SETTINGS, DATA / "claude_settings.json")
shutil.copyfile(ASSISTANT_GUIDELINES, DATA / "assistant-guidelines.md")
# tag and push only when the working tree is clean
status = subprocess.run(
["git", "status", "--porcelain"],
capture_output=True,
text=True,
check=True,
cwd=ROOT,
)
if status.stdout.strip():
print("\nworking tree has changes — commit them, then re-run to tag and push")
else:
tag = f"v{version}"
subprocess.run(["git", "push", "origin", "main"], check=True, cwd=ROOT)
subprocess.run(["git", "tag", "-a", tag, "-m", f"Release {tag}"], check=True, cwd=ROOT)
print(f" tagged {tag}")
subprocess.run(["git", "push", "origin", tag], check=True, cwd=ROOT)
print(f" pushed {tag}")
if __name__ == "__main__":
main()