"""Drive the real player build through the HTTP UI and poll its progress. Logs in as admin over HTTPS, POSTs the build form exactly like the browser, then polls /admin/build-player/status until it finishes — mirroring what a real user sees, including the non-blocking behaviour. Optional arg: branch to build (default 'main'). """ import http.cookiejar import json import re import ssl import sys import time import urllib.parse import urllib.request BASE = 'https://192.168.0.152' BRANCH = sys.argv[1] if len(sys.argv) > 1 else 'main' pw = open('.deployment-credentials').read().split('admin password: ')[1].strip() ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE op = urllib.request.build_opener( urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()), urllib.request.HTTPSHandler(context=ctx), ) def get(path): return op.open(BASE + path, timeout=60).read().decode() print('1) logging in…') html = get('/login') tok = re.search(r'name="csrf_token"[^>]*value="([^"]+)"', html) data = urllib.parse.urlencode({ 'username': 'admin', 'password': pw, 'csrf_token': tok.group(1) if tok else '', }).encode() r = op.open(urllib.request.Request(BASE + '/login', data=data, method='POST'), timeout=60) print(' logged in ->', r.geturl()) print(f'2) posting build form (branch={BRANCH})…') html = get('/admin/build-player') tok = re.search(r'name="csrf_token"[^>]*value="([^"]+)"', html) form = urllib.parse.urlencode({ 'action': 'build_and_config', 'repo_url': 'https://gitea.moto-adv.com/ske087/Kiwy-Signage.git', 'branch': BRANCH, 'server_ip': '192.168.0.152', 'port': '443', 'use_https': 'on', 'orientation': 'Landscape', 'max_resolution': '1920x1080', 'csrf_token': tok.group(1) if tok else '', }).encode() t0 = time.time() r = op.open(urllib.request.Request(BASE + '/admin/build-player', data=form, method='POST'), timeout=60) post_elapsed = time.time() - t0 print(f' POST returned in {post_elapsed:.1f}s -> {r.status} {r.geturl()}') if post_elapsed > 30: print(' ⚠ POST blocked for a long time — the build is NOT async!') print('3) polling status…') last = None deadline = time.time() + 420 while time.time() < deadline: try: raw = get('/admin/build-player/status') s = json.loads(raw) except Exception as e: # noqa: BLE001 time.sleep(2) continue cur = (s.get('state'), s.get('step'), s.get('message')) if cur != last: print(f" [{time.time() - t0:6.1f}s] state={s.get('state'):8} " f"step={s.get('step') or '-':28} version={s.get('version')}") if s.get('message'): print(f" msg: {s['message'][:110]}") last = cur if s.get('state') in ('success', 'error'): print() print('RESULT:', s.get('state')) print(' version :', s.get('version')) print(' message :', (s.get('message') or '')[:400]) sys.exit(0 if s.get('state') == 'success' else 1) time.sleep(2) print('timed out waiting for the build') sys.exit(1)