File size: 2,347 Bytes
be42be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7519dd3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
be42be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7519dd3
 
 
be42be3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
"""
StudyCraft release script -- runs CI, tags, and builds.

Usage:
    uv run python scripts/release.py 0.7.0
"""

import re
import subprocess
import sys
from pathlib import Path

RED = "\033[91m"
GREEN = "\033[92m"
RESET = "\033[0m"

PYPROJECT = Path("pyproject.toml")
INIT_PY = Path("src/studycraft/__init__.py")
WEB_PY = Path("src/studycraft/web.py")


def _bump_version(version: str) -> None:
    """Bump version in all files that contain it."""
    # pyproject.toml
    text = PYPROJECT.read_text(encoding="utf-8")
    PYPROJECT.write_text(
        re.sub(r'version = "[^"]+"', f'version = "{version}"', text),
        encoding="utf-8",
    )

    # __init__.py
    text = INIT_PY.read_text(encoding="utf-8")
    INIT_PY.write_text(
        re.sub(r'__version__ = "[^"]+"', f'__version__ = "{version}"', text),
        encoding="utf-8",
    )

    # web.py (FastAPI version)
    text = WEB_PY.read_text(encoding="utf-8")
    WEB_PY.write_text(
        re.sub(r'version="[^"]+"', f'version="{version}"', text),
        encoding="utf-8",
    )


def main() -> None:
    if len(sys.argv) != 2:
        print(f"Usage: uv run python scripts/release.py <version>")
        print(f"  e.g. uv run python scripts/release.py 0.7.0")
        sys.exit(1)

    version = sys.argv[1]
    if not re.match(r"^\d+\.\d+\.\d+$", version):
        print(f"{RED}Invalid version: {version} (expected X.Y.Z){RESET}")
        sys.exit(1)

    # 1. Run CI
    print(f"\n--- Running CI ---")
    r = subprocess.run([sys.executable, "scripts/ci.py"])
    if r.returncode != 0:
        print(f"{RED}CI failed, aborting release.{RESET}")
        sys.exit(1)

    # 2. Bump version in all files
    _bump_version(version)
    print(f"{GREEN}Version bumped to {version} (pyproject.toml, __init__.py, web.py){RESET}")

    # 3. Commit and tag
    subprocess.run(["git", "add", "-A"], check=True)
    subprocess.run(["git", "commit", "-m", f"release: v{version}"], check=True)
    subprocess.run(["git", "tag", f"v{version}"], check=True)
    print(f"{GREEN}Tagged v{version}{RESET}")

    # 4. Build
    subprocess.run(["uv", "build"], check=True)
    print(f"\n{GREEN}Release v{version} ready!{RESET}")
    print(f"  dist/ contains the built packages.")
    print(f"  Push with: git push && git push --tags")


if __name__ == "__main__":
    main()