95 lines
2.6 KiB
Python
95 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Cut a release for Moon Household Budget.
|
|
|
|
Usage:
|
|
python release.py <version> "<change 1>" "<change 2>" ... \\
|
|
[--title "Short title"] [--date YYYY-MM-DD]
|
|
|
|
Prepends a new entry to changelog.json (the single source of truth that drives
|
|
__version__, the footer version chip, and the /changelog page) and regenerates
|
|
CHANGELOG.md to match.
|
|
|
|
Versioning: semver-ish — bump the patch (0.1.0 -> 0.1.1) for fixes, the minor
|
|
(0.1.0 -> 0.2.0) for new features. Run this for EVERY deploy (see CLAUDE.md).
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
from datetime import date
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
CHANGELOG_JSON = os.path.join(HERE, "changelog.json")
|
|
CHANGELOG_MD = os.path.join(HERE, "CHANGELOG.md")
|
|
|
|
|
|
def load():
|
|
try:
|
|
with open(CHANGELOG_JSON) as f:
|
|
return json.load(f)
|
|
except (OSError, json.JSONDecodeError):
|
|
return []
|
|
|
|
|
|
def render_md(data):
|
|
lines = [
|
|
"# Changelog",
|
|
"",
|
|
"All notable changes to Moon Household Budget. Newest first.",
|
|
"Generated from changelog.json by release.py — do not edit by hand.",
|
|
"",
|
|
]
|
|
for rel in data:
|
|
head = f"## {rel['version']} — {rel.get('date', '')}"
|
|
if rel.get("title"):
|
|
head += f" — {rel['title']}"
|
|
lines += [head, ""]
|
|
lines += [f"- {c}" for c in rel.get("changes", [])]
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def main(argv):
|
|
if len(argv) < 2:
|
|
print(__doc__)
|
|
return 1
|
|
|
|
version = argv[1]
|
|
title, rel_date, changes = "", date.today().isoformat(), []
|
|
i = 2
|
|
while i < len(argv):
|
|
if argv[i] == "--title" and i + 1 < len(argv):
|
|
title = argv[i + 1]; i += 2
|
|
elif argv[i] == "--date" and i + 1 < len(argv):
|
|
rel_date = argv[i + 1]; i += 2
|
|
else:
|
|
changes.append(argv[i]); i += 1
|
|
|
|
if not changes:
|
|
print("error: provide at least one change bullet")
|
|
return 1
|
|
|
|
data = load()
|
|
if data and data[0].get("version") == version:
|
|
print(f"error: version {version} is already the latest entry")
|
|
return 1
|
|
|
|
entry = {"version": version, "date": rel_date}
|
|
if title:
|
|
entry["title"] = title
|
|
entry["changes"] = changes
|
|
data.insert(0, entry)
|
|
|
|
with open(CHANGELOG_JSON, "w") as f:
|
|
json.dump(data, f, indent=2)
|
|
f.write("\n")
|
|
with open(CHANGELOG_MD, "w") as f:
|
|
f.write(render_md(data))
|
|
|
|
print(f"released v{version} ({rel_date}) with {len(changes)} change(s)")
|
|
print(" -> changelog.json + CHANGELOG.md updated. Now commit + deploy.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|