Refactor code structure and optimize performance across multiple modules
This commit is contained in:
201
.gitea/scripts/validate/validate-licenses.sh
Normal file
201
.gitea/scripts/validate/validate-licenses.sh
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user