test: guard durable chat deployment packaging
This commit is contained in:
1 parent
550f7c2e91
commit
1a04dab031
2 files changed
+78
-1
No files matched your search
@@ -0,0 +1,77 @@
|
||||
"""Offline source packaging guards; no image build, service or Docker calls."""
|
||||
from html.parser import HTMLParser
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
class AssetReferences(HTMLParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.paths = []
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
attrs = dict(attrs)
|
||||
path = attrs.get('src') if tag == 'script' else attrs.get('href') if tag == 'link' and attrs.get('rel') == 'stylesheet' else None
|
||||
if path and not path.startswith(('http:', 'https:', '//', 'data:')):
|
||||
self.paths.append(path.split('?')[0])
|
||||
|
||||
|
||||
def test_speech_image_packages_coordinator_and_all_entrypoint_assets():
|
||||
dockerfile = (ROOT/'Dockerfile').read_text()
|
||||
for source, destination in (
|
||||
('agent/agent.py', '/opt/voice-agent/agent.py'),
|
||||
('agent/hermes_llm.py', '/opt/voice-agent/hermes_llm.py'),
|
||||
('agent/conversation_llm.py', '/opt/voice-agent/conversation_llm.py'),
|
||||
):
|
||||
assert (ROOT/source).is_file()
|
||||
assert re.search(r'^COPY\s+'+re.escape(source)+r'\s+'+re.escape(destination)+r'\s*$', dockerfile, re.M), source
|
||||
references = AssetReferences()
|
||||
references.feed((ROOT/'web/index.html').read_text())
|
||||
assert {'chat.js', 'features.js', 'hope-themes.css'} <= set(references.paths)
|
||||
for path in references.paths:
|
||||
assert (ROOT/'web'/path).is_file(), path
|
||||
assert re.search(r'^COPY\s+web/'+re.escape(path)+r'\s+/var/www/voice/\s*$', dockerfile, re.M), path
|
||||
assert 'chmod -R a+rX /var/www/voice' in dockerfile
|
||||
assert 'chmod 644 /opt/voice-agent/*.py /opt/voice/*.py' in dockerfile
|
||||
assert '.venv-tests' in (ROOT/'.dockerignore').read_text().splitlines()
|
||||
|
||||
|
||||
def test_control_packages_chat_imports_pdf_and_mounted_private_roots():
|
||||
dockerfile = (ROOT/'control.Dockerfile').read_text()
|
||||
assert re.search(r'^COPY\s+control\s+/app/control\s*$', dockerfile, re.M)
|
||||
assert re.search(r'\bpypdf==6\.\d+\.\d+', dockerfile)
|
||||
for module in ('chat_api', 'chat_store', 'chat_runs', 'chat_features', 'chat_exports'):
|
||||
assert (ROOT/'control'/(module+'.py')).is_file()
|
||||
deploy = (ROOT/'scripts/deploy-unraid.sh').read_text()
|
||||
assert '-e CONTROL_DB_PATH=/var/lib/hope/accounts.sqlite3' in deploy
|
||||
assert '-e HOPE_HERMES_DATA_DIR="$ROOT/hermes"' in deploy
|
||||
assert '-v "$ROOT/accounts:/var/lib/hope"' in deploy
|
||||
assert '-v "$ROOT/hermes:$ROOT/hermes"' in deploy
|
||||
app = (ROOT/'control/app.py').read_text()
|
||||
assert "Path(settings.db_path).absolute().parent / 'chat-features'" in app
|
||||
|
||||
|
||||
def test_nginx_preserves_strict_auth_and_allows_declared_advanced_bodies():
|
||||
nginx = (ROOT/'nginx.conf').read_text()
|
||||
assert re.search(r'client_max_body_size\s+16k;', nginx)
|
||||
for route, limit in ((r'/api/attachments', '20m'), (r'~ ^/api/(artifacts|memory)(/|$)', '1m'), (r'/api/tasks', '64k')):
|
||||
block = re.search(r'location\s+'+re.escape(route)+r'\s*\{([^}]+)\}', nginx)
|
||||
assert block is not None, route
|
||||
assert f'client_max_body_size {limit};' in block[1]
|
||||
assert 'proxy_pass http://127.0.0.1:8092;' in block[1]
|
||||
assert re.search(r'location\s+/internal/\s*\{\s*return 404;', nginx)
|
||||
api = re.search(r'location\s+/api/\s*\{([^}]+)\}', nginx)[1]
|
||||
assert 'proxy_buffering off;' in api and 'proxy_read_timeout 700s;' in api
|
||||
|
||||
|
||||
def test_ci_qualification_gates_images_and_deployment_without_live_conftest():
|
||||
workflow = (ROOT/'.gitea/workflows/rebuild.yml').read_text()
|
||||
assert workflow.index('Qualify offline') < workflow.index('Build images') < workflow.index('Deploy using')
|
||||
assert '--noconftest -p no:cacheprovider' in workflow
|
||||
for name in ('test_chat_packaging.py', 'test_chat_exports.py', 'test_chat_cross_client.py', 'test_chat_security_review.py', 'test_deploy_rollback.py'):
|
||||
assert 'tests/unit/'+name in workflow
|
||||
assert 'pytest-asyncio -r control/requirements.txt' in workflow
|
||||
assert 'scripts/generate_hope_themes.py --check' in workflow
|
||||
assert '-v "$PWD:/src:ro"' in workflow
|
||||
Reference in new issue
Block a user