aa8c9c6f12
release / release (push) Waiting to run
Reinstalling the package was slow because setup rebuilds pysim's prerequisites (pyscard compiles from source on Linux), while a clone updates with a plain `git pull`. - tools/update.py (+ update.sh / update.bat in the package, and the release workflow shipping them) updates a packaged install in place: it downloads the latest release package, extracts it (zip-slip guard, permission bits restored - zipfile drops them), replaces the app files over the app directory and re-installs the app into the existing .venv. The .venv and simple_lastrun.log are not in the package, so pysim and its prerequisites survive: seconds, not a rebuild. --check / --version / --zip (offline) / --no-pip / --force; the same version is a no-op. - CHANGELOG.md (Keep a Changelog, from the first packaged release; earlier history is the git log). The release workflow now uses the version's CHANGELOG section as the release body (tools/changelog_section.py, falling back to generated notes). - The READMEs document the update path and the `git clone --depth 1` option for the clone path; setup prints the update hint. - Version strings + the PWA cache bumped together (simple-v458). Verified: 1007 Python + 953 frontend; the release-package test covers the new files; the updater was exercised end to end (a v3.31.2 install with a real venv updated to the 3.32.0 package: files replaced, the venv marker kept, pip metadata 3.32.0, exec bits kept, a second run a no-op, --check correct).
39 lines
990 B
Python
39 lines
990 B
Python
#!/usr/bin/env python3
|
|
"""Print the CHANGELOG.md section of a version (the release notes body).
|
|
|
|
Usage: python tools/changelog_section.py X.Y.Z
|
|
Exits non-zero when the version has no section - the workflow then falls back
|
|
to generated notes.
|
|
"""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
CHANGELOG = Path(__file__).resolve().parent.parent / 'CHANGELOG.md'
|
|
|
|
|
|
def section(version):
|
|
text = CHANGELOG.read_text(encoding='utf-8')
|
|
pat = re.compile(r'^## \[%s\][^\n]*\n(.*?)(?=^## |\Z)'
|
|
% re.escape(version), re.M | re.S)
|
|
m = pat.search(text)
|
|
if not m:
|
|
return None
|
|
body = m.group(1).strip()
|
|
return body + '\n' if body else None
|
|
|
|
|
|
def main(argv):
|
|
if len(argv) != 2:
|
|
sys.exit('usage: changelog_section.py X.Y.Z')
|
|
body = section(argv[1])
|
|
if body is None:
|
|
sys.exit('error: no CHANGELOG.md section for %s' % argv[1])
|
|
sys.stdout.write(body)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv))
|