fix(release): validate independent module versions

This commit is contained in:
2026-07-21 12:51:25 +02:00
parent b193d4555f
commit a18c7ea040
3 changed files with 43 additions and 15 deletions

View File

@@ -32,9 +32,8 @@ with (Path.cwd() / "pyproject.toml").open("rb") as handle:
print(tomllib.load(handle)["project"]["version"])
PY
)"
RELEASE_TAG="${GOVOPLAN_RELEASE_TAG:-v$RELEASE_VERSION}"
export RELEASE_TAG RELEASE_VERSION
export RELEASE_VERSION
export META_ROOT
export GOVOPLAN_CORE_SOURCE_ROOT="$ROOT"
export GOVOPLAN_MIGRATION_TRACK=release
@@ -91,6 +90,30 @@ install_cloned_webui_dependencies() {
)
}
release_tag_for_package() {
local package_name="$1"
"$PYTHON" - "$META_ROOT/requirements-release.txt" "$package_name" <<'PY'
from __future__ import annotations
from pathlib import Path
import re
import sys
requirements_path = Path(sys.argv[1])
package_name = sys.argv[2]
pattern = re.compile(
rf"^{re.escape(package_name)}\s+@\s+git\+ssh://.+?\.git@(v[0-9]+\.[0-9]+\.[0-9]+)$"
)
for line in requirements_path.read_text(encoding="utf-8").splitlines():
match = pattern.match(line.strip())
if match:
print(match.group(1))
raise SystemExit(0)
raise SystemExit(f"No immutable release reference found for {package_name}")
PY
}
run_step "Validate release refs and installed package metadata"
"$PYTHON" "$META_ROOT/tools/checks/check-version-alignment.py" --release-composition
"$PYTHON" "$META_ROOT/tools/checks/check-contracts.py" --no-impact
@@ -109,7 +132,6 @@ root = Path.cwd()
release_requirements = Path(os.environ["META_ROOT"]) / "requirements-release.txt"
release_webui = root / "webui" / "package.release.json"
expected_version = os.environ["RELEASE_VERSION"]
expected_tag = os.environ["RELEASE_TAG"]
errors: list[str] = []
python_requirements: list[tuple[str, str, str]] = []
@@ -122,8 +144,6 @@ if not python_requirements:
errors.append("No GovOPlaN git+ssh release requirements found.")
for package_name, repo_url, tag in python_requirements:
if tag != expected_tag:
errors.append(f"{package_name} release requirement uses {tag!r}, expected {expected_tag!r}.")
version = metadata.version(package_name)
if version != tag.removeprefix("v"):
errors.append(f"{package_name} installed version {version!r} does not match {tag!r}.")
@@ -147,15 +167,18 @@ for package_name, spec in sorted(webui_dependencies.items()):
if not package_name.startswith("@govoplan/"):
continue
tag = spec.rsplit("#", 1)[-1] if "#" in spec else ""
if tag != expected_tag:
errors.append(f"{package_name} release dependency uses {tag!r}, expected {expected_tag}.")
tag_match = re.fullmatch(r"v([0-9]+\.[0-9]+\.[0-9]+)", tag)
if tag_match is None:
errors.append(f"{package_name} release dependency has invalid immutable tag {tag!r}.")
continue
dependency_version = tag_match.group(1)
package_json = root / "webui" / "node_modules" / package_name / "package.json"
if not package_json.exists():
errors.append(f"{package_name} is missing from release node_modules.")
continue
installed = json.loads(package_json.read_text(encoding="utf-8"))
if installed.get("version") != expected_version:
errors.append(f"{package_name} installed version {installed.get('version')!r}, expected {expected_version!r}.")
if installed.get("version") != dependency_version:
errors.append(f"{package_name} installed version {installed.get('version')!r}, expected {dependency_version!r} from {tag!r}.")
shared_peers = ("lucide-react", "react", "react-dom", "react-router-dom")
root_peers = release_package.get("peerDependencies", {})
@@ -252,7 +275,8 @@ PY
run_step "Clone release module test sources"
for repo in govoplan-mail govoplan-calendar govoplan-campaign; do
git clone --depth 1 --branch "$RELEASE_TAG" "git@git.add-ideas.de:add-ideas/${repo}.git" "$WORK_ROOT/$repo"
repo_tag="$(release_tag_for_package "$repo")"
git clone --depth 1 --branch "$repo_tag" "git@git.add-ideas.de:add-ideas/${repo}.git" "$WORK_ROOT/$repo"
done
run_step "Run core backend release tests"