From 0393867caa65d76c0edc547fcb6f3c6bb5f6a100 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <230051081+jmiller-moko@users.noreply.github.com> Date: Tue, 23 Dec 2025 16:41:53 -0600 Subject: [PATCH] Update version_branch.yml --- .github/workflows/version_branch.yml | 197 ++++++++++++++------------- 1 file changed, 102 insertions(+), 95 deletions(-) diff --git a/.github/workflows/version_branch.yml b/.github/workflows/version_branch.yml index dfb4a31..5de48a1 100644 --- a/.github/workflows/version_branch.yml +++ b/.github/workflows/version_branch.yml @@ -320,120 +320,127 @@ jobs: exit 2 fi - $1 import json - import os - import re - from pathlib import Path - from collections import defaultdict - from datetime import datetime, timezone + - name: Bump versions and update manifest dates (targeted, excluding .github) + run: | + source "$CI_HELPERS" + moko_init "Version bump" - new_version = (os.environ.get("NEW_VERSION") or "").strip() - version_text = (os.environ.get("VERSION_TEXT") or "").strip() - report_only = (os.environ.get("REPORT_ONLY") or "").strip().lower() == "true" - report_path = (os.environ.get("REPORT_PATH") or "").strip() + python3 - <<'PY' +import json +import os +import re +from pathlib import Path +from collections import defaultdict +from datetime import datetime, timezone - stamp = datetime.now(timezone.utc).strftime("%Y-%m-%d") - root = Path(".").resolve() +new_version = (os.environ.get("NEW_VERSION") or "").strip() +version_text = (os.environ.get("VERSION_TEXT") or "").strip() +report_only = (os.environ.get("REPORT_ONLY") or "").strip().lower() == "true" +report_path = (os.environ.get("REPORT_PATH") or "").strip() - header_re = re.compile(r"(?im)(VERSION[ \t]*:[ \t]*)([0-9]{2}[.][0-9]{2}[.][0-9]{2})") - manifest_marker_re = re.compile(r"(?is))([^<]*?)()") - xml_date_res = [ - re.compile(r"(?is)()([^<]*?)()"), - re.compile(r"(?is)()([^<]*?)()"), - re.compile(r"(?is)()([^<]*?)()"), - ] +stamp = datetime.now(timezone.utc).strftime("%Y-%m-%d") +root = Path(".").resolve() - skip_ext = { - ".json", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico", ".pdf", - ".zip", ".7z", ".tar", ".gz", ".woff", ".woff2", ".ttf", ".otf", - ".mp3", ".mp4", - } - skip_dirs = {".git", ".github", "node_modules", "vendor", ".venv", "dist", "build"} +# Use escape sequences only. Do not introduce literal tab characters. +header_re = re.compile(r"(?im)(VERSION[ \t]*:[ \t]*)([0-9]{2}[.][0-9]{2}[.][0-9]{2})") +manifest_marker_re = re.compile(r"(?is))([^<]*?)()") +xml_date_res = [ + re.compile(r"(?is)()([^<]*?)()"), + re.compile(r"(?is)()([^<]*?)()"), + re.compile(r"(?is)()([^<]*?)()"), +] - counters = defaultdict(int) - updated_files = [] - updated_manifests = [] - would_update_files = [] - would_update_manifests = [] +skip_ext = { + ".json", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico", ".pdf", + ".zip", ".7z", ".tar", ".gz", ".woff", ".woff2", ".ttf", ".otf", + ".mp3", ".mp4", +} +skip_dirs = {".git", ".github", "node_modules", "vendor", ".venv", "dist", "build"} - exclude_root = {"update.xml", "updates.xml"} +counters = defaultdict(int) +updated_files = [] +updated_manifests = [] +would_update_files = [] +would_update_manifests = [] - def should_skip(p: Path) -> bool: - if p.suffix.lower() in skip_ext: - counters["skipped_by_ext"] += 1 - return True - parts = {x.lower() for x in p.parts} - if any(d in parts for d in skip_dirs): - counters["skipped_by_dir"] += 1 - return True - return False +exclude_root = {"update.xml", "updates.xml"} - for p in root.rglob("*"): - if not p.is_file(): - continue - if should_skip(p): - continue +def should_skip(p: Path) -> bool: + if p.suffix.lower() in skip_ext: + counters["skipped_by_ext"] += 1 + return True + parts = {x.lower() for x in p.parts} + if any(d in parts for d in skip_dirs): + counters["skipped_by_dir"] += 1 + return True + return False - if p.parent == root and p.name.lower() in exclude_root: - counters["skipped_release_artifacts"] += 1 - continue +for p in root.rglob("*"): + if not p.is_file(): + continue + if should_skip(p): + continue - try: - original = p.read_text(encoding="utf-8", errors="replace") - except Exception: - counters["skipped_read_error"] += 1 - continue + if p.parent == root and p.name.lower() in exclude_root: + counters["skipped_release_artifacts"] += 1 + continue - text = original + try: + original = p.read_text(encoding="utf-8", errors="replace") + except Exception: + counters["skipped_read_error"] += 1 + continue - text, n1 = header_re.subn(lambda m: m.group(1) + new_version, text) - if n1: - counters["header_replacements"] += n1 + text = original - is_manifest = (p.suffix.lower() == ".xml" and manifest_marker_re.search(original) is not None) - if is_manifest: - text, n2 = xml_version_re.subn(lambda m: m.group(1) + new_version + m.group(3), text) - if n2: - counters["xml_version_replacements"] += n2 + text, n1 = header_re.subn(lambda m: m.group(1) + new_version, text) + if n1: + counters["header_replacements"] += n1 - for rx in xml_date_res: - text, n3 = rx.subn(lambda m: m.group(1) + stamp + m.group(3), text) - if n3: - counters["xml_date_replacements"] += n3 + is_manifest = (p.suffix.lower() == ".xml" and manifest_marker_re.search(original) is not None) + if is_manifest: + text, n2 = xml_version_re.subn(lambda m: m.group(1) + new_version + m.group(3), text) + if n2: + counters["xml_version_replacements"] += n2 - if text != original: - would_update_files.append(str(p)) - if is_manifest: - would_update_manifests.append(str(p)) + for rx in xml_date_res: + text, n3 = rx.subn(lambda m: m.group(1) + stamp + m.group(3), text) + if n3: + counters["xml_date_replacements"] += n3 - if not report_only: - p.write_text(text, encoding="utf-8") - updated_files.append(str(p)) - if is_manifest: - updated_manifests.append(str(p)) + if text != original: + would_update_files.append(str(p)) + if is_manifest: + would_update_manifests.append(str(p)) - report = { - "mode": "report_only" if report_only else "apply", - "new_version": new_version, - "version_text": version_text, - "stamp_utc": stamp, - "counters": dict(counters), - "updated_files": updated_files, - "updated_manifests": updated_manifests, - "would_update_files": would_update_files, - "would_update_manifests": would_update_manifests, - } + if not report_only: + p.write_text(text, encoding="utf-8") + updated_files.append(str(p)) + if is_manifest: + updated_manifests.append(str(p)) - Path(report_path).write_text(json.dumps(report, indent=2), encoding="utf-8") +report = { + "mode": "report_only" if report_only else "apply", + "new_version": new_version, + "version_text": version_text, + "stamp_utc": stamp, + "counters": dict(counters), + "updated_files": updated_files, + "updated_manifests": updated_manifests, + "would_update_files": would_update_files, + "would_update_manifests": would_update_manifests, +} - print("[INFO] Report written to:", report_path) - print("[INFO] Mode:", report["mode"]) - print("[INFO] Would update files:", len(would_update_files)) - print("[INFO] Would update manifests:", len(would_update_manifests)) - print("[INFO] Updated files:", len(updated_files)) - print("[INFO] Updated manifests:", len(updated_manifests)) - PY +Path(report_path).write_text(json.dumps(report, indent=2), encoding="utf-8") + +print("[INFO] Report written to:", report_path) +print("[INFO] Mode:", report["mode"]) +print("[INFO] Would update files:", len(would_update_files)) +print("[INFO] Would update manifests:", len(would_update_manifests)) +print("[INFO] Updated files:", len(updated_files)) +print("[INFO] Updated manifests:", len(updated_manifests)) +PY - name: Commit changes if: ${{ env.REPORT_ONLY != 'true' }}