#!/usr/bin/env bash set -euo pipefail # Collect third-party license texts into LICENSES.md # Usage: scripts/collect_licenses.sh [output-path] # output-path defaults to LICENSES.md at the repo root REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" OUT="${1:-$REPO_ROOT/LICENSES.md}" FRONTEND_DOCKER_LOCK="$REPO_ROOT/frontend/package-lock.docker.json" FRONTEND_LICENSE_IMAGE="${FRONTEND_LICENSE_IMAGE:-node:20-slim}" FRONTEND_LICENSE_NPM="${FRONTEND_LICENSE_NPM:-10.9.5}" # ── Backend (Python) — uses pip-licenses ───────────────────────────── backend_licenses() { cd "$REPO_ROOT" # Extract direct dependency names from pyproject.toml local packages packages=$(uv run python3 -c " import re, tomllib with open('pyproject.toml', 'rb') as f: deps = tomllib.load(f)['project']['dependencies'] names = [re.split(r'[\[><=!;]', d)[0].strip() for d in deps] print(' '.join(names)) ") # shellcheck disable=SC2086 uv run pip-licenses \ --packages $packages \ --with-license-file \ --no-license-path \ --format=json \ | uv run python3 -c " import json, sys data = sorted(json.load(sys.stdin), key=lambda d: d['Name'].lower()) for d in data: name = d['Name'] version = d['Version'] lic = d.get('License', 'Unknown') text = d.get('LicenseText', '').strip() print(f'### {name} ({version}) — {lic}\n') if text and text != 'UNKNOWN': print('
') print('Full license text') print() print('\`\`\`') print(text) print('\`\`\`') print() print('
') else: print('*License file not found in package metadata.*') print() " } # ── Frontend (npm) ─────────────────────────────────────────────────── frontend_licenses_local() { cd "$REPO_ROOT/frontend" node "$REPO_ROOT/scripts/print_frontend_licenses.cjs" } frontend_licenses_docker() { docker run --rm \ -v "$REPO_ROOT:/src:ro" \ -w /tmp \ "$FRONTEND_LICENSE_IMAGE" \ bash -lc " set -euo pipefail cp -a /src/frontend ./frontend cd frontend cp package-lock.docker.json package-lock.json npm i -g npm@$FRONTEND_LICENSE_NPM >/dev/null npm ci --ignore-scripts >/dev/null node /src/scripts/print_frontend_licenses.cjs " } frontend_licenses() { if [ -f "$FRONTEND_DOCKER_LOCK" ]; then frontend_licenses_docker else frontend_licenses_local fi } # ── Assemble ───────────────────────────────────────────────────────── { echo "# Third-Party Licenses" echo echo "Auto-generated by \`scripts/collect_licenses.sh\` — do not edit by hand." echo echo "## Backend (Python) Dependencies" echo backend_licenses echo "## Frontend (npm) Dependencies" echo frontend_licenses } > "$OUT" echo "Wrote $OUT" >&2