#!/usr/bin/env bash set -Eeuo pipefail umask 077 # ================================================== # Configuration # ================================================== : "${CACHE_ROOT:=/vuln-cache/vuln-builder}" SOURCES_DIR="${SOURCES_DIR:-$CACHE_ROOT/sources}" SOURCES_CONFIG="${SOURCES_CONFIG:-$CACHE_ROOT/sources.json}" SOURCE_MANIFEST="$CACHE_ROOT/source-manifest.json" RELEASE_DIR="$CACHE_ROOT/releases" # ================================================== # Create directories # ================================================== mkdir -p "$CACHE_ROOT" "$SOURCES_DIR" "$RELEASE_DIR" # ================================================== # Prevent concurrent builds # ================================================== exec 9>"$CACHE_ROOT/.build.lock" /usr/bin/flock -w 1800 9 || { echo "ERROR: Another builder run is active" >&2 exit 1 } # ================================================== # Validate configuration # ================================================== echo "========================================" echo "Vulnerability SQLite Builder" echo "========================================" if [ ! -s "$SOURCES_CONFIG" ]; then echo "ERROR: sources.json missing: $SOURCES_CONFIG" >&2 exit 1 fi if [ ! -s "$SOURCE_MANIFEST" ]; then echo "ERROR: Source manifest missing" >&2 exit 1 fi if [ ! -d "$SOURCES_DIR" ]; then echo "ERROR: Source directory missing" >&2 exit 1 fi # Verify that all sources listed in the manifest # exist as local Git repositories. python3 - "$SOURCE_MANIFEST" "$SOURCES_DIR" <<'PY' import json import subprocess import sys from pathlib import Path manifest_path = Path(sys.argv[1]) sources_dir = Path(sys.argv[2]) entries = json.loads( manifest_path.read_text(encoding="utf-8") ) if not isinstance(entries, list) or not entries: raise SystemExit("ERROR: Empty source manifest") for entry in entries: name = entry["repo"] expected = entry["commit"] repo = sources_dir / name if not (repo / ".git").is_dir(): raise SystemExit(f"ERROR: Missing repository {name}") actual = subprocess.check_output( ["git", "-C", str(repo), "rev-parse", "HEAD"], text=True ).strip() if actual != expected: raise SystemExit( f"ERROR: Commit mismatch in {name}: " f"{actual} != {expected}" ) print(f"OK {name}: {actual[:12]}", flush=True) print(f"Validated {len(entries)} repositories") PY # ================================================== # Build SQLite # ================================================== cd "$(dirname "$0")/.." echo "Starting SQLite build..." python3 scripts/build.py \ --sources "$SOURCES_DIR" \ --output "$RELEASE_DIR" # ================================================== # Verify release files # ================================================== echo "Checking build results..." if [ ! -s "$RELEASE_DIR/master.db.zst" ]; then echo "ERROR: master.db.zst missing or empty" >&2 exit 1 fi if [ ! -s "$RELEASE_DIR/manifest.json" ]; then echo "ERROR: Release manifest missing" >&2 exit 1 fi # ================================================== # Show results # ================================================== echo "========================================" echo "Build completed" echo "========================================" ls -lh \ "$RELEASE_DIR/master.db.zst" \ "$RELEASE_DIR/manifest.json" find "$RELEASE_DIR" \ -maxdepth 1 \ -name 'delta-*.zst' \ -printf '%f %s bytes\n' echo "SQLite build finished successfully"