upgrade: adopt V8.33.1 — final merge, our patches upstreamed natively
V8.33.0 absorbed our entire platform patch set as native features (discovery/env_for macro override/blocks.css priority/type-mapping fix/ frontend entries/locale override) and synced trade-pro from our remote; V8.33.1 adds HESU PIPE industrial-theme home fixes (1.3.1). Zero patch re-application this round — all verified native. Theme suites 35/35; full run 428 passed + same 10 known Windows env fails (FAILED set unchanged). Live: container 8.33.1-dev.1 healthy, hesupipe 192 entries intact, trade-pro build 203 pages 0 errors. Patch registry retired to archive — future upgrades are plain overlay. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""End-to-end HTTP + Worker smoke test on an isolated disposable SQLite database.
|
||||
|
||||
Launches an actual uvicorn process, calls authenticated HTTP APIs, runs a real
|
||||
Worker claim + isolated subprocess build, then downloads and checks the archive.
|
||||
Never points at production data or remote deployment services.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from urllib.error import URLError
|
||||
from urllib.request import urlopen
|
||||
import httpx
|
||||
|
||||
ROOT=Path(__file__).resolve().parent.parent
|
||||
|
||||
def run():
|
||||
with tempfile.TemporaryDirectory(prefix='siteforge-e2e-') as folder:
|
||||
with socket.socket() as sock:
|
||||
sock.bind(('127.0.0.1',0)); port=sock.getsockname()[1]
|
||||
base=f'http://127.0.0.1:{port}'
|
||||
env=os.environ.copy()
|
||||
env.update(SITEFORGE_ADMIN_PASSWORD='e2e-only-dummy-password-123456',
|
||||
SITEFORGE_SESSION_SECRET='e2e-only-session-secret-long-value-123456',
|
||||
SITEFORGE_DATA_DIR=folder,SITEFORGE_DB_FILE=str(Path(folder)/'siteforge.sqlite3'),
|
||||
SITEFORGE_DATABASE_URL='',SITEFORGE_REDIS_URL='',SITEFORGE_COOKIE_SECURE='false')
|
||||
proc=subprocess.Popen([sys.executable,'-m','uvicorn','app.main:app','--host','127.0.0.1','--port',str(port)],
|
||||
cwd=ROOT,env=env,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE)
|
||||
try:
|
||||
for n in range(120):
|
||||
if proc.poll() is not None:raise RuntimeError('Web startup failed: '+proc.stderr.read().decode(errors='replace')[-3000:])
|
||||
try:
|
||||
with urlopen(base+'/api/ready',timeout=0.5) as result:
|
||||
if result.status==200:break
|
||||
except (OSError,URLError):time.sleep(0.1)
|
||||
else:raise RuntimeError('Web readiness timeout')
|
||||
with httpx.Client(base_url=base,timeout=20,follow_redirects=False) as client:
|
||||
auth=client.post('/api/auth/login',json={'username':'admin','password':env['SITEFORGE_ADMIN_PASSWORD']})
|
||||
assert auth.status_code==200,auth.text
|
||||
me=client.get('/api/auth/me')
|
||||
assert me.status_code==200,me.text
|
||||
client.headers['X-SiteForge-CSRF']=me.json()['csrf']
|
||||
site=client.post('/api/sites',json={'name':'V8.33 Trade Pro Worker','theme':'trade-pro'})
|
||||
assert site.status_code==201,site.text
|
||||
sid=site.json()['id']
|
||||
page=client.post(f'/api/sites/{sid}/entries',json={'type':'page','title':'Test about','route':'/about/','body':'E2E smoke content'})
|
||||
assert page.status_code==201,page.text
|
||||
job=client.post(f'/api/sites/{sid}/builds',json={'mirror_images':False},headers={'Idempotency-Key':'e2e-build-000001'})
|
||||
assert job.status_code==202,job.text
|
||||
completed=subprocess.run([sys.executable,'-c','from app import db,enterprise,worker; db.init(); enterprise.setup(); assert worker.run_once()'],cwd=ROOT,env=env,capture_output=True,text=True,timeout=70)
|
||||
assert completed.returncode==0,completed.stderr[-2500:]
|
||||
builds=client.get(f'/api/sites/{sid}/builds')
|
||||
assert builds.status_code==200,builds.text
|
||||
done=[x for x in builds.json() if x['status']=='complete']
|
||||
if not done:
|
||||
raise AssertionError('No completed static build: '+str(builds.json())[:1200])
|
||||
archive=client.get(f"/api/sites/{sid}/builds/{done[0]['id']}/download")
|
||||
assert archive.status_code==200,archive.text[:300]
|
||||
with zipfile.ZipFile(io.BytesIO(archive.content)) as z:
|
||||
assert 'index.html' in z.namelist()
|
||||
assert 'about/index.html' in z.namelist()
|
||||
assert '<html lang="en"' in z.read('index.html').decode('utf-8')
|
||||
preview=client.get(f"/preview/{sid}/{done[0]['id']}/about/")
|
||||
assert preview.status_code==200 and 'E2E smoke content' in preview.text
|
||||
print('PASS: ready -> login/CSRF -> create site/page -> enqueue -> Worker build -> ZIP -> preview')
|
||||
finally:
|
||||
proc.terminate()
|
||||
try:proc.communicate(timeout=5)
|
||||
except subprocess.TimeoutExpired:proc.kill();proc.communicate()
|
||||
|
||||
if __name__=='__main__':run()
|
||||
Reference in New Issue
Block a user