#!/usr/bin/env python3 """Verify local code, tests, databases and Docker without calling an external LLM.""" from __future__ import annotations import argparse import ast import ipaddress import json import os from pathlib import Path import re import shlex import socket import sqlite3 import subprocess import sys import time import urllib.request ROOT = Path(__file__).resolve().parents[1] def local_test_worker() -> int: """Allow live local API/Neo4j tests, forbid outbound model calls.""" os.environ.pop('OPENWEBUI_API_KEY', None) for line in (ROOT / '.env').read_text().splitlines(): key, separator, value = line.partition('=') if separator and key in {'NEO4J_URI', 'NEO4J_USER', 'NEO4J_PASSWORD', 'NEO4J_DATABASE'}: values = shlex.split(value) if values: os.environ[key] = values[0] for key in ['RUN_NEO4J_TESTS', 'RUN_LIVE_TESTS', 'RUN_LIVE_RAG_E2E', 'HF_HUB_OFFLINE', 'TRANSFORMERS_OFFLINE']: os.environ[key] = '1' original_connect, original_connect_ex = socket.socket.connect, socket.socket.connect_ex original_dns = socket.getaddrinfo def permitted(address): try: return address[1] in {7687, 8000} and ipaddress.ip_address(address[0]).is_loopback except (ValueError, TypeError, IndexError): return False def guarded_connect(self, address): if self.family in {socket.AF_INET, socket.AF_INET6} and not permitted(address): raise RuntimeError('External network disabled during local verification') return original_connect(self, address) def guarded_connect_ex(self, address): if self.family in {socket.AF_INET, socket.AF_INET6} and not permitted(address): raise RuntimeError('External network disabled during local verification') return original_connect_ex(self, address) def guarded_dns(host, port, *args, **kwargs): if host not in {'localhost', '127.0.0.1', '::1'} or int(port) not in {7687, 8000}: raise RuntimeError('External DNS disabled during local verification') return original_dns(host, port, *args, **kwargs) socket.socket.connect, socket.socket.connect_ex = guarded_connect, guarded_connect_ex socket.getaddrinfo = guarded_dns import pytest return pytest.main(['-q', 'test', 'tools/rag/tests', 'tools/graphrag/tests']) def verify_code() -> dict: files = [path for name in ['app', 'tools', 'test', 'scripts'] for path in (ROOT / name).rglob('*.py')] for path in files: text = path.read_text() compile(text, str(path), 'exec') for node in ast.walk(ast.parse(text)): modules = ([node.module] if isinstance(node, ast.ImportFrom) and node.module else [item.name for item in node.names] if isinstance(node, ast.Import) else []) for module in modules: if module.split('.')[0] in {'tools', 'app'}: target = ROOT.joinpath(*module.split('.')) if not target.with_suffix('.py').is_file() and not (target / '__init__.py').is_file(): raise RuntimeError(f'Unresolved internal module {module} in {path.relative_to(ROOT)}') shells = [path for name in ['scripts', 'tools'] for path in (ROOT / name).rglob('*.sh')] for path in shells: subprocess.run(['bash', '-n', str(path)], check=True) return {'compiled_python_files': len(files), 'checked_shell_scripts': len(shells)} def verify_database() -> dict: path = ROOT / 'data/zp_index.sqlite' with sqlite3.connect(path.resolve().as_uri() + '?mode=ro', uri=True) as conn: assert conn.execute('PRAGMA quick_check').fetchone()[0] == 'ok', 'SQLite integrity failed' assert not conn.execute('PRAGMA foreign_key_check').fetchall(), 'SQLite foreign keys failed' counts = {table: conn.execute(f'SELECT count(*) FROM {table}').fetchone()[0] for table in ['documents', 'chunks', 'chunks_fts', 'chunk_embeddings']} assert counts['chunks'] == counts['chunks_fts'] and counts['chunks'] > 0, 'FTS count mismatch' return counts def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--docker-context', default='default') parser.add_argument('--git-network', action='store_true', help='Read-only probe of wiki origin over its configured SSH connection') parser.add_argument('--output', type=Path, default=ROOT / 'data/project_verification.json') parser.add_argument('--test-worker', action='store_true', help=argparse.SUPPRESS) args = parser.parse_args() os.chdir(ROOT) sys.path.insert(0, str(ROOT)) if args.test_worker: return local_test_worker() report = {'checks': {}, 'external_llm_calls': False} args.output.parent.mkdir(parents=True, exist_ok=True) def check(name, action): started = time.monotonic() try: result = action() record = {'passed': True, 'details': result} except Exception as error: record = {'passed': False, 'error_type': type(error).__name__} record['seconds'] = round(time.monotonic() - started, 2) report['checks'][name] = record args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n') print(f'{name}: {"OK" if record["passed"] else "FAILED"}', flush=True) def command(*argv): result = subprocess.run(argv, text=True, capture_output=True, timeout=90) if result.returncode: raise RuntimeError('Verification command failed; inspect the service locally') return result.stdout.strip() docker = ['docker', '--context', args.docker_context] compose = [*docker, 'compose', '--project-directory', str(ROOT)] check('python_and_shell', verify_code) check('git_diff', lambda: command('git', 'diff', '--check')) check('git_integrity', lambda: command('git', 'fsck', '--connectivity-only')) check('compose_configuration', lambda: command(*compose, 'config', '--quiet')) def health(): with urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=15) as response: value = json.load(response) assert value['ready'] and all(tool['ready'] for tool in value['tools'].values()) assert value['tools']['rag']['index_version'] == value['tools']['graphrag']['index_version'] return {'ready': True, 'index_version': value['index_version'], 'tools': {name: item['ready'] for name, item in value['tools'].items()}} check('api_and_both_indexes', health) check('sqlite_integrity', verify_database) check('container_readiness', lambda: command(*compose, 'exec', '-T', 'zp-agent-api', 'python', '-m', 'tools.runtime.runtime_health')) if args.git_network: probe = ("import os,subprocess; from tools.sync.wiki_git import expected_branch; " "p=subprocess.run(['git','-C',os.environ['ZPWIKI_ROOT'],'ls-remote','--exit-code'," "'origin','refs/heads/'+expected_branch()],capture_output=True,text=True,timeout=60); " "assert p.returncode==0,'Wiki origin unavailable'; print(p.stdout.strip())") check('wiki_git_ssh', lambda: command(*compose, 'exec', '-T', 'zp-agent-api', 'python', '-c', probe)) def tests(): log = args.output.with_suffix('.pytest.log') environment = {**os.environ} environment.pop('OPENWEBUI_API_KEY', None) with log.open('w') as output: result = subprocess.run([sys.executable, str(Path(__file__).resolve()), '--test-worker'], env=environment, stdout=output, stderr=subprocess.STDOUT, timeout=900) assert result.returncode == 0, 'Regression failed; see local pytest log' text = log.read_text() counts = {name: int(value) for value, name in re.findall(r'(\d+) (passed|failed|skipped)', text)} assert counts.get('passed', 0) > 0 and counts.get('skipped', 0) == 0 return {**counts, 'log': str(log), 'external_network_blocked': True} check('full_local_regression', tests) report['passed'] = all(item['passed'] for item in report['checks'].values()) args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + '\n') print('Report: ' + str(args.output)) return 0 if report['passed'] else 1 if __name__ == '__main__': raise SystemExit(main())