sprints work
This commit is contained in:
244
scripts/validate-sbom.sh
Normal file
244
scripts/validate-sbom.sh
Normal file
@@ -0,0 +1,244 @@
|
||||
#!/bin/bash
|
||||
# scripts/validate-sbom.sh
|
||||
# Sprint: SPRINT_8200_0001_0003 - SBOM Schema Validation in CI
|
||||
# Task: SCHEMA-8200-004 - Create validate-sbom.sh wrapper for sbom-utility
|
||||
#
|
||||
# Validates SBOM files against official CycloneDX JSON schemas.
|
||||
# Uses sbom-utility for CycloneDX validation.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/validate-sbom.sh <sbom-file> [--schema <schema-path>]
|
||||
# ./scripts/validate-sbom.sh bench/golden-corpus/sample.cyclonedx.json
|
||||
# ./scripts/validate-sbom.sh --all # Validate all CycloneDX fixtures
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - All validations passed
|
||||
# 1 - Validation failed or error
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
SCHEMA_DIR="${REPO_ROOT}/docs/schemas"
|
||||
DEFAULT_SCHEMA="${SCHEMA_DIR}/cyclonedx-bom-1.6.schema.json"
|
||||
SBOM_UTILITY_VERSION="v0.16.0"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $*"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $*"
|
||||
}
|
||||
|
||||
check_sbom_utility() {
|
||||
if ! command -v sbom-utility &> /dev/null; then
|
||||
log_warn "sbom-utility not found in PATH"
|
||||
log_info "Installing sbom-utility ${SBOM_UTILITY_VERSION}..."
|
||||
|
||||
# Detect OS and architecture
|
||||
local os arch
|
||||
case "$(uname -s)" in
|
||||
Linux*) os="linux";;
|
||||
Darwin*) os="darwin";;
|
||||
MINGW*|MSYS*|CYGWIN*) os="windows";;
|
||||
*) log_error "Unsupported OS: $(uname -s)"; exit 1;;
|
||||
esac
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) arch="amd64";;
|
||||
arm64|aarch64) arch="arm64";;
|
||||
*) log_error "Unsupported architecture: $(uname -m)"; exit 1;;
|
||||
esac
|
||||
|
||||
local url="https://github.com/CycloneDX/sbom-utility/releases/download/${SBOM_UTILITY_VERSION}/sbom-utility-${SBOM_UTILITY_VERSION}-${os}-${arch}.tar.gz"
|
||||
local temp_dir
|
||||
temp_dir=$(mktemp -d)
|
||||
|
||||
log_info "Downloading from ${url}..."
|
||||
curl -sSfL "${url}" | tar xz -C "${temp_dir}"
|
||||
|
||||
if [[ "$os" == "windows" ]]; then
|
||||
log_info "Please add ${temp_dir}/sbom-utility.exe to your PATH"
|
||||
export PATH="${temp_dir}:${PATH}"
|
||||
else
|
||||
log_info "Installing to /usr/local/bin (may require sudo)..."
|
||||
if [[ -w /usr/local/bin ]]; then
|
||||
mv "${temp_dir}/sbom-utility" /usr/local/bin/
|
||||
else
|
||||
sudo mv "${temp_dir}/sbom-utility" /usr/local/bin/
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -rf "${temp_dir}"
|
||||
log_info "sbom-utility installed successfully"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_cyclonedx() {
|
||||
local sbom_file="$1"
|
||||
local schema="${2:-$DEFAULT_SCHEMA}"
|
||||
|
||||
if [[ ! -f "$sbom_file" ]]; then
|
||||
log_error "File not found: $sbom_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$schema" ]]; then
|
||||
log_error "Schema not found: $schema"
|
||||
log_info "Expected schema at: ${DEFAULT_SCHEMA}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Detect if it's a CycloneDX file
|
||||
if ! grep -q '"bomFormat"' "$sbom_file" 2>/dev/null; then
|
||||
log_warn "File does not appear to be CycloneDX: $sbom_file"
|
||||
log_info "Skipping (use validate-spdx.sh for SPDX files)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Validating: $sbom_file"
|
||||
|
||||
# Run sbom-utility validation
|
||||
if sbom-utility validate --input-file "$sbom_file" --format json 2>&1; then
|
||||
log_info "✓ Validation passed: $sbom_file"
|
||||
return 0
|
||||
else
|
||||
log_error "✗ Validation failed: $sbom_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_all() {
|
||||
local fixture_dir="${REPO_ROOT}/bench/golden-corpus"
|
||||
local failed=0
|
||||
local passed=0
|
||||
local skipped=0
|
||||
|
||||
log_info "Validating all CycloneDX fixtures in ${fixture_dir}..."
|
||||
|
||||
if [[ ! -d "$fixture_dir" ]]; then
|
||||
log_error "Fixture directory not found: $fixture_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
if grep -q '"bomFormat".*"CycloneDX"' "$file" 2>/dev/null; then
|
||||
if validate_cyclonedx "$file"; then
|
||||
((passed++))
|
||||
else
|
||||
((failed++))
|
||||
fi
|
||||
else
|
||||
log_info "Skipping non-CycloneDX file: $file"
|
||||
((skipped++))
|
||||
fi
|
||||
done < <(find "$fixture_dir" -type f -name '*.json' -print0)
|
||||
|
||||
echo ""
|
||||
log_info "Validation Summary:"
|
||||
log_info " Passed: ${passed}"
|
||||
log_info " Failed: ${failed}"
|
||||
log_info " Skipped: ${skipped}"
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
log_error "Some validations failed!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "All CycloneDX validations passed!"
|
||||
return 0
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [OPTIONS] <sbom-file>
|
||||
|
||||
Validates CycloneDX SBOM files against official JSON schemas.
|
||||
|
||||
Options:
|
||||
--all Validate all CycloneDX fixtures in bench/golden-corpus/
|
||||
--schema <path> Use custom schema file (default: docs/schemas/cyclonedx-bom-1.6.schema.json)
|
||||
--help, -h Show this help message
|
||||
|
||||
Examples:
|
||||
$(basename "$0") sample.cyclonedx.json
|
||||
$(basename "$0") --schema custom-schema.json sample.json
|
||||
$(basename "$0") --all
|
||||
|
||||
Exit codes:
|
||||
0 All validations passed
|
||||
1 Validation failed or error
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
local schema="$DEFAULT_SCHEMA"
|
||||
local validate_all_flag=false
|
||||
local files=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--all)
|
||||
validate_all_flag=true
|
||||
shift
|
||||
;;
|
||||
--schema)
|
||||
schema="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
log_error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
files+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure sbom-utility is available
|
||||
check_sbom_utility
|
||||
|
||||
if [[ "$validate_all_flag" == "true" ]]; then
|
||||
validate_all
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
log_error "No SBOM file specified"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local failed=0
|
||||
for file in "${files[@]}"; do
|
||||
if ! validate_cyclonedx "$file" "$schema"; then
|
||||
((failed++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
277
scripts/validate-spdx.sh
Normal file
277
scripts/validate-spdx.sh
Normal file
@@ -0,0 +1,277 @@
|
||||
#!/bin/bash
|
||||
# scripts/validate-spdx.sh
|
||||
# Sprint: SPRINT_8200_0001_0003 - SBOM Schema Validation in CI
|
||||
# Task: SCHEMA-8200-005 - Create validate-spdx.sh wrapper for SPDX validation
|
||||
#
|
||||
# Validates SPDX files against SPDX 3.0.1 JSON schema.
|
||||
# Uses pyspdxtools (spdx-tools) for SPDX validation.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/validate-spdx.sh <spdx-file>
|
||||
# ./scripts/validate-spdx.sh bench/golden-corpus/sample.spdx.json
|
||||
# ./scripts/validate-spdx.sh --all # Validate all SPDX fixtures
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - All validations passed
|
||||
# 1 - Validation failed or error
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
SCHEMA_DIR="${REPO_ROOT}/docs/schemas"
|
||||
DEFAULT_SCHEMA="${SCHEMA_DIR}/spdx-jsonld-3.0.1.schema.json"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $*"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $*"
|
||||
}
|
||||
|
||||
check_spdx_tools() {
|
||||
if ! command -v pyspdxtools &> /dev/null; then
|
||||
log_warn "pyspdxtools not found in PATH"
|
||||
log_info "Installing spdx-tools via pip..."
|
||||
|
||||
if command -v pip3 &> /dev/null; then
|
||||
pip3 install --user spdx-tools
|
||||
elif command -v pip &> /dev/null; then
|
||||
pip install --user spdx-tools
|
||||
else
|
||||
log_error "pip not found. Please install Python and pip first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "spdx-tools installed successfully"
|
||||
|
||||
# Refresh PATH for newly installed tools
|
||||
if [[ -d "${HOME}/.local/bin" ]]; then
|
||||
export PATH="${HOME}/.local/bin:${PATH}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_ajv() {
|
||||
if ! command -v ajv &> /dev/null; then
|
||||
log_warn "ajv-cli not found in PATH"
|
||||
log_info "Installing ajv-cli via npm..."
|
||||
|
||||
if command -v npm &> /dev/null; then
|
||||
npm install -g ajv-cli ajv-formats
|
||||
else
|
||||
log_warn "npm not found. JSON schema validation will be skipped."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "ajv-cli installed successfully"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
validate_spdx_schema() {
|
||||
local spdx_file="$1"
|
||||
local schema="$2"
|
||||
|
||||
if check_ajv; then
|
||||
log_info "Validating against JSON schema: $schema"
|
||||
if ajv validate -s "$schema" -d "$spdx_file" --spec=draft2020 2>&1; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_warn "Skipping JSON schema validation (ajv not available)"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
validate_spdx() {
|
||||
local spdx_file="$1"
|
||||
local schema="${2:-$DEFAULT_SCHEMA}"
|
||||
|
||||
if [[ ! -f "$spdx_file" ]]; then
|
||||
log_error "File not found: $spdx_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Detect if it's an SPDX file (JSON-LD format)
|
||||
if ! grep -qE '"@context"|"spdxId"|"spdxVersion"' "$spdx_file" 2>/dev/null; then
|
||||
log_warn "File does not appear to be SPDX: $spdx_file"
|
||||
log_info "Skipping (use validate-sbom.sh for CycloneDX files)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Validating: $spdx_file"
|
||||
|
||||
local validation_passed=true
|
||||
|
||||
# Try pyspdxtools validation first (semantic validation)
|
||||
if command -v pyspdxtools &> /dev/null; then
|
||||
log_info "Running SPDX semantic validation..."
|
||||
if pyspdxtools validate "$spdx_file" 2>&1; then
|
||||
log_info "✓ SPDX semantic validation passed"
|
||||
else
|
||||
# pyspdxtools may not support SPDX 3.0 yet
|
||||
log_warn "pyspdxtools validation failed or not supported for this format"
|
||||
log_info "Falling back to JSON schema validation only"
|
||||
fi
|
||||
fi
|
||||
|
||||
# JSON schema validation (syntax validation)
|
||||
if [[ -f "$schema" ]]; then
|
||||
if validate_spdx_schema "$spdx_file" "$schema"; then
|
||||
log_info "✓ JSON schema validation passed"
|
||||
else
|
||||
log_error "✗ JSON schema validation failed"
|
||||
validation_passed=false
|
||||
fi
|
||||
else
|
||||
log_warn "Schema file not found: $schema"
|
||||
log_info "Skipping schema validation"
|
||||
fi
|
||||
|
||||
if [[ "$validation_passed" == "true" ]]; then
|
||||
log_info "✓ Validation passed: $spdx_file"
|
||||
return 0
|
||||
else
|
||||
log_error "✗ Validation failed: $spdx_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_all() {
|
||||
local fixture_dir="${REPO_ROOT}/bench/golden-corpus"
|
||||
local failed=0
|
||||
local passed=0
|
||||
local skipped=0
|
||||
|
||||
log_info "Validating all SPDX fixtures in ${fixture_dir}..."
|
||||
|
||||
if [[ ! -d "$fixture_dir" ]]; then
|
||||
log_error "Fixture directory not found: $fixture_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
# Check if it's an SPDX file
|
||||
if grep -qE '"@context"|"spdxVersion"' "$file" 2>/dev/null; then
|
||||
if validate_spdx "$file"; then
|
||||
((passed++))
|
||||
else
|
||||
((failed++))
|
||||
fi
|
||||
else
|
||||
log_info "Skipping non-SPDX file: $file"
|
||||
((skipped++))
|
||||
fi
|
||||
done < <(find "$fixture_dir" -type f \( -name '*spdx*.json' -o -name '*.spdx.json' \) -print0)
|
||||
|
||||
echo ""
|
||||
log_info "Validation Summary:"
|
||||
log_info " Passed: ${passed}"
|
||||
log_info " Failed: ${failed}"
|
||||
log_info " Skipped: ${skipped}"
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
log_error "Some validations failed!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "All SPDX validations passed!"
|
||||
return 0
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [OPTIONS] <spdx-file>
|
||||
|
||||
Validates SPDX files against SPDX 3.0.1 JSON schema.
|
||||
|
||||
Options:
|
||||
--all Validate all SPDX fixtures in bench/golden-corpus/
|
||||
--schema <path> Use custom schema file (default: docs/schemas/spdx-jsonld-3.0.1.schema.json)
|
||||
--help, -h Show this help message
|
||||
|
||||
Examples:
|
||||
$(basename "$0") sample.spdx.json
|
||||
$(basename "$0") --schema custom-schema.json sample.json
|
||||
$(basename "$0") --all
|
||||
|
||||
Exit codes:
|
||||
0 All validations passed
|
||||
1 Validation failed or error
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
local schema="$DEFAULT_SCHEMA"
|
||||
local validate_all_flag=false
|
||||
local files=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--all)
|
||||
validate_all_flag=true
|
||||
shift
|
||||
;;
|
||||
--schema)
|
||||
schema="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
log_error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
files+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure tools are available
|
||||
check_spdx_tools || true # Continue even if pyspdxtools install fails
|
||||
|
||||
if [[ "$validate_all_flag" == "true" ]]; then
|
||||
validate_all
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
log_error "No SPDX file specified"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local failed=0
|
||||
for file in "${files[@]}"; do
|
||||
if ! validate_spdx "$file" "$schema"; then
|
||||
((failed++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
261
scripts/validate-vex.sh
Normal file
261
scripts/validate-vex.sh
Normal file
@@ -0,0 +1,261 @@
|
||||
#!/bin/bash
|
||||
# scripts/validate-vex.sh
|
||||
# Sprint: SPRINT_8200_0001_0003 - SBOM Schema Validation in CI
|
||||
# Task: SCHEMA-8200-006 - Create validate-vex.sh wrapper for OpenVEX validation
|
||||
#
|
||||
# Validates OpenVEX files against the OpenVEX 0.2.0 JSON schema.
|
||||
# Uses ajv-cli for JSON schema validation.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/validate-vex.sh <vex-file>
|
||||
# ./scripts/validate-vex.sh bench/golden-corpus/sample.vex.json
|
||||
# ./scripts/validate-vex.sh --all # Validate all VEX fixtures
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - All validations passed
|
||||
# 1 - Validation failed or error
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
SCHEMA_DIR="${REPO_ROOT}/docs/schemas"
|
||||
DEFAULT_SCHEMA="${SCHEMA_DIR}/openvex-0.2.0.schema.json"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $*"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $*"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $*"
|
||||
}
|
||||
|
||||
check_ajv() {
|
||||
if ! command -v ajv &> /dev/null; then
|
||||
log_warn "ajv-cli not found in PATH"
|
||||
log_info "Installing ajv-cli via npm..."
|
||||
|
||||
if command -v npm &> /dev/null; then
|
||||
npm install -g ajv-cli ajv-formats
|
||||
elif command -v npx &> /dev/null; then
|
||||
log_info "Using npx for ajv (no global install)"
|
||||
return 0
|
||||
else
|
||||
log_error "npm/npx not found. Please install Node.js first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "ajv-cli installed successfully"
|
||||
fi
|
||||
}
|
||||
|
||||
run_ajv() {
|
||||
local schema="$1"
|
||||
local data="$2"
|
||||
|
||||
if command -v ajv &> /dev/null; then
|
||||
ajv validate -s "$schema" -d "$data" --spec=draft2020 2>&1
|
||||
elif command -v npx &> /dev/null; then
|
||||
npx ajv-cli validate -s "$schema" -d "$data" --spec=draft2020 2>&1
|
||||
else
|
||||
log_error "No ajv available"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_openvex() {
|
||||
local vex_file="$1"
|
||||
local schema="${2:-$DEFAULT_SCHEMA}"
|
||||
|
||||
if [[ ! -f "$vex_file" ]]; then
|
||||
log_error "File not found: $vex_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$schema" ]]; then
|
||||
log_error "Schema not found: $schema"
|
||||
log_info "Expected schema at: ${DEFAULT_SCHEMA}"
|
||||
log_info "Download from: https://raw.githubusercontent.com/openvex/spec/main/openvex_json_schema.json"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Detect if it's an OpenVEX file
|
||||
if ! grep -qE '"@context".*"https://openvex.dev/ns"|"openvex"' "$vex_file" 2>/dev/null; then
|
||||
log_warn "File does not appear to be OpenVEX: $vex_file"
|
||||
log_info "Skipping (use validate-sbom.sh for CycloneDX files)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Validating: $vex_file"
|
||||
|
||||
# Run ajv validation
|
||||
if run_ajv "$schema" "$vex_file"; then
|
||||
log_info "✓ Validation passed: $vex_file"
|
||||
return 0
|
||||
else
|
||||
log_error "✗ Validation failed: $vex_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
validate_all() {
|
||||
local failed=0
|
||||
local passed=0
|
||||
local skipped=0
|
||||
|
||||
# Search multiple directories for VEX files
|
||||
local search_dirs=(
|
||||
"${REPO_ROOT}/bench/golden-corpus"
|
||||
"${REPO_ROOT}/bench/vex-lattice"
|
||||
"${REPO_ROOT}/datasets"
|
||||
)
|
||||
|
||||
log_info "Validating all OpenVEX fixtures..."
|
||||
|
||||
for fixture_dir in "${search_dirs[@]}"; do
|
||||
if [[ ! -d "$fixture_dir" ]]; then
|
||||
log_warn "Directory not found, skipping: $fixture_dir"
|
||||
continue
|
||||
fi
|
||||
|
||||
log_info "Searching in: $fixture_dir"
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
# Check if it's an OpenVEX file
|
||||
if grep -qE '"@context".*"https://openvex.dev/ns"|"openvex"' "$file" 2>/dev/null; then
|
||||
if validate_openvex "$file"; then
|
||||
((passed++))
|
||||
else
|
||||
((failed++))
|
||||
fi
|
||||
elif grep -q '"vex"' "$file" 2>/dev/null || [[ "$file" == *vex* ]]; then
|
||||
# Might be VEX-related but not OpenVEX format
|
||||
log_info "Checking potential VEX file: $file"
|
||||
if grep -qE '"@context"' "$file" 2>/dev/null; then
|
||||
if validate_openvex "$file"; then
|
||||
((passed++))
|
||||
else
|
||||
((failed++))
|
||||
fi
|
||||
else
|
||||
log_info "Skipping non-OpenVEX file: $file"
|
||||
((skipped++))
|
||||
fi
|
||||
else
|
||||
((skipped++))
|
||||
fi
|
||||
done < <(find "$fixture_dir" -type f \( -name '*vex*.json' -o -name '*.vex.json' -o -name '*openvex*.json' \) -print0 2>/dev/null || true)
|
||||
done
|
||||
|
||||
echo ""
|
||||
log_info "Validation Summary:"
|
||||
log_info " Passed: ${passed}"
|
||||
log_info " Failed: ${failed}"
|
||||
log_info " Skipped: ${skipped}"
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
log_error "Some validations failed!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ $passed -eq 0 ]] && [[ $skipped -eq 0 ]]; then
|
||||
log_warn "No OpenVEX files found to validate"
|
||||
else
|
||||
log_info "All OpenVEX validations passed!"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat << EOF
|
||||
Usage: $(basename "$0") [OPTIONS] <vex-file>
|
||||
|
||||
Validates OpenVEX files against the OpenVEX 0.2.0 JSON schema.
|
||||
|
||||
Options:
|
||||
--all Validate all OpenVEX fixtures in bench/ and datasets/
|
||||
--schema <path> Use custom schema file (default: docs/schemas/openvex-0.2.0.schema.json)
|
||||
--help, -h Show this help message
|
||||
|
||||
Examples:
|
||||
$(basename "$0") sample.vex.json
|
||||
$(basename "$0") --schema custom-schema.json sample.json
|
||||
$(basename "$0") --all
|
||||
|
||||
Exit codes:
|
||||
0 All validations passed
|
||||
1 Validation failed or error
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
local schema="$DEFAULT_SCHEMA"
|
||||
local validate_all_flag=false
|
||||
local files=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--all)
|
||||
validate_all_flag=true
|
||||
shift
|
||||
;;
|
||||
--schema)
|
||||
schema="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
log_error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
files+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Ensure ajv is available
|
||||
check_ajv
|
||||
|
||||
if [[ "$validate_all_flag" == "true" ]]; then
|
||||
validate_all
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ ${#files[@]} -eq 0 ]]; then
|
||||
log_error "No VEX file specified"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local failed=0
|
||||
for file in "${files[@]}"; do
|
||||
if ! validate_openvex "$file" "$schema"; then
|
||||
((failed++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $failed -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user