Initial commit: moon-household-budget
This commit is contained in:
94
release.py
Normal file
94
release.py
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/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))
|
||||
Reference in New Issue
Block a user