Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,102 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MPL-2.0
"""Check the ARM64 reference in a private mount namespace, without starting services."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import subprocess
import sys
from urllib.parse import quote
def run(*args, check=True):
result = subprocess.run(args, check=False, capture_output=True, text=True, timeout=45)
if check and result.returncode:
raise RuntimeError(f'{args}: {result.stderr.strip()}')
return result
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--root', type=Path, required=True)
parser.add_argument('--product', type=Path, required=True)
parser.add_argument('--inside-namespace', action='store_true', help=argparse.SUPPRESS)
args = parser.parse_args()
if os.geteuid() != 0:
parser.error('chroot and the private mount namespace require administrator privileges')
root, product = args.root.resolve(), args.product.resolve()
base = Path('/home/droidian/vulpes-tundra-tests')
for path in (root, product):
if not path.is_relative_to(base) or path == base:
parser.error('Expected isolated device trial directories')
if not (root.parent/(root.name+'-stage.json')).is_file():
parser.error('Staging report missing')
if not args.inside_namespace:
result = subprocess.run(['unshare', '--mount', '--net', '--fork', sys.executable,
str(Path(__file__).resolve()), '--inside-namespace', '--root', str(root),
'--product', str(product)], check=False)
raise SystemExit(result.returncode)
if os.readlink('/proc/self/ns/mnt') == os.readlink('/proc/1/ns/mnt'):
parser.error('Refusing to mount in the system namespace')
run('mount', '--make-rprivate', '/')
run('mount', '--bind', str(product), str(root/'opt/vulpes'))
run('mount', '-o', 'remount,bind,ro', str(root/'opt/vulpes'))
run('mount', '-t', 'proc', 'proc', str(root/'proc'))
for name in ('null', 'urandom', 'random'):
(root/'dev'/name).touch(exist_ok=True)
run('mount', '--bind', '/dev/'+name, str(root/'dev'/name))
for name in ('run', 'tmp'):
run('mount', '-t', 'tmpfs', '-o', 'mode=1777,size=128m', 'tmpfs', str(root/name))
os.chown(root/'home/vulpes', 1000, 1000)
profile = root/'home/vulpes/render-profile'
profile.mkdir(exist_ok=True)
os.chown(profile, 1000, 1000)
(root/'home/vulpes/render.png').unlink(missing_ok=True)
run('chroot', str(root), '/sbin/ldconfig')
compiler = '/usr/lib/aarch64-linux-gnu/glib-2.0/glib-compile-schemas'
run('chroot', str(root), compiler, '/usr/share/glib-2.0/schemas')
engine = json.loads((product/'engine-lock.json').read_text())['version']
binary = f'/opt/vulpes/engines/{engine}/firefox/firefox'
commands = {
'python': ['/usr/bin/python3', '-c', 'import platform,ssl,json; print(json.dumps({"machine":platform.machine(),"python":platform.python_version(),"ssl":ssl.OPENSSL_VERSION}))'],
'compositor': ['/usr/bin/phoc', '--version'],
'gecko': [binary, '--headless', '--version'],
'geckoRendering': [binary, '--headless', '--no-remote',
'--profile', '/home/vulpes/render-profile', '--window-size', '360,740',
'--screenshot', '/home/vulpes/render.png',
'data:text/html,'+quote('<!doctype html><meta charset="utf-8"><title>Tundra runtime check</title><body style="background:#123456;color:white">Gecko runtime qualification</body>')],
'geckoLibraries': ['/usr/bin/ldd', binary],
'compositorLibraries': ['/usr/bin/ldd', '/usr/bin/phoc'],
}
results = {}
for name, command in commands.items():
result = run('chroot', '--userspec=1000:1000', str(root), '/usr/bin/env', '-i',
'HOME=/home/vulpes', 'PATH=/usr/bin:/bin:/usr/sbin:/sbin',
'LANG=C', *command, check=False)
results[name] = {'command': command, 'returncode': result.returncode,
'stdout': result.stdout, 'stderr': result.stderr}
report = {'scope': 'Offline non-root chroot programs; not a boot, HAL or graphical qualification',
'engine': engine, 'uid': 1000, 'commands': results, 'sandboxQualified': False,
'passed': all(r['returncode'] == 0 and 'not found' not in r['stdout']
for r in results.values())}
screenshot = root/'home/vulpes/render.png'
if screenshot.is_file():
data = screenshot.read_bytes()
report['render'] = {'sha256': hashlib.sha256(data).hexdigest(),
'width': int.from_bytes(data[16:20], 'big'),
'height': int.from_bytes(data[20:24], 'big')}
report['passed'] &= (data.startswith(b'\x89PNG\r\n\x1a\n') and
report['render']['width'] == 360 and report['render']['height'] == 740)
else:
report['passed'] = False
path = root.parent/'chroot-check.json'
path.write_text(json.dumps(report, indent=2)+'\n')
print(json.dumps(report, indent=2), flush=True)
if not report['passed']:
raise SystemExit(1)
if __name__ == '__main__':
main()