mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 00:20:07 +00:00
Implements automated verification to ensure the OSS distribution: 1. Only includes open-source licensed dependencies 2. Properly tree-shakes proprietary fonts (ABCROM) 3. Removes telemetry code (Mixpanel) from OSS builds New scripts: - scripts/verify-licenses.js - Validates production dependency licenses - scripts/verify-oss-build.js - Checks dist/ for violations New CI workflow: - .github/workflows/ci-oss-compliance.yaml - Runs compliance checks New npm scripts: - pnpm verify:licenses - Check dependency licenses - pnpm verify:oss - Verify OSS build compliance - pnpm verify:compliance - Run all checks - pnpm build:oss - Build OSS distribution Documentation: - docs/OSS_COMPLIANCE.md - Complete guide for compliance checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
226 lines
5.4 KiB
JavaScript
226 lines
5.4 KiB
JavaScript
/**
|
|
* CI Script: Verify License Compliance
|
|
*
|
|
* This script verifies that all production dependencies use open-source compatible licenses.
|
|
* It checks against a list of approved licenses and flags any non-compliant dependencies.
|
|
*
|
|
* Usage: node scripts/verify-licenses.js
|
|
*
|
|
* Exit codes:
|
|
* - 0: All licenses are compliant
|
|
* - 1: Non-compliant licenses found
|
|
*/
|
|
|
|
import { execSync } from 'child_process'
|
|
|
|
const COLORS = {
|
|
red: '\x1b[31m',
|
|
green: '\x1b[32m',
|
|
yellow: '\x1b[33m',
|
|
blue: '\x1b[34m',
|
|
reset: '\x1b[0m'
|
|
}
|
|
|
|
// Approved open-source licenses
|
|
// Based on OSI-approved licenses and common permissive licenses
|
|
const APPROVED_LICENSES = new Set([
|
|
'MIT',
|
|
'Apache-2.0',
|
|
'BSD-2-Clause',
|
|
'BSD-3-Clause',
|
|
'ISC',
|
|
'CC0-1.0',
|
|
'CC-BY-3.0',
|
|
'CC-BY-4.0',
|
|
'Unlicense',
|
|
'WTFPL',
|
|
'0BSD',
|
|
'BlueOak-1.0.0',
|
|
'Python-2.0',
|
|
'Zlib',
|
|
// GPL is acceptable for libraries as long as we're GPL-3.0-only
|
|
'GPL-2.0',
|
|
'GPL-3.0',
|
|
'GPL-3.0-only',
|
|
'LGPL-2.1',
|
|
'LGPL-3.0',
|
|
'MPL-2.0',
|
|
// Public domain
|
|
'Public Domain',
|
|
'Unlicensed'
|
|
])
|
|
|
|
// Known problematic licenses
|
|
const PROBLEMATIC_LICENSES = new Set([
|
|
'UNLICENSED',
|
|
'CUSTOM',
|
|
'SEE LICENSE IN LICENSE',
|
|
'PROPRIETARY'
|
|
])
|
|
|
|
/**
|
|
* Parse pnpm licenses output
|
|
*/
|
|
function getLicenses() {
|
|
console.log(
|
|
`${COLORS.blue}Fetching production dependency licenses...${COLORS.reset}`
|
|
)
|
|
|
|
try {
|
|
const output = execSync('pnpm licenses list --json --prod', {
|
|
encoding: 'utf-8',
|
|
maxBuffer: 10 * 1024 * 1024 // 10MB buffer
|
|
})
|
|
|
|
const licenses = JSON.parse(output)
|
|
return licenses
|
|
} catch (err) {
|
|
console.error(
|
|
`${COLORS.red}Error fetching licenses: ${err.message}${COLORS.reset}`
|
|
)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Normalize license names for comparison
|
|
*/
|
|
function normalizeLicense(license) {
|
|
if (!license) return 'UNKNOWN'
|
|
|
|
// Handle common variations
|
|
const normalized = license.trim().replace(/\s+/g, '-').toUpperCase()
|
|
|
|
// Handle "OR" clauses - take the first license
|
|
if (normalized.includes(' OR ')) {
|
|
return normalized.split(' OR ')[0].trim()
|
|
}
|
|
|
|
// Handle "AND" clauses - if any license is approved, consider it approved
|
|
if (normalized.includes(' AND ')) {
|
|
const licenses = normalized.split(' AND ')
|
|
for (const lic of licenses) {
|
|
const trimmed = lic.trim()
|
|
if (APPROVED_LICENSES.has(trimmed)) {
|
|
return trimmed
|
|
}
|
|
}
|
|
}
|
|
|
|
return normalized
|
|
}
|
|
|
|
/**
|
|
* Check if a license is approved
|
|
*/
|
|
function isLicenseApproved(license) {
|
|
const normalized = normalizeLicense(license)
|
|
|
|
// Check exact match
|
|
if (APPROVED_LICENSES.has(normalized)) {
|
|
return true
|
|
}
|
|
|
|
// Check if any approved license is a substring (handles variations)
|
|
for (const approved of APPROVED_LICENSES) {
|
|
if (normalized.includes(approved.toUpperCase())) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* Main verification function
|
|
*/
|
|
function main() {
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(`${COLORS.blue}License Compliance Verification${COLORS.reset}`)
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}\n`
|
|
)
|
|
|
|
const licenses = getLicenses()
|
|
|
|
const violations = []
|
|
const warnings = []
|
|
let totalPackages = 0
|
|
|
|
// Check each license group
|
|
for (const [license, packages] of Object.entries(licenses)) {
|
|
for (const pkg of packages) {
|
|
totalPackages++
|
|
|
|
const isApproved = isLicenseApproved(license)
|
|
const isProblematic = PROBLEMATIC_LICENSES.has(normalizeLicense(license))
|
|
|
|
if (isProblematic || !isApproved) {
|
|
violations.push({
|
|
package: pkg.name,
|
|
version: pkg.versions[0],
|
|
license: license,
|
|
isProblematic
|
|
})
|
|
} else if (license === 'UNKNOWN' || !license) {
|
|
warnings.push({
|
|
package: pkg.name,
|
|
version: pkg.versions[0],
|
|
license: 'UNKNOWN'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// Report warnings
|
|
if (warnings.length > 0) {
|
|
console.log(
|
|
`${COLORS.yellow}⚠ Packages with unknown licenses (${warnings.length}):${COLORS.reset}`
|
|
)
|
|
warnings.forEach(({ package: name, version }) => {
|
|
console.log(` ${COLORS.yellow}- ${name}@${version}${COLORS.reset}`)
|
|
})
|
|
console.log()
|
|
}
|
|
|
|
// Report violations
|
|
if (violations.length > 0) {
|
|
console.log(
|
|
`${COLORS.red}✗ Found ${violations.length} package(s) with non-compliant licenses:${COLORS.reset}\n`
|
|
)
|
|
|
|
violations.forEach(({ package: name, version, license, isProblematic }) => {
|
|
console.log(` ${COLORS.red}Package: ${name}@${version}${COLORS.reset}`)
|
|
console.log(` ${COLORS.red}License: ${license}${COLORS.reset}`)
|
|
if (isProblematic) {
|
|
console.log(
|
|
` ${COLORS.red}⚠ This license is known to be problematic${COLORS.reset}`
|
|
)
|
|
}
|
|
console.log()
|
|
})
|
|
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(`${COLORS.red}✗ License verification failed!${COLORS.reset}`)
|
|
console.log(
|
|
`${COLORS.red}Please review and update dependencies with non-compliant licenses.${COLORS.reset}\n`
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
// Success
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(
|
|
`${COLORS.green}✓ All ${totalPackages} production dependencies use approved licenses!${COLORS.reset}\n`
|
|
)
|
|
process.exit(0)
|
|
}
|
|
|
|
main()
|