From dd259313e51a6c7d6000977dcb6b5103f25eafd6 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:16:58 +0200 Subject: [PATCH 01/16] chore: ignore docs/superpowers/ (local specs and plans) --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 44954f5..ea0d85b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,7 @@ yarn-error.log* # Local Typesense dev server (see docker/typesense) /docker/typesense/certs -/docker/typesense/data \ No newline at end of file +/docker/typesense/data + +# Local superpowers specs/plans (not committed) +docs/superpowers/ From e93805dbb79109212844117a9648a9218824155d Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:47:02 +0200 Subject: [PATCH 02/16] refactor: expose run() in update-spring-boot-version-table for import --- .devenv/scripts/update-spring-boot-version-table.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.devenv/scripts/update-spring-boot-version-table.py b/.devenv/scripts/update-spring-boot-version-table.py index c8d79ec..0c1d84c 100755 --- a/.devenv/scripts/update-spring-boot-version-table.py +++ b/.devenv/scripts/update-spring-boot-version-table.py @@ -195,7 +195,7 @@ def fetch_new_rows(new_versions: set[tuple[int, int, int]]) -> list[tuple[str, s return new_rows -def main(dry_run: bool = False) -> None: +def run(dry_run: bool = False) -> None: script_dir = os.path.dirname(os.path.abspath(__file__)) repo_root = os.path.abspath(os.path.join(script_dir, "..", "..")) docs_path = os.path.join(repo_root, DOCS_FILE) @@ -244,5 +244,9 @@ def main(dry_run: bool = False) -> None: print(f"\nUpdated {DOCS_FILE}") +def main() -> None: + run(dry_run="--dry-run" in sys.argv) + + if __name__ == "__main__": - main(dry_run="--dry-run" in sys.argv) + main() From a31c2e639c1c94960972707e823c1ae11c3d3248 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:50:01 +0200 Subject: [PATCH 03/16] refactor: expose run() in update-quarkus-version-table for import --- .devenv/scripts/update-quarkus-version-table.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.devenv/scripts/update-quarkus-version-table.py b/.devenv/scripts/update-quarkus-version-table.py index 61591b8..b122880 100755 --- a/.devenv/scripts/update-quarkus-version-table.py +++ b/.devenv/scripts/update-quarkus-version-table.py @@ -242,7 +242,7 @@ def fetch_new_rows( return new_rows -def main(dry_run: bool = False) -> None: +def run(dry_run: bool = False) -> None: script_dir = os.path.dirname(os.path.abspath(__file__)) repo_root = os.path.abspath(os.path.join(script_dir, "..", "..")) docs_path = os.path.join(repo_root, DOCS_FILE) @@ -292,5 +292,9 @@ def main(dry_run: bool = False) -> None: print(f"\nUpdated {DOCS_FILE}") +def main() -> None: + run(dry_run="--dry-run" in sys.argv) + + if __name__ == "__main__": - main(dry_run="--dry-run" in sys.argv) + main() From d692bc1a1b642ff4a2eb49926df1ec745a011074 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:53:31 +0200 Subject: [PATCH 04/16] feat: add update-versions.py skeleton with GitHub/SBOM helpers Co-Authored-By: Claude Sonnet 4.6 --- .devenv/scripts/tests/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 179 bytes ...date_versions.cpython-310-pytest-9.0.3.pyc | Bin 0 -> 3382 bytes .devenv/scripts/tests/test_update_versions.py | 59 ++++++ .devenv/scripts/update_versions.py | 174 ++++++++++++++++++ 5 files changed, 233 insertions(+) create mode 100644 .devenv/scripts/tests/__init__.py create mode 100644 .devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc create mode 100644 .devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc create mode 100644 .devenv/scripts/tests/test_update_versions.py create mode 100644 .devenv/scripts/update_versions.py diff --git a/.devenv/scripts/tests/__init__.py b/.devenv/scripts/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/.devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc b/.devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a95fb6b53bdfd235d592c4e334a31a34b99e9b0 GIT binary patch literal 179 zcmd1j<>g`k0;gt~ED-$|L?8o3AjbiSi&=m~3PUi1CZpdhj9;i<65o q3rdRhOHzx0WPE&PUS>&ryk0@&Ee@O9{FKt1R6CG;#Y{kgg#iHiRxP#w literal 0 HcmV?d00001 diff --git a/.devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc b/.devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f4dd9193d2ed2fb885abbd22d7385f4751ddcc2 GIT binary patch literal 3382 zcmb7G&2!U66xT|!tvF5s!TI2;P)ZA?jSPX(DbvzW2u!Dt&OqCPE<1{M<0#QrcV#Eh zq^Iy_T1!JWD&5)}D?S#^3mH z{Bhu80sitYAk1JSG(4i;W@MQLF(TV5kz%IomGw-;tLV4mIq){ak*Mlbqfu{^7`(Dp z+Z$sBA7|DMf$_v(bcUbZC(PbA_syQXN$(shu`;VLhmGu7ZNjR%rdMa9tj5OJIGfnD z*co<~P2#9+2E?0sX0UUt{@P%5?yODkSl$e9rr0!arhA-O;LNaD;LP?o=NWlrG|vA6 z78*+pQ;odv+d=C^(pp!g)X!S0%1mT#x^7VvEKB8sW|MFFQ5tf$l|;?qn;Vw0V?W}m)=J`x#~IDGQts84MY18e zpe)&l!^CH_Bf(n~7+MdrJkQRprQ zF>9V=%=u}sa1V}}9~_m}hb_uWdQ}T!aQw00V*&p1DGU1f|gJT>1 zkKr#b0LhGPLdmwVXJ*!(y$@h0QWXv}mvZnKc&$-VwWp7MUZgJXB`pK zt{--|8pT+NZ1IndA1brcRTtq@8fpb;KQE{#R6Q`2EqS=&IT7R{>UUs>Iw*3u-24s1 z$mV*snnbesgm-zEq!EO^3C0W(tjUsA2f0N;x(wFE-KK1bAkAbGy;4wm(kJPbs^c`3 z8LXAGOH;vDg3TH91v;f{)=AzN=3sZ&zSA9h6@)R;hB~opf_n{cFUib33*2iB+-olZ z^zOJ{yLUwe*5@TXZrEZRzQhEQGf2)NnM8taD##R!)T~yj2!*5wonH7a!K^l@h6c@@ zZqSguOO3K}s0JaWs!C~;uujNfT%!~tjPRsXU=E9EBj^WVb+CguVzz7C|12?lt0ZFm;5mN{ppg4<9 zk$=L@8`{o(hQ+Xqt|Wr?Bpz9O6ZXDA^o^5ol0W=Ei$5&v!?r{7J_h2P0VbGlFdudpgt_6KajUZ59o7o9vY|U*8J>de99@ccB^F z7FYrVRzZlqZUwpv+(PbEB-k0enF4>b<%c0>G>KcBZa~Y2%*D#%RdjcaT0=|F9qrW> z*edC=4_!D*-t{QmSmiN|lZ*zj_WFI0sq?99j*}VzH$OSe%^xFnNP>TfCZaoqhR;z^ zIZE&b%--oMgbA*@3UV74l(XCkLa3=y)fUn%I`}$I(=9aHEgT1TK3DJ!5oBDA3|Okt z=T%{|_L47@y(W`bS#nD%rxOPm^1ZSC$VE>JY%^MIWy9@yRh2;lxD#Omg{x^IGH9Uo zS`x&n!UCbM#L#6|0_?2b#EHx+iq9B|yb44)=/@?type=jar +Matching uses prefix: pkg:maven//@ + +Usage: + python3 .devenv/scripts/update-versions.py [--dry-run] + +Environment variables: + GITHUB_TOKEN Optional GitHub personal-access token. +""" + +import io +import json +import os +import re +import sys +import urllib.error +import urllib.request +import zipfile +from dataclasses import dataclass +from pathlib import Path +from typing import Optional + +REPO = "operaton/operaton" +GITHUB_API_BASE = "https://api.github.com" +MAVEN_CENTRAL_SEARCH = "https://search.maven.org/solrsearch/select" + +SCRIPT_DIR = Path(__file__).parent +REPO_ROOT = (SCRIPT_DIR / ".." / "..").resolve() +DOCS_DIR = REPO_ROOT / "docs" +ARCHIVE_DIR = DOCS_DIR / "get-started" / "archive" + + +# ── GitHub API ──────────────────────────────────────────────────────────────── + +def _github_get(path: str) -> object: + token = os.environ.get("GITHUB_TOKEN", "") + url = f"{GITHUB_API_BASE}{path}" + req = urllib.request.Request(url) + req.add_header("Accept", "application/vnd.github+json") + req.add_header("X-GitHub-Api-Version", "2022-11-28") + if token: + req.add_header("Authorization", f"Bearer {token}") + try: + with urllib.request.urlopen(req) as resp: + return json.loads(resp.read().decode()) + except urllib.error.HTTPError as exc: + print(f"GitHub API error for {url}: {exc.code} {exc.reason}", file=sys.stderr) + raise + + +def get_latest_operaton_release() -> str: + """Return latest release version string without 'v' prefix, e.g. '2.2.0'.""" + data = _github_get(f"/repos/{REPO}/releases/latest") + tag = data["tag_name"] + return tag.lstrip("v") + + +# ── SBOM ────────────────────────────────────────────────────────────────────── + +def _download_bytes(url: str) -> bytes: + token = os.environ.get("GITHUB_TOKEN", "") + req = urllib.request.Request(url) + if token: + req.add_header("Authorization", f"Bearer {token}") + with urllib.request.urlopen(req) as resp: + return resp.read() + + +def get_sbom(release_data: dict) -> Optional[dict]: + """Extract sbom.cdx.json from the distribution zip in release assets. + + The distribution zip is named operaton-bpm-X.Y.Z.zip. The SBOM is at + sbom.cdx.json inside the zip root. Returns None if not found. + """ + for asset in release_data.get("assets", []): + name = asset.get("name", "") + if name.startswith("operaton-bpm-") and name.endswith(".zip"): + print(f"Downloading distribution zip for SBOM: {name}") + raw = _download_bytes(asset["browser_download_url"]) + with zipfile.ZipFile(io.BytesIO(raw)) as zf: + # sbom.cdx.json may be at root or inside a top-level directory + for entry in zf.namelist(): + if entry.endswith("sbom.cdx.json"): + with zf.open(entry) as f: + return json.loads(f.read().decode()) + print("sbom.cdx.json not found inside zip — will use Maven Central only.") + return None + print("No operaton-bpm-*.zip asset found — will use Maven Central only.") + return None + + +def get_version_from_sbom(sbom: Optional[dict], group_id: str, artifact_id: str) -> Optional[str]: + """Look up a component version in a CycloneDX SBOM by groupId:artifactId. + + Matches on purl prefix 'pkg:maven//@'. + The ?type=... suffix in actual purls is handled by prefix matching. + """ + if not sbom: + return None + purl_prefix = f"pkg:maven/{group_id}/{artifact_id}@" + for component in sbom.get("components", []): + purl = component.get("purl", "") + if purl.startswith(purl_prefix): + return component.get("version") + return None + + +# ── Maven Central ───────────────────────────────────────────────────────────── + +def get_version_from_maven_central(group_id: str, artifact_id: str) -> str: + """Return the latest release version for a Maven artifact from Maven Central.""" + params = f"q=g:{group_id}+AND+a:{artifact_id}&rows=1&wt=json&core=gav" + url = f"{MAVEN_CENTRAL_SEARCH}?{params}" + req = urllib.request.Request(url) + try: + with urllib.request.urlopen(req) as resp: + data = json.loads(resp.read().decode()) + docs = data["response"]["docs"] + if not docs: + raise RuntimeError(f"No results from Maven Central for {group_id}:{artifact_id}") + return docs[0]["v"] + except urllib.error.HTTPError as exc: + print(f"Maven Central error for {group_id}:{artifact_id}: {exc.code}", file=sys.stderr) + raise + + +def resolve_version(sbom: Optional[dict], group_id: str, artifact_id: str) -> str: + """Return version from SBOM if present, else from Maven Central.""" + v = get_version_from_sbom(sbom, group_id, artifact_id) + if v: + return v + return get_version_from_maven_central(group_id, artifact_id) + + +# ── Placeholder for doc replacement (Task 5) ───────────────────────────────── + +@dataclass +class Replacement: + description: str + pattern: re.Pattern + new_version: str + + +def _build_replacements(operaton_version: str, versions: dict) -> list: + raise NotImplementedError("Implemented in Task 5") + + +def _apply_replacements_to_text(text: str, replacements: list) -> tuple: + raise NotImplementedError("Implemented in Task 5") + + +def update_docs(replacements: list, dry_run: bool = False) -> int: + raise NotImplementedError("Implemented in Task 5") + + +# ── Orchestration (Task 6) ──────────────────────────────────────────────────── + +def main(dry_run: bool = False) -> None: + raise NotImplementedError("Implemented in Task 6") + + +if __name__ == "__main__": + main(dry_run="--dry-run" in sys.argv) From 08f963b6eda3ec460d4e31a68c0d602e80d855a0 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:56:24 +0200 Subject: [PATCH 05/16] fix: stream zip to tempfile, use artifact core for Maven Central, strengthen test --- .devenv/scripts/tests/test_update_versions.py | 4 +- .devenv/scripts/update_versions.py | 48 +++++++++++-------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/.devenv/scripts/tests/test_update_versions.py b/.devenv/scripts/tests/test_update_versions.py index 8206601..a43de9b 100644 --- a/.devenv/scripts/tests/test_update_versions.py +++ b/.devenv/scripts/tests/test_update_versions.py @@ -47,9 +47,11 @@ def test_returns_none_for_none_sbom(self): class TestResolveVersion(unittest.TestCase): - def test_prefers_sbom_over_maven_central(self): + @patch("update_versions.get_version_from_maven_central") + def test_prefers_sbom(self, mock_mc): version = uv.resolve_version(FAKE_SBOM, "org.slf4j", "slf4j-simple") self.assertEqual(version, "2.0.9") + mock_mc.assert_not_called() @patch("update_versions.get_version_from_maven_central") def test_falls_back_to_maven_central_when_not_in_sbom(self, mock_mc): diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index 82be213..bc0c2e7 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -19,11 +19,12 @@ GITHUB_TOKEN Optional GitHub personal-access token. """ -import io import json import os import re +import shutil import sys +import tempfile import urllib.error import urllib.request import zipfile @@ -68,33 +69,40 @@ def get_latest_operaton_release() -> str: # ── SBOM ────────────────────────────────────────────────────────────────────── -def _download_bytes(url: str) -> bytes: - token = os.environ.get("GITHUB_TOKEN", "") - req = urllib.request.Request(url) - if token: - req.add_header("Authorization", f"Bearer {token}") - with urllib.request.urlopen(req) as resp: - return resp.read() - - def get_sbom(release_data: dict) -> Optional[dict]: """Extract sbom.cdx.json from the distribution zip in release assets. The distribution zip is named operaton-bpm-X.Y.Z.zip. The SBOM is at sbom.cdx.json inside the zip root. Returns None if not found. + + Streams the zip to a temporary file to avoid loading large files into memory. """ for asset in release_data.get("assets", []): name = asset.get("name", "") if name.startswith("operaton-bpm-") and name.endswith(".zip"): print(f"Downloading distribution zip for SBOM: {name}") - raw = _download_bytes(asset["browser_download_url"]) - with zipfile.ZipFile(io.BytesIO(raw)) as zf: - # sbom.cdx.json may be at root or inside a top-level directory - for entry in zf.namelist(): - if entry.endswith("sbom.cdx.json"): - with zf.open(entry) as f: - return json.loads(f.read().decode()) - print("sbom.cdx.json not found inside zip — will use Maven Central only.") + token = os.environ.get("GITHUB_TOKEN", "") + req = urllib.request.Request(asset["browser_download_url"]) + if token: + req.add_header("Authorization", f"Bearer {token}") + try: + with urllib.request.urlopen(req) as resp, \ + tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp: + shutil.copyfileobj(resp, tmp) + tmp_path = tmp.name + except urllib.error.HTTPError as exc: + print(f"Failed to download zip {name}: {exc.code} {exc.reason}", file=sys.stderr) + return None + try: + with zipfile.ZipFile(tmp_path) as zf: + # sbom.cdx.json may be at root or inside a top-level directory + for entry in zf.namelist(): + if entry.endswith("sbom.cdx.json"): + with zf.open(entry) as f: + return json.loads(f.read().decode()) + print("sbom.cdx.json not found inside zip — will use Maven Central only.") + finally: + os.unlink(tmp_path) return None print("No operaton-bpm-*.zip asset found — will use Maven Central only.") return None @@ -120,7 +128,7 @@ def get_version_from_sbom(sbom: Optional[dict], group_id: str, artifact_id: str) def get_version_from_maven_central(group_id: str, artifact_id: str) -> str: """Return the latest release version for a Maven artifact from Maven Central.""" - params = f"q=g:{group_id}+AND+a:{artifact_id}&rows=1&wt=json&core=gav" + params = f"q=g:{group_id}+AND+a:{artifact_id}&rows=1&wt=json" url = f"{MAVEN_CENTRAL_SEARCH}?{params}" req = urllib.request.Request(url) try: @@ -129,7 +137,7 @@ def get_version_from_maven_central(group_id: str, artifact_id: str) -> str: docs = data["response"]["docs"] if not docs: raise RuntimeError(f"No results from Maven Central for {group_id}:{artifact_id}") - return docs[0]["v"] + return docs[0]["latestVersion"] except urllib.error.HTTPError as exc: print(f"Maven Central error for {group_id}:{artifact_id}: {exc.code}", file=sys.stderr) raise From 69b6ae5f1d7fc9a8defbecadffd588e9b5ca35a3 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 20:58:42 +0200 Subject: [PATCH 06/16] feat: implement Replacement dataclass and update_docs with archive exclusion Co-Authored-By: Claude Sonnet 4.6 --- .devenv/scripts/tests/test_update_versions.py | 102 +++++++++++++----- .devenv/scripts/update_versions.py | 87 +++++++++++++-- 2 files changed, 154 insertions(+), 35 deletions(-) diff --git a/.devenv/scripts/tests/test_update_versions.py b/.devenv/scripts/tests/test_update_versions.py index a43de9b..481076a 100644 --- a/.devenv/scripts/tests/test_update_versions.py +++ b/.devenv/scripts/tests/test_update_versions.py @@ -1,61 +1,113 @@ import json import sys +import tempfile import unittest -from unittest.mock import MagicMock, patch +from pathlib import Path +from unittest.mock import patch -sys.path.insert(0, __import__("os").path.join(__import__("os").path.dirname(__file__), "..")) +sys.path.insert(0, str(Path(__file__).parent.parent)) import update_versions as uv -FAKE_RELEASE = {"tag_name": "v2.2.0", "assets": [ - {"name": "operaton-bpm-2.2.0.zip", - "content_type": "application/zip", - "browser_download_url": "https://example.com/operaton-bpm-2.2.0.zip"}, -]} - FAKE_SBOM = {"components": [ - {"purl": "pkg:maven/org.slf4j/slf4j-simple@2.0.9?type=jar", "name": "slf4j-simple", "version": "2.0.9"}, - {"purl": "pkg:maven/jakarta.xml.bind/jakarta.xml.bind-api@4.0.2?type=jar", "name": "jakarta.xml.bind-api", "version": "4.0.2"}, + {"purl": "pkg:maven/org.slf4j/slf4j-simple@2.0.9?type=jar", "version": "2.0.9"}, + {"purl": "pkg:maven/jakarta.xml.bind/jakarta.xml.bind-api@4.0.2?type=jar", "version": "4.0.2"}, ]} class TestGetLatestRelease(unittest.TestCase): @patch("update_versions._github_get") def test_strips_v_prefix(self, mock_get): - mock_get.return_value = FAKE_RELEASE + mock_get.return_value = {"tag_name": "v2.2.0", "assets": []} self.assertEqual(uv.get_latest_operaton_release(), "2.2.0") @patch("update_versions._github_get") - def test_returns_tag_version(self, mock_get): + def test_strips_v_prefix_single_digit(self, mock_get): mock_get.return_value = {"tag_name": "v1.5.3", "assets": []} self.assertEqual(uv.get_latest_operaton_release(), "1.5.3") class TestGetVersionFromSbom(unittest.TestCase): def test_finds_existing_component(self): - # purl has ?type=jar suffix — prefix matching must handle this - version = uv.get_version_from_sbom(FAKE_SBOM, "org.slf4j", "slf4j-simple") - self.assertEqual(version, "2.0.9") + self.assertEqual(uv.get_version_from_sbom(FAKE_SBOM, "org.slf4j", "slf4j-simple"), "2.0.9") - def test_returns_none_for_missing_component(self): - version = uv.get_version_from_sbom(FAKE_SBOM, "com.example", "missing") - self.assertIsNone(version) + def test_returns_none_for_missing(self): + self.assertIsNone(uv.get_version_from_sbom(FAKE_SBOM, "com.example", "missing")) def test_returns_none_for_none_sbom(self): - version = uv.get_version_from_sbom(None, "org.slf4j", "slf4j-simple") - self.assertIsNone(version) + self.assertIsNone(uv.get_version_from_sbom(None, "org.slf4j", "slf4j-simple")) class TestResolveVersion(unittest.TestCase): @patch("update_versions.get_version_from_maven_central") def test_prefers_sbom(self, mock_mc): - version = uv.resolve_version(FAKE_SBOM, "org.slf4j", "slf4j-simple") - self.assertEqual(version, "2.0.9") + self.assertEqual(uv.resolve_version(FAKE_SBOM, "org.slf4j", "slf4j-simple"), "2.0.9") mock_mc.assert_not_called() @patch("update_versions.get_version_from_maven_central") - def test_falls_back_to_maven_central_when_not_in_sbom(self, mock_mc): + def test_falls_back_to_maven_central(self, mock_mc): mock_mc.return_value = "3.5.0" - version = uv.resolve_version(FAKE_SBOM, "com.example", "missing") - self.assertEqual(version, "3.5.0") + self.assertEqual(uv.resolve_version(FAKE_SBOM, "com.example", "missing"), "3.5.0") mock_mc.assert_called_once_with("com.example", "missing") + + +class TestApplyReplacements(unittest.TestCase): + def _make_rep(self, desc, pattern_str, version): + import re + return uv.Replacement(desc, re.compile(pattern_str), version) + + def test_replaces_operaton_version(self): + text = "1.0.0" + rep = self._make_rep( + "test", + r"()\d+\.\d+\.\d+()", + "2.2.0", + ) + result, changes = uv._apply_replacements_to_text(text, [rep]) + self.assertEqual(result, "2.2.0") + self.assertEqual(changes, ["test"]) + + def test_no_change_when_already_current(self): + text = "2.2.0" + rep = self._make_rep( + "test", + r"()\d+\.\d+\.\d+()", + "2.2.0", + ) + result, changes = uv._apply_replacements_to_text(text, [rep]) + self.assertEqual(result, text) + self.assertEqual(changes, []) + + def test_skips_archive_directory(self): + """update_docs must not touch files under docs/get-started/archive/.""" + with tempfile.TemporaryDirectory() as tmp: + tmp_path = Path(tmp) + archive = tmp_path / "docs" / "get-started" / "archive" + archive.mkdir(parents=True) + active = tmp_path / "docs" / "get-started" + active.mkdir(parents=True, exist_ok=True) + + archive_file = archive / "old.md" + archive_file.write_text("1.0.0") + active_file = active / "index.md" + active_file.write_text("1.0.0") + + import re + reps = [uv.Replacement( + "test", + re.compile(r"()\d+\.\d+\.\d+()"), + "2.2.0", + )] + + orig_docs = uv.DOCS_DIR + orig_archive = uv.ARCHIVE_DIR + uv.DOCS_DIR = tmp_path / "docs" + uv.ARCHIVE_DIR = tmp_path / "docs" / "get-started" / "archive" + try: + uv.update_docs(reps, dry_run=False) + finally: + uv.DOCS_DIR = orig_docs + uv.ARCHIVE_DIR = orig_archive + + self.assertEqual(archive_file.read_text(), "1.0.0") + self.assertEqual(active_file.read_text(), "2.2.0") diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index bc0c2e7..11f7978 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -160,16 +160,83 @@ class Replacement: new_version: str -def _build_replacements(operaton_version: str, versions: dict) -> list: - raise NotImplementedError("Implemented in Task 5") - - -def _apply_replacements_to_text(text: str, replacements: list) -> tuple: - raise NotImplementedError("Implemented in Task 5") - - -def update_docs(replacements: list, dry_run: bool = False) -> int: - raise NotImplementedError("Implemented in Task 5") +def _build_replacements(operaton_version: str, versions: dict[str, str]) -> list["Replacement"]: + """Build replacement list from pre-resolved version dict.""" + ov = operaton_version + return [ + Replacement(" property", + re.compile(r"()\d+\.\d+\.\d+()"), ov), + Replacement("operaton-bom ", + re.compile(r"(operaton-bom\s*)\d+\.\d+\.\d+()", re.DOTALL), ov), + Replacement("operaton-engine-dmn-bom ", + re.compile(r"(operaton-engine-dmn-bom\s*)\d+\.\d+\.\d+()", re.DOTALL), ov), + Replacement("operaton-bpm-junit5 ", + re.compile(r"(operaton-bpm-junit5\s*)\d+\.\d+\.\d+()", re.DOTALL), ov), + Replacement(" property", + re.compile(r"()\d+\.\d+\.\d+()"), ov), + Replacement("GitHub tree link /tree/vX.Y.Z/", + re.compile(r"(github\.com/operaton/operaton/tree/v)\d+\.\d+\.\d+(/)"), ov), + Replacement("slf4j-simple ", + re.compile(r"(slf4j-simple\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["slf4j-simple"]), + Replacement("jakarta.xml.bind-api ", + re.compile(r"(jakarta\.xml\.bind-api\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["jakarta.xml.bind-api"]), + Replacement("javax.servlet-api ", + re.compile(r"(javax\.servlet-api\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["javax.servlet-api"]), + Replacement("maven-compiler-plugin ", + re.compile(r"(maven-compiler-plugin\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["maven-compiler-plugin"]), + Replacement("maven-war-plugin ", + re.compile(r"(maven-war-plugin\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["maven-war-plugin"]), + Replacement("bootstrap webjars ", + re.compile(r"(bootstrap\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["bootstrap"]), + Replacement("uuid-creator ", + re.compile(r"(uuid-creator\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["uuid-creator"]), + Replacement("logback-classic ", + re.compile(r"(logback-classic\s*)\d+[\d.]+\d+()", re.DOTALL), + versions["logback-classic"]), + Replacement(" property", + re.compile(r"()\d+[\d.]+\d+()"), + versions["spring-boot"]), + ] + + +def _apply_replacements_to_text(text: str, replacements: list["Replacement"]) -> tuple[str, list[str]]: + """Apply all replacements to text. Returns (new_text, list_of_descriptions_that_changed).""" + changes = [] + for rep in replacements: + new_text = rep.pattern.sub(lambda m, v=rep.new_version: m.group(1) + v + m.group(2), text) + if new_text != text: + changes.append(rep.description) + text = new_text + return text, changes + + +def update_docs(replacements: list["Replacement"], dry_run: bool = False) -> int: + """Walk active docs, apply replacements. Returns count of changed files.""" + changed = 0 + for md_file in sorted(DOCS_DIR.rglob("*.md")): + if md_file.is_relative_to(ARCHIVE_DIR): + continue + original = md_file.read_text(encoding="utf-8") + updated, changes = _apply_replacements_to_text(original, replacements) + if updated != original: + changed += 1 + try: + rel = md_file.relative_to(REPO_ROOT) + except ValueError: + rel = md_file + if dry_run: + print(f" [dry-run] Would update {rel}: {', '.join(changes)}") + else: + md_file.write_text(updated, encoding="utf-8") + print(f" Updated {rel}: {', '.join(changes)}") + return changed # ── Orchestration (Task 6) ──────────────────────────────────────────────────── From ecbf4057c7a6376750c4f3df595c9018270b83f6 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 21:03:15 +0200 Subject: [PATCH 07/16] fix: tighten third-party version regex to disallow malformed version strings --- .devenv/scripts/update_versions.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index 11f7978..ac08a82 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -177,31 +177,31 @@ def _build_replacements(operaton_version: str, versions: dict[str, str]) -> list Replacement("GitHub tree link /tree/vX.Y.Z/", re.compile(r"(github\.com/operaton/operaton/tree/v)\d+\.\d+\.\d+(/)"), ov), Replacement("slf4j-simple ", - re.compile(r"(slf4j-simple\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(slf4j-simple\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["slf4j-simple"]), Replacement("jakarta.xml.bind-api ", - re.compile(r"(jakarta\.xml\.bind-api\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(jakarta\.xml\.bind-api\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["jakarta.xml.bind-api"]), Replacement("javax.servlet-api ", - re.compile(r"(javax\.servlet-api\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(javax\.servlet-api\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["javax.servlet-api"]), Replacement("maven-compiler-plugin ", - re.compile(r"(maven-compiler-plugin\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(maven-compiler-plugin\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["maven-compiler-plugin"]), Replacement("maven-war-plugin ", - re.compile(r"(maven-war-plugin\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(maven-war-plugin\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["maven-war-plugin"]), Replacement("bootstrap webjars ", - re.compile(r"(bootstrap\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(bootstrap\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["bootstrap"]), Replacement("uuid-creator ", - re.compile(r"(uuid-creator\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(uuid-creator\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["uuid-creator"]), Replacement("logback-classic ", - re.compile(r"(logback-classic\s*)\d+[\d.]+\d+()", re.DOTALL), + re.compile(r"(logback-classic\s*)\d+(?:\.\d+)+()", re.DOTALL), versions["logback-classic"]), Replacement(" property", - re.compile(r"()\d+[\d.]+\d+()"), + re.compile(r"()\d+(?:\.\d+)+()"), versions["spring-boot"]), ] From ec1f2133a544b83a8f1d3928a9d696d1d45f95ef Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 21:04:20 +0200 Subject: [PATCH 08/16] feat: wire main() with THIRD_PARTY_ARTIFACTS registry and module imports Co-Authored-By: Claude Sonnet 4.6 --- .devenv/scripts/update_versions.py | 45 +++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index ac08a82..7f4415d 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -241,8 +241,51 @@ def update_docs(replacements: list["Replacement"], dry_run: bool = False) -> int # ── Orchestration (Task 6) ──────────────────────────────────────────────────── +THIRD_PARTY_ARTIFACTS = [ + ("slf4j-simple", "org.slf4j", "slf4j-simple"), + ("jakarta.xml.bind-api", "jakarta.xml.bind", "jakarta.xml.bind-api"), + ("javax.servlet-api", "javax.servlet", "javax.servlet-api"), + ("maven-compiler-plugin", "org.apache.maven.plugins", "maven-compiler-plugin"), + ("maven-war-plugin", "org.apache.maven.plugins", "maven-war-plugin"), + ("bootstrap", "org.webjars", "bootstrap"), + ("uuid-creator", "com.github.f4b6a3", "uuid-creator"), + ("logback-classic", "ch.qos.logback", "logback-classic"), + ("spring-boot", "org.springframework.boot", "spring-boot"), +] + + def main(dry_run: bool = False) -> None: - raise NotImplementedError("Implemented in Task 6") + print("Fetching latest Operaton release…") + release_data = _github_get(f"/repos/{REPO}/releases/latest") + operaton_version = release_data["tag_name"].lstrip("v") + print(f"Latest Operaton release: {operaton_version}") + + print("Fetching SBOM…") + sbom = get_sbom(release_data) + + print("Resolving third-party versions…") + third_party_versions: dict[str, str] = {} + for key, group_id, artifact_id in THIRD_PARTY_ARTIFACTS: + v = resolve_version(sbom, group_id, artifact_id) + print(f" {group_id}:{artifact_id} → {v}") + third_party_versions[key] = v + + replacements = _build_replacements(operaton_version, third_party_versions) + + print(f"\nUpdating docs (dry_run={dry_run})…") + changed = update_docs(replacements, dry_run=dry_run) + print(f"\n{changed} file(s) {'would be ' if dry_run else ''}updated.") + + print("\nUpdating Spring Boot compatibility table…") + sys.path.insert(0, str(SCRIPT_DIR)) + import update_spring_boot_version_table as sb + sb.run(dry_run=dry_run) + + print("\nUpdating Quarkus compatibility table…") + import update_quarkus_version_table as qk + qk.run(dry_run=dry_run) + + print("\nDone.") if __name__ == "__main__": From 00c5512dc5e976566a622dcb8dd4b11d96088e0e Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 21:34:09 +0200 Subject: [PATCH 09/16] fix: use importlib to load hyphenated script filenames --- .devenv/scripts/update_versions.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index 7f4415d..cf7c374 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -19,6 +19,7 @@ GITHUB_TOKEN Optional GitHub personal-access token. """ +import importlib.util import json import os import re @@ -239,6 +240,26 @@ def update_docs(replacements: list["Replacement"], dry_run: bool = False) -> int return changed +# ── Script Loading ──────────────────────────────────────────────────────────── + +def _load_script(name: str, path: Path) -> object: + """Load a Python script as a module by file path (supports hyphenated filenames). + + Args: + name: Module name (identifier for the module) + path: Path to the .py file to load + + Returns: + The loaded module object + """ + spec = importlib.util.spec_from_file_location(name, path) + if spec is None or spec.loader is None: + raise RuntimeError(f"Cannot load spec from {path}") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + # ── Orchestration (Task 6) ──────────────────────────────────────────────────── THIRD_PARTY_ARTIFACTS = [ @@ -277,12 +298,13 @@ def main(dry_run: bool = False) -> None: print(f"\n{changed} file(s) {'would be ' if dry_run else ''}updated.") print("\nUpdating Spring Boot compatibility table…") - sys.path.insert(0, str(SCRIPT_DIR)) - import update_spring_boot_version_table as sb + sb = _load_script("update_spring_boot_version_table", + SCRIPT_DIR / "update-spring-boot-version-table.py") sb.run(dry_run=dry_run) print("\nUpdating Quarkus compatibility table…") - import update_quarkus_version_table as qk + qk = _load_script("update_quarkus_version_table", + SCRIPT_DIR / "update-quarkus-version-table.py") qk.run(dry_run=dry_run) print("\nDone.") From e66fcf48b69fd60f9340f82dfd804a6a4ea0989a Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 21:34:48 +0200 Subject: [PATCH 10/16] chore: consolidate maintenance workflow to single update-versions script --- .github/workflows/maintenance.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml index 128a8e6..e7f15e5 100644 --- a/.github/workflows/maintenance.yml +++ b/.github/workflows/maintenance.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: jobs: - update-version-tables: + update-versions: runs-on: ubuntu-latest permissions: contents: write @@ -20,18 +20,13 @@ jobs: with: python-version: '3.11' - - name: Update Quarkus version compatibility table - run: python3 .devenv/scripts/update-quarkus-version-table.py - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Update Spring Boot version compatibility table - run: python3 .devenv/scripts/update-spring-boot-version-table.py + - name: Update all versions + run: python3 .devenv/scripts/update_versions.py env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Commit and push changes uses: EndBug/add-and-commit@v11 with: - message: 'docs: update version compatibility tables' + message: 'docs: update version references' default_author: github_actions From 395cd9ebc1c11bfba10e3fed4533d59536e53401 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 21:42:46 +0200 Subject: [PATCH 11/16] fix: use get_latest_operaton_release() in main(), exclude docs/superpowers/ from rewrites --- .devenv/scripts/tests/test_update_versions.py | 13 +++++++++++-- .devenv/scripts/update_versions.py | 17 ++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.devenv/scripts/tests/test_update_versions.py b/.devenv/scripts/tests/test_update_versions.py index 481076a..b24d59a 100644 --- a/.devenv/scripts/tests/test_update_versions.py +++ b/.devenv/scripts/tests/test_update_versions.py @@ -19,12 +19,21 @@ class TestGetLatestRelease(unittest.TestCase): @patch("update_versions._github_get") def test_strips_v_prefix(self, mock_get): mock_get.return_value = {"tag_name": "v2.2.0", "assets": []} - self.assertEqual(uv.get_latest_operaton_release(), "2.2.0") + version, _ = uv.get_latest_operaton_release() + self.assertEqual(version, "2.2.0") @patch("update_versions._github_get") def test_strips_v_prefix_single_digit(self, mock_get): mock_get.return_value = {"tag_name": "v1.5.3", "assets": []} - self.assertEqual(uv.get_latest_operaton_release(), "1.5.3") + version, _ = uv.get_latest_operaton_release() + self.assertEqual(version, "1.5.3") + + @patch("update_versions._github_get") + def test_returns_release_data(self, mock_get): + fake_data = {"tag_name": "v2.2.0", "assets": [{"name": "test.zip"}]} + mock_get.return_value = fake_data + _, release_data = uv.get_latest_operaton_release() + self.assertEqual(release_data["assets"][0]["name"], "test.zip") class TestGetVersionFromSbom(unittest.TestCase): diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index cf7c374..6fdb5f5 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -41,6 +41,7 @@ REPO_ROOT = (SCRIPT_DIR / ".." / "..").resolve() DOCS_DIR = REPO_ROOT / "docs" ARCHIVE_DIR = DOCS_DIR / "get-started" / "archive" +SUPERPOWERS_DIR = DOCS_DIR / "superpowers" # ── GitHub API ──────────────────────────────────────────────────────────────── @@ -61,11 +62,16 @@ def _github_get(path: str) -> object: raise -def get_latest_operaton_release() -> str: - """Return latest release version string without 'v' prefix, e.g. '2.2.0'.""" +def get_latest_operaton_release() -> tuple[str, dict]: + """Return (version_string, release_data) for the latest release. + + version_string has no 'v' prefix, e.g. '2.2.0'. + release_data is the full GitHub API response (includes assets for SBOM). + """ data = _github_get(f"/repos/{REPO}/releases/latest") tag = data["tag_name"] - return tag.lstrip("v") + version = tag.lstrip("v") + return version, data # ── SBOM ────────────────────────────────────────────────────────────────────── @@ -224,6 +230,8 @@ def update_docs(replacements: list["Replacement"], dry_run: bool = False) -> int for md_file in sorted(DOCS_DIR.rglob("*.md")): if md_file.is_relative_to(ARCHIVE_DIR): continue + if md_file.is_relative_to(SUPERPOWERS_DIR): + continue original = md_file.read_text(encoding="utf-8") updated, changes = _apply_replacements_to_text(original, replacements) if updated != original: @@ -277,8 +285,7 @@ def _load_script(name: str, path: Path) -> object: def main(dry_run: bool = False) -> None: print("Fetching latest Operaton release…") - release_data = _github_get(f"/repos/{REPO}/releases/latest") - operaton_version = release_data["tag_name"].lstrip("v") + operaton_version, release_data = get_latest_operaton_release() print(f"Latest Operaton release: {operaton_version}") print("Fetching SBOM…") From e7d23296f039ed59e898dba5a3864b39010661b1 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 31 May 2026 20:01:34 +0000 Subject: [PATCH 12/16] docs: update version references --- ...update-quarkus-version-table.cpython-311.pyc | Bin 0 -> 19788 bytes ...te-spring-boot-version-table.cpython-311.pyc | Bin 0 -> 16580 bytes docs/documentation/user-guide/logging.md | 2 +- .../user-guide/task-forms/jsf-task-forms.md | 2 +- docs/documentation/user-guide/testing/index.md | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 .devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc create mode 100644 .devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc diff --git a/.devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc b/.devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1045b67f55d5b99fd27b65ca71d09064922ca296 GIT binary patch literal 19788 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 A82|tP literal 0 HcmV?d00001 diff --git a/.devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc b/.devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..808ff9b704d5a961ab4deeb3680b45a6b41c78da GIT binary patch literal 16580 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 w704Hr ch.qos.logback logback-classic - 1.1.2 + 1.5.32 ``` diff --git a/docs/documentation/user-guide/task-forms/jsf-task-forms.md b/docs/documentation/user-guide/task-forms/jsf-task-forms.md index 28b5baf..1236821 100644 --- a/docs/documentation/user-guide/task-forms/jsf-task-forms.md +++ b/docs/documentation/user-guide/task-forms/jsf-task-forms.md @@ -246,7 +246,7 @@ To include CSS and JavaScript libraries in your project you can add them to your org.webjars bootstrap - 3.1.1 + 5.3.7 diff --git a/docs/documentation/user-guide/testing/index.md b/docs/documentation/user-guide/testing/index.md index 6c9a004..91f34fd 100644 --- a/docs/documentation/user-guide/testing/index.md +++ b/docs/documentation/user-guide/testing/index.md @@ -243,7 +243,7 @@ You can now see the engine database and use it to understand how and why your un ## Operaton Assertions -Additional to normal JUnit assertions, [Operaton Assert](https://github.com/operaton/operaton/tree/v1.0.0/test-utils/assert) adds a fluent API for asserting typical scenarios in a process integrating with [AssertJ](https://joel-costigliola.github.io/assertj/). +Additional to normal JUnit assertions, [Operaton Assert](https://github.com/operaton/operaton/tree/v2.1.1/test-utils/assert) adds a fluent API for asserting typical scenarios in a process integrating with [AssertJ](https://joel-costigliola.github.io/assertj/). ```java assertThat(processInstance).isWaitingAt("UserTask_InformCustomer"); From 98d0c6abf2a959d5e42622513062bf63f66224ed Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Sun, 31 May 2026 22:06:48 +0200 Subject: [PATCH 13/16] chore: ignore __pycache__ and remove tracked pyc files Co-Authored-By: Claude Sonnet 4.6 --- .../tests/__pycache__/__init__.cpython-310.pyc | Bin 179 -> 0 bytes ..._update_versions.cpython-310-pytest-9.0.3.pyc | Bin 3382 -> 0 bytes .gitignore | 5 +++++ 3 files changed, 5 insertions(+) delete mode 100644 .devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 .devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc diff --git a/.devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc b/.devenv/scripts/tests/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 8a95fb6b53bdfd235d592c4e334a31a34b99e9b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179 zcmd1j<>g`k0;gt~ED-$|L?8o3AjbiSi&=m~3PUi1CZpdhj9;i<65o q3rdRhOHzx0WPE&PUS>&ryk0@&Ee@O9{FKt1R6CG;#Y{kgg#iHiRxP#w diff --git a/.devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc b/.devenv/scripts/tests/__pycache__/test_update_versions.cpython-310-pytest-9.0.3.pyc deleted file mode 100644 index 0f4dd9193d2ed2fb885abbd22d7385f4751ddcc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3382 zcmb7G&2!U66xT|!tvF5s!TI2;P)ZA?jSPX(DbvzW2u!Dt&OqCPE<1{M<0#QrcV#Eh zq^Iy_T1!JWD&5)}D?S#^3mH z{Bhu80sitYAk1JSG(4i;W@MQLF(TV5kz%IomGw-;tLV4mIq){ak*Mlbqfu{^7`(Dp z+Z$sBA7|DMf$_v(bcUbZC(PbA_syQXN$(shu`;VLhmGu7ZNjR%rdMa9tj5OJIGfnD z*co<~P2#9+2E?0sX0UUt{@P%5?yODkSl$e9rr0!arhA-O;LNaD;LP?o=NWlrG|vA6 z78*+pQ;odv+d=C^(pp!g)X!S0%1mT#x^7VvEKB8sW|MFFQ5tf$l|;?qn;Vw0V?W}m)=J`x#~IDGQts84MY18e zpe)&l!^CH_Bf(n~7+MdrJkQRprQ zF>9V=%=u}sa1V}}9~_m}hb_uWdQ}T!aQw00V*&p1DGU1f|gJT>1 zkKr#b0LhGPLdmwVXJ*!(y$@h0QWXv}mvZnKc&$-VwWp7MUZgJXB`pK zt{--|8pT+NZ1IndA1brcRTtq@8fpb;KQE{#R6Q`2EqS=&IT7R{>UUs>Iw*3u-24s1 z$mV*snnbesgm-zEq!EO^3C0W(tjUsA2f0N;x(wFE-KK1bAkAbGy;4wm(kJPbs^c`3 z8LXAGOH;vDg3TH91v;f{)=AzN=3sZ&zSA9h6@)R;hB~opf_n{cFUib33*2iB+-olZ z^zOJ{yLUwe*5@TXZrEZRzQhEQGf2)NnM8taD##R!)T~yj2!*5wonH7a!K^l@h6c@@ zZqSguOO3K}s0JaWs!C~;uujNfT%!~tjPRsXU=E9EBj^WVb+CguVzz7C|12?lt0ZFm;5mN{ppg4<9 zk$=L@8`{o(hQ+Xqt|Wr?Bpz9O6ZXDA^o^5ol0W=Ei$5&v!?r{7J_h2P0VbGlFdudpgt_6KajUZ59o7o9vY|U*8J>de99@ccB^F z7FYrVRzZlqZUwpv+(PbEB-k0enF4>b<%c0>G>KcBZa~Y2%*D#%RdjcaT0=|F9qrW> z*edC=4_!D*-t{QmSmiN|lZ*zj_WFI0sq?99j*}VzH$OSe%^xFnNP>TfCZaoqhR;z^ zIZE&b%--oMgbA*@3UV74l(XCkLa3=y)fUn%I`}$I(=9aHEgT1TK3DJ!5oBDA3|Okt z=T%{|_L47@y(W`bS#nD%rxOPm^1ZSC$VE>JY%^MIWy9@yRh2;lxD#Omg{x^IGH9Uo zS`x&n!UCbM#L#6|0_?2b#EHx+iq9B|yb44)= Date: Sun, 31 May 2026 22:10:49 +0200 Subject: [PATCH 14/16] fix: skip pre-release versions when querying Maven Central Alpha, beta, RC, and milestone versions are excluded via regex filter. Fetches 20 candidates from the GAV core and returns the first stable release. Co-Authored-By: Claude Sonnet 4.6 --- .devenv/scripts/tests/test_update_versions.py | 48 +++++++++++++++++++ .devenv/scripts/update_versions.py | 18 +++++-- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/.devenv/scripts/tests/test_update_versions.py b/.devenv/scripts/tests/test_update_versions.py index b24d59a..1c7348d 100644 --- a/.devenv/scripts/tests/test_update_versions.py +++ b/.devenv/scripts/tests/test_update_versions.py @@ -47,6 +47,54 @@ def test_returns_none_for_none_sbom(self): self.assertIsNone(uv.get_version_from_sbom(None, "org.slf4j", "slf4j-simple")) +class TestIsReleaseVersion(unittest.TestCase): + def test_accepts_stable(self): + for v in ("2.0.9", "1.0.0", "3.5.0", "10.2.1"): + self.assertTrue(uv._is_release_version(v), v) + + def test_rejects_alpha(self): + self.assertFalse(uv._is_release_version("2.0.0-alpha")) + self.assertFalse(uv._is_release_version("2.0.0.alpha1")) + + def test_rejects_beta(self): + self.assertFalse(uv._is_release_version("2.0.0-beta")) + self.assertFalse(uv._is_release_version("2.0.0-beta2")) + + def test_rejects_rc(self): + self.assertFalse(uv._is_release_version("2.0.0-RC1")) + self.assertFalse(uv._is_release_version("2.0.0-rc2")) + + def test_rejects_milestone(self): + self.assertFalse(uv._is_release_version("6.0.0-M1")) + self.assertFalse(uv._is_release_version("6.0.0-M12")) + + +class TestGetVersionFromMavenCentral(unittest.TestCase): + @patch("update_versions.urllib.request.urlopen") + def test_skips_prerelease_versions(self, mock_urlopen): + docs = [ + {"v": "6.0.0-M1"}, + {"v": "5.3.39"}, + {"v": "5.3.38"}, + ] + payload = json.dumps({"response": {"docs": docs}}).encode() + mock_urlopen.return_value.__enter__ = lambda s: s + mock_urlopen.return_value.__exit__ = unittest.mock.MagicMock(return_value=False) + mock_urlopen.return_value.read = lambda: payload + result = uv.get_version_from_maven_central("org.springframework", "spring-core") + self.assertEqual(result, "5.3.39") + + @patch("update_versions.urllib.request.urlopen") + def test_raises_when_only_prereleases(self, mock_urlopen): + docs = [{"v": "6.0.0-M1"}, {"v": "5.0.0-RC1"}] + payload = json.dumps({"response": {"docs": docs}}).encode() + mock_urlopen.return_value.__enter__ = lambda s: s + mock_urlopen.return_value.__exit__ = unittest.mock.MagicMock(return_value=False) + mock_urlopen.return_value.read = lambda: payload + with self.assertRaises(RuntimeError): + uv.get_version_from_maven_central("org.springframework", "spring-core") + + class TestResolveVersion(unittest.TestCase): @patch("update_versions.get_version_from_maven_central") def test_prefers_sbom(self, mock_mc): diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index 6fdb5f5..6ff8942 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -133,9 +133,18 @@ def get_version_from_sbom(sbom: Optional[dict], group_id: str, artifact_id: str) # ── Maven Central ───────────────────────────────────────────────────────────── +_PRE_RELEASE_RE = re.compile( + r"(?i)[.-](alpha\d*|beta\d*|rc\d*|m\d+)(\..*)?$" +) + + +def _is_release_version(version: str) -> bool: + return _PRE_RELEASE_RE.search(version) is None + + def get_version_from_maven_central(group_id: str, artifact_id: str) -> str: - """Return the latest release version for a Maven artifact from Maven Central.""" - params = f"q=g:{group_id}+AND+a:{artifact_id}&rows=1&wt=json" + """Return the latest stable release version for a Maven artifact from Maven Central.""" + params = f"q=g:{group_id}+AND+a:{artifact_id}&core=gav&rows=20&wt=json" url = f"{MAVEN_CENTRAL_SEARCH}?{params}" req = urllib.request.Request(url) try: @@ -144,7 +153,10 @@ def get_version_from_maven_central(group_id: str, artifact_id: str) -> str: docs = data["response"]["docs"] if not docs: raise RuntimeError(f"No results from Maven Central for {group_id}:{artifact_id}") - return docs[0]["latestVersion"] + release_versions = [d["v"] for d in docs if _is_release_version(d["v"])] + if not release_versions: + raise RuntimeError(f"No stable release found on Maven Central for {group_id}:{artifact_id}") + return release_versions[0] except urllib.error.HTTPError as exc: print(f"Maven Central error for {group_id}:{artifact_id}: {exc.code}", file=sys.stderr) raise From 49243d38afd96ee131fbfd25f4892b8cba11ac54 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Mon, 8 Jun 2026 21:40:04 +0200 Subject: [PATCH 15/16] chore: Get github token smarter --- .devenv/scripts/update_versions.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.devenv/scripts/update_versions.py b/.devenv/scripts/update_versions.py index 6ff8942..4a25d58 100644 --- a/.devenv/scripts/update_versions.py +++ b/.devenv/scripts/update_versions.py @@ -46,8 +46,25 @@ # ── GitHub API ──────────────────────────────────────────────────────────────── -def _github_get(path: str) -> object: +def _get_github_token() -> str: token = os.environ.get("GITHUB_TOKEN", "") + if token: + return token + try: + import subprocess + result = subprocess.run( + ["gh", "auth", "token"], + capture_output=True, text=True, timeout=5, + ) + if result.returncode == 0: + return result.stdout.strip() + except Exception: + pass + return "" + + +def _github_get(path: str) -> object: + token = _get_github_token() url = f"{GITHUB_API_BASE}{path}" req = urllib.request.Request(url) req.add_header("Accept", "application/vnd.github+json") From da3a63560905aa8aa0b7bd91c7e18c8d1194a015 Mon Sep 17 00:00:00 2001 From: Andreas Zill Date: Sun, 6 Sep 2026 15:37:08 +0200 Subject: [PATCH 16/16] address Copilot review feedback: untrack stray .pyc files, fix prerelease regex, fix docstring, fix Bootstrap webjar path Untrack .pyc files (Copilot didn't flag this, requested separately): - .devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc - .devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc These re-appeared in the "docs: update version references" automation commit despite .gitignore already excluding __pycache__/ - adding a gitignore entry doesn't untrack already-committed files. Fix _PRE_RELEASE_RE to catch hyphen-separated qualifiers (Copilot, update_versions.py:181): "4.0.0-beta-4" (maven-compiler-plugin's actual prerelease scheme) wasn't matched by the old alpha\d*|beta\d*|rc\d*|m\d+ pattern, which only handled qualifiers with digits attached directly (e.g. "2.1.0-alpha1"). Added a regression test. Fix already-committed prerelease versions that slipped through before this regex existed (Copilot, service-task.md:135 and dmn/project-setup.md:91): - slf4j-simple 2.1.0-alpha1 -> 2.0.17 (current stable) - maven-compiler-plugin 4.0.0-beta-4 -> 3.15.0 (current stable) Also restored two unrelated version bumps from the same commit that a naive conflict resolution during the rebase onto current main had accidentally reverted to their pre-PR values: - javax.servlet-api -> 4.0.1 - maven-war-plugin -> 3.5.1 Fix docstring usage example (Copilot, update_versions.py:16): referenced "update-versions.py" (hyphen), the file is "update_versions.py" (underscore). Fix Bootstrap webjar resource path (Copilot, jsf-task-forms.md:249): the dependency was bumped to 5.3.7 but the JSF / library paths still pointed at webjars/bootstrap/3.1.1/, which doesn't exist for that version. Co-Authored-By: Claude Sonnet 5 --- ...update-quarkus-version-table.cpython-311.pyc | Bin 19788 -> 0 bytes ...te-spring-boot-version-table.cpython-311.pyc | Bin 16580 -> 0 bytes .devenv/scripts/tests/test_update_versions.py | 7 +++++++ .devenv/scripts/update_versions.py | 7 +++++-- .../user-guide/task-forms/jsf-task-forms.md | 4 ++-- docs/get-started/dmn/project-setup.md | 6 +++--- docs/get-started/quick-start/service-task.md | 2 +- 7 files changed, 18 insertions(+), 8 deletions(-) delete mode 100644 .devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc delete mode 100644 .devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc diff --git a/.devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc b/.devenv/scripts/__pycache__/update-quarkus-version-table.cpython-311.pyc deleted file mode 100644 index 1045b67f55d5b99fd27b65ca71d09064922ca296..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19788 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 A82|tP diff --git a/.devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc b/.devenv/scripts/__pycache__/update-spring-boot-version-table.cpython-311.pyc deleted file mode 100644 index 808ff9b704d5a961ab4deeb3680b45a6b41c78da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16580 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 w704Hr/@ Usage: - python3 .devenv/scripts/update-versions.py [--dry-run] + python3 .devenv/scripts/update_versions.py [--dry-run] Environment variables: GITHUB_TOKEN Optional GitHub personal-access token. @@ -150,8 +150,11 @@ def get_version_from_sbom(sbom: Optional[dict], group_id: str, artifact_id: str) # ── Maven Central ───────────────────────────────────────────────────────────── +# The qualifier and its digits may be separated by another "-" (e.g. +# "4.0.0-beta-4", as seen on maven-compiler-plugin), not just attached +# directly (e.g. "2.1.0-alpha1") - both forms show up on Maven Central. _PRE_RELEASE_RE = re.compile( - r"(?i)[.-](alpha\d*|beta\d*|rc\d*|m\d+)(\..*)?$" + r"(?i)[.-](alpha|beta|rc|m)[-.]?\d*(\..*)?$" ) diff --git a/docs/documentation/user-guide/task-forms/jsf-task-forms.md b/docs/documentation/user-guide/task-forms/jsf-task-forms.md index 1236821..9159714 100644 --- a/docs/documentation/user-guide/task-forms/jsf-task-forms.md +++ b/docs/documentation/user-guide/task-forms/jsf-task-forms.md @@ -260,10 +260,10 @@ To use them, add tags like the following ones to your JSF page. If you have seve - + - + ``` diff --git a/docs/get-started/dmn/project-setup.md b/docs/get-started/dmn/project-setup.md index 95b3b86..4738908 100644 --- a/docs/get-started/dmn/project-setup.md +++ b/docs/get-started/dmn/project-setup.md @@ -77,7 +77,7 @@ The next step consists of setting up the Maven dependencies for your new process javax.servlet javax.servlet-api - 3.0.1 + 4.0.1 provided @@ -87,12 +87,12 @@ The next step consists of setting up the Maven dependencies for your new process org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.15.0 org.apache.maven.plugins maven-war-plugin - 3.3.2 + 3.5.1 false diff --git a/docs/get-started/quick-start/service-task.md b/docs/get-started/quick-start/service-task.md index 10480f5..048cd6e 100644 --- a/docs/get-started/quick-start/service-task.md +++ b/docs/get-started/quick-start/service-task.md @@ -131,7 +131,7 @@ Your pom.xml file of your project should look like this: org.slf4j slf4j-simple - 1.7.36 + 2.0.17 jakarta.xml.bind