docs: record migration head 0020 in the release manifest and docs
RELEASE_MANIFEST.json still said head 0011 (repo was at 0018, now 0020)
and RELEASE_CANDIDATE_V1.md said 0010. Updated both, plus
AI_PROJECT_STATE.md and PILOT_DEPLOYMENT.md, to head
0020_not_null_timestamps as applied in production.
scripts/release_manifest.py reported the 4-digit file prefix as the head
("0020" instead of "0020_not_null_timestamps") and always read the
applied revision from the dev container. It now asks Alembic for the real
head and revision count, and the Hub container is configurable
(HUB_CONTAINER); the source is recorded in the manifest.
tests/test_release_candidate.py now fails when the manifest head differs
from Alembic's head.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ Registers together: release version, agent/hub versions, fiscal engine + decisio
|
||||
(kind, provider, sha256, record_count) read from the running Hub, alembic head (from the migration files) and the applied revision.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -31,10 +32,18 @@ def main():
|
||||
from central.app.icms_context import ICMS_CONTEXT_ENGINE_VERSION
|
||||
from central.app.product_defaults import PRODUCT_DEFAULTS_ENGINE_VERSION
|
||||
version = (ROOT / "release" / "VERSION").read_text(encoding="utf-8").strip()
|
||||
heads = sorted(p.name.split("_")[0] for p in (ROOT / "central" / "alembic" / "versions").glob("00*.py"))
|
||||
# Real revision ids (e.g. "0020_not_null_timestamps"), not file-name prefixes:
|
||||
# from 0015 on the id is longer than the 4-digit prefix.
|
||||
from alembic.config import Config
|
||||
from alembic.script import ScriptDirectory
|
||||
alembic_cfg = Config(str(ROOT / "central" / "alembic.ini"))
|
||||
alembic_cfg.set_main_option("script_location", str(ROOT / "central" / "alembic"))
|
||||
script = ScriptDirectory.from_config(alembic_cfg)
|
||||
head, revision_count = script.get_current_head(), len(list(script.walk_revisions()))
|
||||
container = os.getenv("HUB_CONTAINER", "projeto-fiscal-hub-1")
|
||||
try:
|
||||
applied = subprocess.run(["docker", "exec", "projeto-fiscal-hub-1", "sh", "-c", "cd /app && alembic -c central/alembic.ini current"], capture_output=True, text=True, timeout=60).stdout
|
||||
applied = re.findall(r"^(\d{4})", applied, re.M)[-1:] or ["unknown"]
|
||||
current = subprocess.run(["docker", "exec", container, "sh", "-c", "cd /app && alembic -c central/alembic.ini current"], capture_output=True, text=True, timeout=60).stdout
|
||||
applied = re.findall(r"^(\d{4}\S*)", current, re.M)[-1:] or ["unknown"]
|
||||
except Exception: # noqa: BLE001
|
||||
applied = ["unknown"]
|
||||
datasets = sorted(({"kind": d["kind"], "sha256": d["sha256"][:16], "record_count": d["record_count"]} for d in get(f"{hub}/v1/datasets/status", token) if d["status"] == "ACTIVE"), key=lambda x: x["kind"])
|
||||
@@ -42,7 +51,7 @@ def main():
|
||||
"hub": get(f"{hub}/version", token), "agent_version": version,
|
||||
"fiscal_engine": {"ENGINE_VERSION": ENGINE_VERSION, "DECISION_VERSION": DECISION_VERSION, "DECISION_ENGINE_VERSION": DECISION_ENGINE_VERSION,
|
||||
"PRODUCT_DEFAULTS_ENGINE_VERSION": PRODUCT_DEFAULTS_ENGINE_VERSION, "ICMS_CONTEXT_ENGINE_VERSION": ICMS_CONTEXT_ENGINE_VERSION},
|
||||
"migrations": {"alembic_head_in_repo": heads[-1], "applied_revision": applied[0], "count": len(heads)},
|
||||
"migrations": {"alembic_head_in_repo": head, "applied_revision": applied[0], "applied_revision_source": f"container {container}", "count": revision_count},
|
||||
"datasets_active": datasets, "note": "A release bump does not change fiscal semantics; engine/decision versions are versioned independently."}
|
||||
(ROOT / "release" / "RELEASE_MANIFEST.json").write_text(json.dumps(manifest, indent=1), encoding="utf-8")
|
||||
print(json.dumps({"version": version, "engine": ENGINE_VERSION, "migrations": manifest["migrations"], "datasets": len(datasets)}))
|
||||
|
||||
Reference in New Issue
Block a user