#!/usr/bin/env python3 """Validate JSON files and CVE identity; nonzero exit status on errors.""" import argparse import json import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] PAT = re.compile(r'CVE-(\d{4})-\d{4,}') def main(): p = argparse.ArgumentParser() p.add_argument('--changed-only', action='store_true', help='Validate files modified in the last Git worktree diff (including staged)') args = p.parse_args() if args.changed_only: import subprocess changed = subprocess.run(['git', 'status', '--porcelain', '-uall'], cwd=ROOT, capture_output=True, text=True, check=True).stdout files = [] for line in changed.splitlines(): if len(line) < 4: continue path = line[3:] if path.startswith('data/') and path.endswith('.json') and (ROOT / path).is_file(): files.append(ROOT / path) else: files = list((ROOT / 'data').glob('*/*.json')) errors = [] for path in files: try: record = json.loads(path.read_text(encoding='utf-8')) identifier = record['id'] match = PAT.fullmatch(identifier) assert match and path.name == identifier + '.json' and path.parent.name == match.group(1) assert isinstance(record.get('published'), str) assert isinstance(record.get('lastModified'), str) assert isinstance(record.get('vulnStatus'), str) except Exception as exc: errors.append(f'{path}: {exc}') for error in errors[:30]: print(error, file=sys.stderr) print(f'Validated {len(files)} files; errors: {len(errors)}') sys.exit(1 if errors else 0) if __name__ == '__main__': main()