Fiw-Gentoo-Dots/tools/ci/check.py
fi3w0 ca8c5de013
Some checks are pending
Check and mirror to GitHub / checks (push) Waiting to run
Check and mirror to GitHub / github-mirror (push) Blocked by required conditions
Add Forgejo CI and GitHub mirroring after checks
2026-10-03 23:28:26 +02:00

65 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Check portable code and the shipped assets without applying the installer."""
import gzip
import hashlib
import importlib.util
import io
import json
import subprocess
from pathlib import Path
REPO = Path(__file__).resolve().parents[2]
def sha(data):
return hashlib.sha256(data).hexdigest()
def check_assets():
spec = importlib.util.spec_from_file_location('launcher', REPO / 'lib/launcher.py')
launcher = importlib.util.module_from_spec(spec)
spec.loader.exec_module(launcher)
root = REPO / 'assets/bin'
metadata = json.loads((root / 'tui.json').read_text())
if metadata['version'] != (REPO / 'VERSION').read_text().strip():
raise RuntimeError('TUI version does not match VERSION; rebuild the release bundle.')
if metadata['source_sha256'] != launcher.source_hash(REPO):
raise RuntimeError('TUI source changed; rebuild the release bundle.')
for binary in metadata['binaries'].values():
path = root / binary['file']
if path.parent.resolve() != root.resolve():
raise RuntimeError('Invalid TUI archive path.')
compressed = path.read_bytes()
if sha(compressed) != binary['gzip_sha256']:
raise RuntimeError('TUI archive checksum mismatch.')
size = binary['size']
if not isinstance(size, int) or not 0 < size <= 64 * 1024 * 1024:
raise RuntimeError('Invalid TUI size.')
with gzip.GzipFile(fileobj=io.BytesIO(compressed)) as stream:
executable = stream.read(size + 1)
if len(executable) != size or sha(executable) != binary['sha256']:
raise RuntimeError('TUI executable checksum mismatch.')
line = binary['gzip_sha256'] + ' ' + binary['file']
if line not in (root / 'SHA256SUMS').read_text().splitlines():
raise RuntimeError('SHA256SUMS does not match the TUI archive.')
for name, entry in json.loads((REPO / 'assets/editor-themes.json').read_text()).items():
directory = REPO / entry['root']
if not directory.resolve().is_relative_to(REPO):
raise RuntimeError('Invalid editor asset directory.')
actual = {path.relative_to(directory).as_posix(): sha(path.read_bytes())
for path in sorted(directory.rglob('*')) if path.is_file()}
if actual != entry['sha256']:
raise RuntimeError('Editor asset fingerprints changed: ' + name)
print('Prebuilt TUI and editor asset fingerprints match.', flush=True)
def main():
subprocess.run(['python3', 'tools/check-private.py'], cwd=REPO, check=True)
check_assets()
subprocess.run(['python3', '-m', 'unittest', 'discover', '-s', 'tests'], cwd=REPO, check=True)
subprocess.run(['go', 'test', './...'], cwd=REPO, check=True)
print('Portable CI checks passed; no installer actions were applied.', flush=True)
if __name__ == '__main__':
main()