Files
git.stella-ops.org/.gitea/scripts/validate/validate-licenses.sh

202 lines
4.8 KiB
Bash

#!/usr/bin/env bash
# License validation script for StellaOps CI
# Usage: validate-licenses.sh <type> <input-file>
# type: nuget | npm
# input-file: Path to package list or license-checker output
set -euo pipefail
# SPDX identifiers for licenses compatible with AGPL-3.0-or-later
ALLOWED_LICENSES=(
"MIT"
"Apache-2.0"
"Apache 2.0"
"BSD-2-Clause"
"BSD-3-Clause"
"BSD"
"ISC"
"0BSD"
"CC0-1.0"
"CC0"
"Unlicense"
"PostgreSQL"
"MPL-2.0"
"MPL 2.0"
"LGPL-2.1-or-later"
"LGPL-3.0-or-later"
"GPL-3.0-or-later"
"AGPL-3.0-or-later"
"Zlib"
"WTFPL"
"BlueOak-1.0.0"
"Python-2.0"
"(MIT OR Apache-2.0)"
"(Apache-2.0 OR MIT)"
"MIT OR Apache-2.0"
"Apache-2.0 OR MIT"
)
# Licenses that are OK but should be noted
CONDITIONAL_LICENSES=(
"MPL-2.0"
"LGPL-2.1-or-later"
"LGPL-3.0-or-later"
"CC-BY-4.0"
)
# Licenses that are NOT compatible with AGPL-3.0-or-later
BLOCKED_LICENSES=(
"GPL-2.0-only"
"SSPL-1.0"
"SSPL"
"BUSL-1.1"
"BSL-1.0"
"Commons Clause"
"Proprietary"
"Commercial"
"UNLICENSED"
)
TYPE="${1:-}"
INPUT="${2:-}"
if [[ -z "$TYPE" || -z "$INPUT" ]]; then
echo "Usage: $0 <nuget|npm> <input-file>"
exit 1
fi
if [[ ! -f "$INPUT" ]]; then
echo "ERROR: Input file not found: $INPUT"
exit 1
fi
echo "=== StellaOps License Validation ==="
echo "Type: $TYPE"
echo "Input: $INPUT"
echo ""
found_blocked=0
found_conditional=0
found_unknown=0
validate_npm() {
local input="$1"
echo "Validating npm licenses..."
# Extract licenses from license-checker JSON output
if command -v jq &> /dev/null; then
jq -r 'to_entries[] | "\(.key): \(.value.licenses)"' "$input" 2>/dev/null | while read -r line; do
pkg=$(echo "$line" | cut -d: -f1)
license=$(echo "$line" | cut -d: -f2- | xargs)
# Check if license is blocked
for blocked in "${BLOCKED_LICENSES[@]}"; do
if [[ "$license" == *"$blocked"* ]]; then
echo "BLOCKED: $pkg uses '$license'"
found_blocked=$((found_blocked + 1))
fi
done
# Check if license is allowed
allowed=0
for ok_license in "${ALLOWED_LICENSES[@]}"; do
if [[ "$license" == *"$ok_license"* ]]; then
allowed=1
break
fi
done
if [[ $allowed -eq 0 ]]; then
echo "UNKNOWN: $pkg uses '$license'"
found_unknown=$((found_unknown + 1))
fi
done
else
echo "WARNING: jq not available, performing basic grep check"
for blocked in "${BLOCKED_LICENSES[@]}"; do
if grep -qi "$blocked" "$input"; then
echo "BLOCKED: Found potentially blocked license: $blocked"
found_blocked=$((found_blocked + 1))
fi
done
fi
}
validate_nuget() {
local input="$1"
echo "Validating NuGet licenses..."
# NuGet package list doesn't include licenses directly
# We check for known problematic packages
# Known packages with compatible licenses (allowlist approach for critical packages)
known_good_patterns=(
"Microsoft."
"System."
"Newtonsoft.Json"
"Serilog"
"BouncyCastle"
"Npgsql"
"Dapper"
"Polly"
"xunit"
"Moq"
"FluentAssertions"
"CycloneDX"
"YamlDotNet"
"StackExchange.Redis"
"Google."
"AWSSDK."
"Grpc."
)
# Check if any packages don't match known patterns
echo "Checking for unknown packages..."
# This is informational - we trust the allowlist in THIRD-PARTY-DEPENDENCIES.md
echo "OK: NuGet validation relies on documented license allowlist"
echo "See: docs/legal/THIRD-PARTY-DEPENDENCIES.md"
}
case "$TYPE" in
npm)
validate_npm "$INPUT"
;;
nuget)
validate_nuget "$INPUT"
;;
*)
echo "ERROR: Unknown type: $TYPE"
echo "Supported types: nuget, npm"
exit 1
;;
esac
echo ""
echo "=== Validation Summary ==="
echo "Blocked licenses found: $found_blocked"
echo "Conditional licenses found: $found_conditional"
echo "Unknown licenses found: $found_unknown"
if [[ $found_blocked -gt 0 ]]; then
echo ""
echo "ERROR: Blocked licenses detected!"
echo "These licenses are NOT compatible with AGPL-3.0-or-later"
echo "Please remove or replace the affected packages"
exit 1
fi
if [[ $found_unknown -gt 0 ]]; then
echo ""
echo "WARNING: Unknown licenses detected"
echo "Please review and add to allowlist if compatible"
echo "See: docs/legal/LICENSE-COMPATIBILITY.md"
# Don't fail on unknown - just warn
fi
echo ""
echo "License validation: PASSED"
exit 0