mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-11-11 14:47:39 +00:00
67 lines
3.6 KiB
Python
67 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Verify actual Linux release archives before uploading them as release assets."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import struct
|
|
import subprocess
|
|
import tempfile
|
|
|
|
|
|
def field(package, name):
|
|
return subprocess.check_output(["dpkg-deb", "-f", str(package), name], text=True).strip()
|
|
|
|
|
|
def verify(directory, version, device):
|
|
name, arch, runtime, binary, machine = (
|
|
("trailmate-cardputer-zero", "arm64", "linux-arm64", "usr/lib/trailmate-cardputer-zero/trailmate-cardputer-zero-fbdev", 183)
|
|
if device == "cardputer-zero" else
|
|
("trailmate-cm0", "armhf", "linux-arm", "usr/bin/trailmate-linux", 40))
|
|
packages = [p for p in directory.rglob("*.deb") if field(p, "Package") == name]
|
|
if len(packages) != 1:
|
|
raise RuntimeError(f"Expected one {name} archive, found {len(packages)}")
|
|
package = packages[0]
|
|
assert field(package, "Architecture") == arch, "Incorrect target architecture"
|
|
assert field(package, "Version") == version, "Package version differs from release"
|
|
depends = field(package, "Depends")
|
|
assert "osmium-tool" in depends and "libicu" in depends, "Missing online-map dependencies"
|
|
with tempfile.TemporaryDirectory(prefix="trailmate-release-verify-") as temporary:
|
|
root = Path(temporary)
|
|
subprocess.run(["dpkg-deb", "-x", str(package), str(root)], check=True)
|
|
executable = root / binary
|
|
header = executable.read_bytes()[:20]
|
|
assert header[:4] == b"\x7fELF" and struct.unpack_from("<H", header, 18)[0] == machine, "Incorrect ELF architecture"
|
|
assert executable.stat().st_mode & 0o111, "Application is not executable"
|
|
if device == "t-display-cm0":
|
|
font = root / "usr/share/trailmate/packs/fonts/ja-broadcast-cjk"
|
|
assert (font / "font.bin").stat().st_size > 0, "Missing broadcast content font"
|
|
assert (font / "LICENSE-Noto.txt").is_file() and (font / "LICENSE-NotoMath.txt").is_file()
|
|
producer = root / "usr/lib/trailmate/tmap-producer"
|
|
manifest = json.loads((producer / "producer-manifest.json").read_text(encoding="utf-8-sig"))
|
|
assert manifest["runtime"] == runtime
|
|
assert manifest["sourceRevision"] == "efa12462a526aabad7212cbadfa537ace0b7dbd6"
|
|
assert (producer / "Center-LICENSE").is_file()
|
|
assert (producer / "TmapTool").stat().st_mode & 0o111
|
|
for entry in manifest["files"]:
|
|
if entry["name"].endswith(".pdb"):
|
|
continue
|
|
assert Path(entry["name"]).name == entry["name"], "Invalid producer manifest path"
|
|
assert hashlib.sha256((producer / entry["name"]).read_bytes()).hexdigest() == entry["sha256"], entry["name"]
|
|
if device == "t-display-cm0":
|
|
assert "trailmate-oneseg-backend" in depends, "Missing native 1seg backend dependency"
|
|
backends = [p for p in directory.rglob("*.deb") if field(p, "Package") == "trailmate-oneseg-backend"]
|
|
assert len(backends) == 1 and field(backends[0], "Architecture") == "armhf"
|
|
provides = field(backends[0], "Provides")
|
|
assert "trailmate-oneseg-backend-cm0-abi-v1" in provides and "trailmate-oneseg-backend-auto-v1" in provides
|
|
print(f"Validated {package.name}: version, ELF, dependencies and pinned producer hashes")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--directory", type=Path, required=True)
|
|
parser.add_argument("--version", required=True)
|
|
parser.add_argument("--device", choices=("cardputer-zero", "t-display-cm0"), required=True)
|
|
args = parser.parse_args()
|
|
verify(args.directory, args.version, args.device)
|