fix: deploy health via docker exec (prod port bound to VM IP), safe rollback, error propagation, VPN retry, release default + download verification
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Post-deploy proof through the PUBLIC panel: the default release is served as the real installer EXE (not a zip)
|
||||
with the published sha256. Creates a throwaway LOCAL admin + an E2E installation, revokes/deactivates both after
|
||||
(never deleted: audit FKs). Run inside the Hub container: python central/scripts/verify_release_download.py <version>"""
|
||||
import hashlib
|
||||
import sys
|
||||
import time
|
||||
|
||||
import httpx
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
sys.path.insert(0, "central")
|
||||
from app.db import engine # noqa: E402
|
||||
from app.human_auth import hash_password # noqa: E402
|
||||
from app.models import AdminUser, AgentRelease, Tenant # noqa: E402
|
||||
|
||||
BASE = "https://gtifiscal.gtigrupo.com.br"
|
||||
PASSWORD = "Verify-tmp-2026!x"
|
||||
want = sys.argv[1]
|
||||
user = f"e2e-verify-{int(time.time())}"
|
||||
with Session(engine) as db:
|
||||
rel = db.query(AgentRelease).filter_by(version=want, platform="windows", architecture="x64").one()
|
||||
default = db.query(AgentRelease).filter_by(status="PUBLISHED").order_by(AgentRelease.created_at.desc()).first()
|
||||
assert rel.status == "PUBLISHED" and default.id == rel.id, f"default release is {default.version}, expected {want}"
|
||||
tenant = db.query(Tenant).filter_by(name="E2E-PROD-TEST").one_or_none() or Tenant(name="E2E-PROD-TEST")
|
||||
db.add(tenant); db.add(AdminUser(username=user, password_hash=hash_password(PASSWORD), is_active=True, auth_source="LOCAL")); db.flush()
|
||||
tenant_id, release_id, sha, name = tenant.id, rel.id, rel.sha256, rel.filename
|
||||
db.commit()
|
||||
try:
|
||||
c = httpx.Client(follow_redirects=False, timeout=120)
|
||||
assert c.post(f"{BASE}/login", data={"username": user, "password": PASSWORD}).status_code == 303
|
||||
csrf = c.cookies.get("gti_csrf")
|
||||
r = c.post(f"{BASE}/agents/new", data={"csrf_token": csrf, "tenant_id": tenant_id, "display_name": "E2E-VERIFY Servidor", "release_id": release_id})
|
||||
assert r.status_code == 303, r.status_code
|
||||
uuid = r.headers["location"].rsplit("/", 1)[-1]
|
||||
d = c.get(f"{BASE}/agents/pending/{uuid}/download")
|
||||
disp = d.headers.get("content-disposition", "")
|
||||
assert d.status_code == 200 and name in disp and name.endswith(".exe"), (d.status_code, disp)
|
||||
assert d.content[:2] == b"MZ", "not a Windows executable"
|
||||
got = hashlib.sha256(d.content).hexdigest()
|
||||
assert got == sha, "sha256 mismatch"
|
||||
print(f"DOWNLOAD_IS_EXE=true filename={name} SHA256_MATCH=true size={len(d.content)}")
|
||||
c.post(f"{BASE}/agents/pending/{uuid}/revoke", data={"csrf_token": csrf})
|
||||
finally:
|
||||
with Session(engine) as db:
|
||||
db.query(AdminUser).filter_by(username=user).update({"is_active": False}); db.commit()
|
||||
print("VERIFY_DOWNLOAD=PASS")
|
||||
Reference in New Issue
Block a user