#!/usr/bin/env python3 """ Validate a directory of locally-built VPP .deb packages before a Docker build. Checks: - The directory exists - Exactly one *.changes file - Exactly one *.buildinfo file - Exactly one of each required .deb package - All packages carry the same version string - Optionally: version matches an expected value (for cross-machine consistency) Usage: check-vppdebs.py [--print-version] [--assert-version VERSION] [directory] --print-version Print only the detected version string and exit (no other output). --assert-version VER After all checks pass, assert the detected version equals VER. Use this to verify summer and jessica-orb have the same build. directory Path to check (default: ~/src/vpp/build-root). """ import sys import glob import argparse from pathlib import Path REQUIRED_DEBS = [ "libvppinfra_*.deb", "python3-vpp-api_*.deb", "vpp_*.deb", "vpp-crypto-engines_*.deb", "vpp-plugin-core_*.deb", ] def find(directory, pattern): return sorted(glob.glob(str(directory / pattern))) def version_from_deb(path): """Extract the version field from a deb filename: name_VERSION_arch.deb""" return Path(path).stem.split("_")[1] def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("--print-version", action="store_true") parser.add_argument("--assert-version", metavar="VERSION", default=None) parser.add_argument("directory", nargs="?", default="~/src/vpp/build-root") args = parser.parse_args() directory = Path(args.directory).expanduser() errors = [] versions = [] if not args.print_version: print(f"Checking VPP debs in: {directory}") if not directory.is_dir(): print(f" ERROR: directory does not exist: {directory}") sys.exit(1) # *.changes changes = find(directory, "*.changes") if len(changes) == 1: if not args.print_version: print(f" OK changes : {Path(changes[0]).name}") else: errors.append(f"expected exactly 1 *.changes, found {len(changes)}: {[Path(f).name for f in changes]}") # *.buildinfo buildinfo = find(directory, "*.buildinfo") if len(buildinfo) == 1: if not args.print_version: print(f" OK buildinfo : {Path(buildinfo[0]).name}") else: errors.append(f"expected exactly 1 *.buildinfo, found {len(buildinfo)}: {[Path(f).name for f in buildinfo]}") # required debs for pattern in REQUIRED_DEBS: matches = find(directory, pattern) if len(matches) == 1: ver = version_from_deb(matches[0]) versions.append(ver) if not args.print_version: print(f" OK {pattern:<30s}: {Path(matches[0]).name}") else: errors.append(f"expected exactly 1 {pattern}, found {len(matches)}: {[Path(f).name for f in matches]}") # version consistency within this directory if versions and len(set(versions)) > 1: errors.append(f"debs carry mixed versions: {sorted(set(versions))}") if errors: if not args.print_version: print() for e in errors: print(f" ERROR: {e}") sys.exit(1) detected = versions[0] if versions else None if args.print_version: print(detected or "") sys.exit(0) print(f" OK version : {detected}") # cross-machine version assertion if args.assert_version: if detected == args.assert_version: print(f" OK matches summer : {detected}") else: print(f" ERROR: version mismatch: this machine={detected}, summer={args.assert_version}") sys.exit(1) print() print("Preflight OK.") if __name__ == "__main__": main()