#!/usr/bin/env python3 """Freeze a complete passing build; keep earlier version evidence separate.""" import argparse from datetime import datetime, timezone import hashlib import json from pathlib import Path import platform import re import subprocess import xml.etree.ElementTree as ET def sha(path): with path.open('rb') as stream: return hashlib.file_digest(stream, 'sha256').hexdigest() def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--source', type=Path, default=Path(__file__).resolve().parents[2]) parser.add_argument('--build', type=Path, required=True) parser.add_argument('--ctest', type=Path, required=True) parser.add_argument('--installed', type=Path) parser.add_argument('--output', type=Path, required=True) args = parser.parse_args() cases = ET.parse(args.ctest / 'tests.xml').findall('.//testcase') assert len(cases) == 22 and all(c.find('failure') is None and c.find('skipped') is None for c in cases) files = [args.source / name for name in ('CMakeLists.txt', 'resources.qrc')] for folder in ('src', 'qml', 'cmake', 'resources', 'tools', 'tests'): files += [path for path in (args.source / folder).rglob('*') if path.is_file() and not path.is_symlink() and '__pycache__' not in path.parts and 'results' not in path.parts and 'fixtures' not in path.parts] names = ['docview', 'docview-pdf-worker', 'docview-archive-worker', 'test_app', 'test_core', 'test_pdf', 'test_pdf_canvas', 'test_web_qml', 'test_translations'] value = { 'recordedAtUtc': datetime.now(timezone.utc).isoformat(), 'scope': 'Full CTest after URL representation fix; Xvfb/xcb, software rendering, internal sandboxes enabled', 'os': platform.freedesktop_os_release(), 'kernel': platform.release(), 'compiler': subprocess.check_output(['c++', '--version'], text=True).splitlines()[0], 'binaries': {name: sha(args.build / name) for name in names}, 'sourceSha256': {str(path.relative_to(args.source)): sha(path) for path in sorted(set(files))}, 'ctest': {'groups': len(cases), 'failures': 0, 'junitSha256': sha(args.ctest / 'tests.xml'), 'logSha256': sha(args.ctest / 'LastTest.log'), 'cases': [case.attrib for case in cases]}, 'qtTestTotalsIncludingSetupAndCleanup': re.findall(r'Totals: .*', (args.ctest / 'LastTest.log').read_text()), 'runnerSha256': sha(Path(__file__)), } if args.installed: value['installedBinaries'] = {name: sha(args.installed / 'bin' / name) for name in names[:3]} with args.output.open('x') as stream: stream.write(json.dumps(value, ensure_ascii=False, indent=2) + '\n') print(json.dumps({'ctestGroups': len(cases), 'docviewSha256': value['binaries']['docview']})) if __name__ == '__main__': main()