127 lines
7.9 KiB
Python
127 lines
7.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Build/package the pinned v2 candidate only in the dedicated Ubuntu guest.
|
|
|
|
Input transfer is recorded separately. Existing source/build/install/provider
|
|
prefixes and earlier evidence are preserved. This does not stop the VM.
|
|
"""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
HOME = Path('/home/docview')
|
|
PREFIX = HOME / 'validation/pdfium-context-prefix'
|
|
BUILD = HOME / 'docview-context-build'
|
|
INSTALL = HOME / 'docview-context-install'
|
|
RESULTS = HOME / 'validation/pdfium-context-package'
|
|
VERSION = '0.1.0~validation4'
|
|
|
|
|
|
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('--phase', choices=('build', 'package', 'smoke'), required=True)
|
|
parser.add_argument('--run-name', required=True)
|
|
args = parser.parse_args()
|
|
assert os.getuid() != 0 and Path.home() == HOME and ROOT == HOME / 'docview-context-source'
|
|
assert re.fullmatch('[a-z0-9-]{1,64}', args.run_name)
|
|
output = RESULTS / args.run_name; output.mkdir(parents=True, exist_ok=False)
|
|
env = {**os.environ, 'PATH': '/opt/docview-deps/bin:/opt/docview-qt/6.11.2/gcc_64/bin:' + os.environ['PATH'],
|
|
'PKG_CONFIG_PATH': '/opt/docview-deps/lib/pkgconfig',
|
|
'LD_LIBRARY_PATH': '/opt/docview-deps/lib:/opt/docview-qt/6.11.2/gcc_64/lib',
|
|
'QT_QPA_PLATFORM': 'xcb', 'QT_QUICK_BACKEND': 'software',
|
|
'QTWEBENGINE_CHROMIUM_FLAGS': '--disable-gpu', 'QT_SCALE_FACTOR': '1',
|
|
'QT_AUTO_SCREEN_SCALE_FACTOR': '0', 'XDG_SESSION_TYPE': 'x11'}
|
|
for key in ('LD_PRELOAD', 'LD_AUDIT', 'QTWEBENGINE_DISABLE_SANDBOX', 'WAYLAND_DISPLAY'):
|
|
assert not env.get(key), key
|
|
preserved = [HOME / 'docview-source/.deps/pdfium/lib/libpdfium.so', HOME / 'docview-build/docview',
|
|
HOME / 'docview-build/docview-pdf-worker', HOME / 'docview-install/bin/docview']
|
|
before = {str(path): sha(path) for path in preserved}
|
|
report = {'success': False, 'phase': args.phase, 'commands': [], 'runnerSha256': sha(Path(__file__)),
|
|
'providerAndOriginalBuildBefore': before, 'scope': 'Local Ubuntu candidate integration only; no public release or complete Chromium notice claim'}
|
|
|
|
def run(label, command, timeout=1800, environment=env):
|
|
start = time.monotonic(); log = output / (label + '.log')
|
|
print('Starting', label, flush=True)
|
|
with log.open('w') as stream:
|
|
result = subprocess.run(command, cwd=ROOT, env=environment, stdout=stream, stderr=subprocess.STDOUT, timeout=timeout)
|
|
report['commands'].append({'name': label, 'command': list(map(str, command)), 'exitCode': result.returncode,
|
|
'seconds': time.monotonic() - start, 'logSha256': sha(log)})
|
|
print('Finished', label, result.returncode, flush=True)
|
|
assert result.returncode == 0, label + ' failed; inspect ' + str(log)
|
|
|
|
try:
|
|
sys.path.insert(0, str(ROOT / 'tools'))
|
|
from verify_pdfium_candidate import verify_prefix, verify_installed
|
|
report['candidatePrefix'], _ = verify_prefix(PREFIX, PREFIX / 'lib/libpdfium.so', PREFIX / 'include')
|
|
if args.phase == 'build':
|
|
run('configure', ['cmake', '-S', str(ROOT), '-B', str(BUILD), '-G', 'Ninja', '-DCMAKE_BUILD_TYPE=Release',
|
|
'-DCMAKE_PREFIX_PATH=/opt/docview-qt/6.11.2/gcc_64;/opt/docview-deps',
|
|
'-DDOCVIEW_PDFIUM_ROOT=' + str(PREFIX)])
|
|
run('build', ['cmake', '--build', str(BUILD), '--parallel', '4'])
|
|
run('candidate-integration-tests', [sys.executable, str(ROOT / 'tests/test_pdfium_candidate_integration.py'), '-v'])
|
|
run('ctest', ['dbus-run-session', '--', 'xvfb-run', '-a', '-s', '-screen 0 1920x1080x24',
|
|
'ctest', '--test-dir', str(BUILD), '--output-on-failure', '--output-junit', str(output / 'tests.xml')])
|
|
shutil.copyfile(BUILD / 'Testing/Temporary/LastTest.log', output / 'LastTest.log')
|
|
run('install', ['cmake', '--install', str(BUILD), '--prefix', str(INSTALL)])
|
|
report['installedCandidate'] = verify_installed(INSTALL)
|
|
report['binaries'] = {name: sha(BUILD / name) for name in ('docview', 'docview-pdf-worker', 'docview-archive-worker')}
|
|
elif args.phase == 'package':
|
|
package_command = [sys.executable, str(ROOT / 'tools/package_ubuntu.py'), '--prefix', str(INSTALL),
|
|
'--qtpaths', '/opt/docview-qt/6.11.2/gcc_64/bin/qtpaths', '--dependency-prefix', '/opt/docview-deps',
|
|
'--source-root', str(HOME / 'dependency-sources/qpdf-12.4.1'),
|
|
'--source-root', str(HOME / 'dependency-sources/libzip-1.11.4'),
|
|
'--input-manifest', str(HOME / 'incoming/sdk-downloads.json'),
|
|
'--sdk-notices', str(ROOT / 'tests/results/source-archives/qt-sdk-notices-final'),
|
|
'--sdk-supplement', str(ROOT / 'tests/results/qt-notice-supplement/collection'),
|
|
'--qt-licenses', str(ROOT / 'tests/results/ubuntu-package/inputs/qt-licenses'), '--version', VERSION]
|
|
for name in ('package', 'repeat'):
|
|
destination = output / name
|
|
run(name, [*package_command, '--output', str(destination)])
|
|
run(name + '-verify', [sys.executable, str(ROOT / 'tools/verify_ubuntu_package.py'), '--archive',
|
|
str(destination / ('docview_' + VERSION + '_amd64.deb')), '--output', str(destination / 'verification.json')])
|
|
archive = 'docview_' + VERSION + '_amd64.deb'
|
|
report['archiveSha256'] = sha(output / 'package' / archive)
|
|
report['repeatSha256'] = sha(output / 'repeat' / archive)
|
|
assert report['archiveSha256'] == report['repeatSha256']
|
|
report['archive'] = str(output / 'package' / archive)
|
|
else:
|
|
package = json.loads((RESULTS / 'package/report.json').read_text())
|
|
assert package['success'] and sha(Path(package['archive'])) == package['archiveSha256']
|
|
run('apt-install', ['sudo', 'env', 'DEBIAN_FRONTEND=noninteractive', 'apt-get', '-y',
|
|
'--no-install-recommends', 'install', package['archive']])
|
|
report['installedCandidate'] = verify_installed(Path('/opt/docview'))
|
|
run('installed-smoke', [sys.executable, str(ROOT / 'tests/ubuntu_vm/package_smoke.py'),
|
|
'--output', str(output / 'installed-smoke'), '--hide-prefix', str(BUILD), '--hide-prefix', str(INSTALL),
|
|
'--hide-prefix', str(PREFIX), '--hide-prefix', str(HOME / 'validation/pdfium-intent-context')],
|
|
environment={key: value for key, value in os.environ.items() if key not in (
|
|
'LD_LIBRARY_PATH', 'QT_PLUGIN_PATH', 'QT_QPA_PLATFORM_PLUGIN_PATH', 'QML_IMPORT_PATH',
|
|
'QML2_IMPORT_PATH', 'QTWEBENGINEPROCESS_PATH', 'QTWEBENGINE_DISABLE_SANDBOX')})
|
|
run('lifecycle', [sys.executable, str(ROOT / 'tests/ubuntu_vm/package_lifecycle.py'), '--smoke',
|
|
str(output / 'installed-smoke'), '--output', str(output / 'lifecycle')])
|
|
report['packagePurged'] = not Path('/opt/docview').exists() and not Path('/etc/apparmor.d/docview').exists()
|
|
assert report['packagePurged']
|
|
after = {str(path): sha(path) for path in preserved}
|
|
report['providerAndOriginalBuildAfter'] = after
|
|
assert before == after
|
|
report['originalsUnchanged'] = report['success'] = True
|
|
finally:
|
|
report['evidenceSha256'] = {str(path.relative_to(output)): sha(path)
|
|
for path in sorted(output.rglob('*')) if path.is_file() and path.suffix != '.deb'}
|
|
(output / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
|
|
print(json.dumps({'phase': args.phase, 'success': report['success']}))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|