Some checks failed
LNM Migration CI / build-runner (push) Has been cancelled
Ledger OpenAPI CI / deprecation-check (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Airgap Sealed CI Smoke / sealed-smoke (push) Has been cancelled
Ledger Packs CI / build-pack (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Ledger OpenAPI CI / validate-oas (push) Has been cancelled
Ledger OpenAPI CI / check-wellknown (push) Has been cancelled
Ledger Packs CI / verify-pack (push) Has been cancelled
LNM Migration CI / validate-metrics (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
330 lines
9.4 KiB
Bash
330 lines
9.4 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# validate-paths.sh - Validates offline kit path structure
|
|
#
|
|
# Usage: ./validate-paths.sh [--combined] [kit_directory]
|
|
#
|
|
# Options:
|
|
# --combined Expect combined runtime format (combined.runtime.ndjson)
|
|
# kit_directory Path to kit directory (default: parent of this script)
|
|
#
|
|
# Exit codes:
|
|
# 0 - All validations passed
|
|
# 1 - Missing required files or directories
|
|
# 2 - Invalid file format
|
|
# 3 - Usage error
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
COMBINED_FORMAT=false
|
|
KIT_DIR=""
|
|
|
|
# Parse arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--combined)
|
|
COMBINED_FORMAT=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
echo "Usage: $0 [--combined] [kit_directory]"
|
|
echo ""
|
|
echo "Validates offline kit path structure and file formats."
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --combined Expect combined runtime format"
|
|
echo " kit_directory Path to kit directory (default: parent of this script)"
|
|
exit 0
|
|
;;
|
|
-*)
|
|
echo "Unknown option: $1" >&2
|
|
exit 3
|
|
;;
|
|
*)
|
|
KIT_DIR="$1"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Default to parent directory if not specified
|
|
if [[ -z "$KIT_DIR" ]]; then
|
|
KIT_DIR="${SCRIPT_DIR}/.."
|
|
fi
|
|
|
|
# Resolve to absolute path
|
|
KIT_DIR="$(cd "$KIT_DIR" && pwd)"
|
|
|
|
echo "Validating kit at: $KIT_DIR"
|
|
|
|
ERRORS=0
|
|
|
|
# Helper functions
|
|
check_file() {
|
|
local file="$1"
|
|
local required="${2:-true}"
|
|
local path="$KIT_DIR/$file"
|
|
|
|
if [[ -f "$path" ]]; then
|
|
echo " [OK] $file"
|
|
return 0
|
|
elif [[ "$required" == "true" ]]; then
|
|
echo " [MISSING] $file (required)" >&2
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
else
|
|
echo " [SKIP] $file (optional)"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
check_dir() {
|
|
local dir="$1"
|
|
local required="${2:-true}"
|
|
local path="$KIT_DIR/$dir"
|
|
|
|
if [[ -d "$path" ]]; then
|
|
echo " [OK] $dir/"
|
|
return 0
|
|
elif [[ "$required" == "true" ]]; then
|
|
echo " [MISSING] $dir/ (required)" >&2
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
else
|
|
echo " [SKIP] $dir/ (optional)"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
validate_json() {
|
|
local file="$1"
|
|
local path="$KIT_DIR/$file"
|
|
|
|
if [[ ! -f "$path" ]]; then
|
|
return 0 # Skip if file doesn't exist (handled by check_file)
|
|
fi
|
|
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
if python3 -c "import json; json.load(open('$path'))" 2>/dev/null; then
|
|
echo " [VALID JSON] $file"
|
|
return 0
|
|
else
|
|
echo " [INVALID JSON] $file" >&2
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
elif command -v jq >/dev/null 2>&1; then
|
|
if jq empty "$path" 2>/dev/null; then
|
|
echo " [VALID JSON] $file"
|
|
return 0
|
|
else
|
|
echo " [INVALID JSON] $file" >&2
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
else
|
|
echo " [SKIP] $file (no JSON validator available)"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
validate_ndjson() {
|
|
local file="$1"
|
|
local path="$KIT_DIR/$file"
|
|
|
|
if [[ ! -f "$path" ]]; then
|
|
return 0 # Skip if file doesn't exist
|
|
fi
|
|
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
local result
|
|
result=$(python3 -c "
|
|
import json, sys
|
|
path = '$path'
|
|
errors = 0
|
|
with open(path, 'r') as f:
|
|
for i, line in enumerate(f, 1):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
try:
|
|
json.loads(line)
|
|
except json.JSONDecodeError as e:
|
|
print(f'Line {i}: {e}', file=sys.stderr)
|
|
errors += 1
|
|
if errors >= 5:
|
|
print('(truncated after 5 errors)', file=sys.stderr)
|
|
break
|
|
sys.exit(0 if errors == 0 else 1)
|
|
" 2>&1)
|
|
if [[ $? -eq 0 ]]; then
|
|
echo " [VALID NDJSON] $file"
|
|
return 0
|
|
else
|
|
echo " [INVALID NDJSON] $file" >&2
|
|
echo "$result" >&2
|
|
ERRORS=$((ERRORS + 1))
|
|
return 1
|
|
fi
|
|
else
|
|
echo " [SKIP] $file (python3 required for NDJSON validation)"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# =============================================================================
|
|
# Directory Structure Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Checking directory structure ==="
|
|
check_dir "schemas"
|
|
check_dir "exports"
|
|
check_dir "kit"
|
|
|
|
# =============================================================================
|
|
# Core Files Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Checking core files ==="
|
|
check_file "thresholds.yaml"
|
|
check_file "thresholds.yaml.dsse"
|
|
check_file "SHA256SUMS"
|
|
|
|
# =============================================================================
|
|
# Schema Files Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Checking schema files ==="
|
|
check_file "schemas/observer_event.schema.json"
|
|
check_file "schemas/observer_event.schema.json.dsse"
|
|
check_file "schemas/webhook_admission.schema.json"
|
|
check_file "schemas/webhook_admission.schema.json.dsse"
|
|
|
|
# =============================================================================
|
|
# Kit Files Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Checking kit files ==="
|
|
check_file "kit/ed25519.pub"
|
|
check_file "kit/verify.sh"
|
|
check_file "kit/zastava-kit.tzst" false # Optional - may not be in source tree
|
|
check_file "kit/zastava-kit.tzst.dsse" false
|
|
|
|
# =============================================================================
|
|
# Export Files Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Checking export files ==="
|
|
|
|
if [[ "$COMBINED_FORMAT" == "true" ]]; then
|
|
# Combined format
|
|
echo "(Combined format mode)"
|
|
check_file "exports/combined.runtime.ndjson"
|
|
check_file "exports/combined.runtime.ndjson.dsse"
|
|
# Legacy files are optional in combined mode
|
|
check_file "exports/observer_events.ndjson" false
|
|
check_file "exports/webhook_admissions.ndjson" false
|
|
else
|
|
# Legacy format
|
|
echo "(Legacy format mode)"
|
|
check_file "exports/observer_events.ndjson"
|
|
check_file "exports/observer_events.ndjson.dsse"
|
|
check_file "exports/webhook_admissions.ndjson"
|
|
check_file "exports/webhook_admissions.ndjson.dsse"
|
|
# Combined is optional in legacy mode
|
|
check_file "exports/combined.runtime.ndjson" false
|
|
fi
|
|
|
|
# =============================================================================
|
|
# JSON/NDJSON Format Validation
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Validating file formats ==="
|
|
|
|
validate_json "schemas/observer_event.schema.json"
|
|
validate_json "schemas/webhook_admission.schema.json"
|
|
|
|
if [[ "$COMBINED_FORMAT" == "true" ]] && [[ -f "$KIT_DIR/exports/combined.runtime.ndjson" ]]; then
|
|
validate_ndjson "exports/combined.runtime.ndjson"
|
|
else
|
|
if [[ -f "$KIT_DIR/exports/observer_events.ndjson" ]]; then
|
|
validate_ndjson "exports/observer_events.ndjson"
|
|
fi
|
|
if [[ -f "$KIT_DIR/exports/webhook_admissions.ndjson" ]]; then
|
|
validate_ndjson "exports/webhook_admissions.ndjson"
|
|
fi
|
|
fi
|
|
|
|
# =============================================================================
|
|
# Combined Format Structure Validation
|
|
# =============================================================================
|
|
if [[ "$COMBINED_FORMAT" == "true" ]] && [[ -f "$KIT_DIR/exports/combined.runtime.ndjson" ]]; then
|
|
echo ""
|
|
echo "=== Validating combined format structure ==="
|
|
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
python3 - "$KIT_DIR/exports/combined.runtime.ndjson" <<'PYTHON'
|
|
import json
|
|
import sys
|
|
|
|
path = sys.argv[1]
|
|
errors = []
|
|
has_header = False
|
|
has_footer = False
|
|
record_types = set()
|
|
|
|
with open(path, 'r') as f:
|
|
for i, line in enumerate(f, 1):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
try:
|
|
record = json.loads(line)
|
|
rtype = record.get("type", "unknown")
|
|
record_types.add(rtype)
|
|
|
|
if rtype == "combined.header":
|
|
if has_header:
|
|
errors.append(f"Line {i}: duplicate header")
|
|
has_header = True
|
|
if i != 1:
|
|
errors.append(f"Line {i}: header should be first record")
|
|
elif rtype == "combined.footer":
|
|
has_footer = True
|
|
except json.JSONDecodeError as e:
|
|
errors.append(f"Line {i}: {e}")
|
|
|
|
if not has_header:
|
|
errors.append("Missing combined.header record")
|
|
if not has_footer:
|
|
errors.append("Missing combined.footer record")
|
|
|
|
if errors:
|
|
for e in errors:
|
|
print(f" [ERROR] {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print(f" [OK] Header and footer present")
|
|
print(f" [OK] Record types: {', '.join(sorted(record_types))}")
|
|
PYTHON
|
|
if [[ $? -ne 0 ]]; then
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# =============================================================================
|
|
# Summary
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Validation Summary ==="
|
|
|
|
if [[ $ERRORS -eq 0 ]]; then
|
|
echo "All validations passed!"
|
|
exit 0
|
|
else
|
|
echo "$ERRORS validation error(s) found" >&2
|
|
exit 1
|
|
fi
|