Prepare GeoIntel 1.0.0 release candidate
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SCRIPT = ROOT / "scripts" / "build_release_package.py"
|
||||
|
||||
|
||||
def load_script():
|
||||
spec = importlib.util.spec_from_file_location("build_release_package", SCRIPT)
|
||||
assert spec is not None and spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def test_release_version_is_consistent_across_runtime_packages() -> None:
|
||||
version = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
|
||||
config = (ROOT / "backend" / "app" / "core" / "config.py").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
pyproject = (ROOT / "backend" / "pyproject.toml").read_text(encoding="utf-8")
|
||||
frontend = json.loads(
|
||||
(ROOT / "frontend" / "package.json").read_text(encoding="utf-8")
|
||||
)
|
||||
package_lock = json.loads(
|
||||
(ROOT / "frontend" / "package-lock.json").read_text(encoding="utf-8")
|
||||
)
|
||||
|
||||
assert version == "1.0.0-rc.1"
|
||||
assert f'default="{version}"' in config
|
||||
assert "GEOINTEL_APP_VERSION" in config
|
||||
assert 'version = "1.0.0rc1"' in pyproject
|
||||
assert frontend["version"] == version
|
||||
assert package_lock["version"] == version
|
||||
assert package_lock["packages"][""]["version"] == version
|
||||
|
||||
|
||||
def test_release_image_carries_semantic_version_identity() -> None:
|
||||
dockerfile = (ROOT / "deploy" / "unraid" / "Dockerfile.all-in-one").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
deploy = (ROOT / "deploy" / "unraid" / "deploy-release.sh").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
assert "ARG GEOINTEL_APP_VERSION=1.0.0-rc.1" in dockerfile
|
||||
assert 'org.opencontainers.image.version="${GEOINTEL_APP_VERSION}"' in dockerfile
|
||||
assert "GEOINTEL_APP_VERSION=\"$(tr -d '[:space:]' < VERSION)\"" in deploy
|
||||
assert "--build-arg GEOINTEL_APP_VERSION=" in deploy
|
||||
assert "stored_version" in deploy
|
||||
|
||||
|
||||
@pytest.mark.skipif(shutil.which("ssh-keygen") is None, reason="ssh-keygen unavailable")
|
||||
def test_release_package_signature_and_checksums_fail_closed(tmp_path: Path) -> None:
|
||||
module = load_script()
|
||||
key = tmp_path / "release-key"
|
||||
result = subprocess.run(
|
||||
["ssh-keygen", "-q", "-t", "ed25519", "-N", "", "-f", str(key)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
assert result.returncode == 0, result.stderr
|
||||
|
||||
package = tmp_path / "package"
|
||||
package.mkdir()
|
||||
evidence = package / "readiness.txt"
|
||||
evidence.write_text("passed\n", encoding="utf-8")
|
||||
identity = "geointel-release"
|
||||
namespace = "geointel-release"
|
||||
(package / module.SIGNERS_NAME).write_text(
|
||||
f"{identity} {module.public_key(key)}\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
manifest = {
|
||||
"schema_version": 1,
|
||||
"release_id": "v1.0.0-rc.1",
|
||||
"version": "1.0.0-rc.1",
|
||||
"scope": "Belgium and the Belgian North Sea",
|
||||
"signature": {"identity": identity, "namespace": namespace},
|
||||
"evidence": [
|
||||
{
|
||||
"path": evidence.name,
|
||||
"size_bytes": evidence.stat().st_size,
|
||||
"sha256": module.sha256(evidence),
|
||||
}
|
||||
],
|
||||
}
|
||||
manifest_path = package / module.MANIFEST_NAME
|
||||
manifest_path.write_text(json.dumps(manifest) + "\n", encoding="utf-8")
|
||||
module.run(
|
||||
(
|
||||
"ssh-keygen",
|
||||
"-Y",
|
||||
"sign",
|
||||
"-f",
|
||||
str(key),
|
||||
"-n",
|
||||
namespace,
|
||||
str(manifest_path),
|
||||
)
|
||||
)
|
||||
module.write_checksums(package)
|
||||
|
||||
verified = module.verify_package(package)
|
||||
assert verified["release_id"] == "v1.0.0-rc.1"
|
||||
|
||||
evidence.write_text("tampered\n", encoding="utf-8")
|
||||
with pytest.raises(RuntimeError, match="Checksum mismatch"):
|
||||
module.verify_package(package)
|
||||
|
||||
|
||||
def test_release_package_cli_requires_tagged_clean_revision() -> None:
|
||||
source = SCRIPT.read_text(encoding="utf-8")
|
||||
readiness = (ROOT / "scripts" / "run_readiness_check.sh").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
assert 'run(("git", "status", "--porcelain=v1"))' in source
|
||||
assert 'run(("git", "rev-list", "-n", "1", release_id))' in source
|
||||
assert "Image revision must equal the tagged Git commit" in source
|
||||
assert "ssh-keygen" in source
|
||||
assert "verify_checksums(package_dir)" in source
|
||||
assert "py_compile scripts/build_release_package.py" in readiness
|
||||
@@ -34,6 +34,7 @@ def test_release_evidence_manifest_is_secret_free_and_read_only(tmp_path: Path)
|
||||
|
||||
assert manifest["schema_version"] == 1
|
||||
assert manifest["release_id"] == "test-rc"
|
||||
assert manifest["version"] == "1.0.0-rc.1"
|
||||
assert manifest["read_only"] is True
|
||||
assert manifest["scope"] == "Belgium and the Belgian North Sea"
|
||||
assert "DATABASE_URL" not in json.dumps(manifest).replace(
|
||||
@@ -72,6 +73,7 @@ def test_release_evidence_cli_writes_single_head_manifest(tmp_path: Path) -> Non
|
||||
assert payload["migrations"]["single_head"] is True
|
||||
assert payload["files"]["docs/RC_SCOPE_FREEZE_BELGIUM_NORTH_SEA.md"]["sha256"]
|
||||
assert payload["files"]["docs/RC_ROADMAP_BELGIUM_NORTH_SEA.md"]["sha256"]
|
||||
assert payload["files"]["docs/RELEASE_RUNBOOK.md"]["sha256"]
|
||||
|
||||
|
||||
def test_readiness_gate_compiles_release_evidence_command() -> None:
|
||||
|
||||
@@ -49,10 +49,11 @@ def test_operator_workflows_put_mol_first_and_name_future_projects() -> None:
|
||||
assert 'QUALITY_SAMPLE_SLUG="${sample_slug}"' in multi_matrix
|
||||
|
||||
|
||||
def test_product_docs_record_mol_primary_focus_without_dropping_kempen_scope() -> None:
|
||||
def test_product_docs_record_national_scope_and_mol_regression_focus() -> None:
|
||||
readme = (ROOT / "README.md").read_text(encoding="utf-8")
|
||||
vision = (ROOT / "docs" / "PRODUCT_VISION.md").read_text(encoding="utf-8")
|
||||
|
||||
assert "primary operating focus is Mol" in readme
|
||||
assert "Mol is de primaire operationele focus" in vision
|
||||
assert "broader Kempen" in readme
|
||||
assert "Belgium and the Belgian North Sea" in readme
|
||||
assert "Mol and the Kempen remain deep regression" in readme
|
||||
assert "Belgie en de Belgische Noordzee" in vision
|
||||
assert "Mol en de Kempen blijven gouden regressiegebieden" in vision
|
||||
|
||||
Reference in New Issue
Block a user