mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-03 06:47:33 +00:00
- Make telemetry detection patterns more specific - Target actual Mixpanel API calls instead of generic patterns - Avoid flagging benign code like `.track()` from other libraries - Focus on MixpanelTelemetryProvider and actual tracking methods This reduces false positives while maintaining security. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
254 lines
6.6 KiB
JavaScript
254 lines
6.6 KiB
JavaScript
/**
|
|
* CI Script: Verify OSS Build Compliance
|
|
*
|
|
* This script verifies that the OSS build (DISTRIBUTION=localhost) does not contain:
|
|
* 1. Proprietary licensed files (e.g., ABCROM font)
|
|
* 2. Telemetry code (e.g., mixpanel library references)
|
|
*
|
|
* Usage: node scripts/verify-oss-build.js
|
|
*
|
|
* Exit codes:
|
|
* - 0: All checks passed
|
|
* - 1: Violations found
|
|
*/
|
|
|
|
import { readFileSync, readdirSync, statSync } from 'fs'
|
|
import { join, extname, dirname } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
|
|
const DIST_DIR = join(__dirname, '..', 'dist')
|
|
const COLORS = {
|
|
red: '\x1b[31m',
|
|
green: '\x1b[32m',
|
|
yellow: '\x1b[33m',
|
|
blue: '\x1b[34m',
|
|
reset: '\x1b[0m'
|
|
}
|
|
|
|
// Patterns to check for violations
|
|
const VIOLATION_PATTERNS = {
|
|
// Proprietary font checks
|
|
font: {
|
|
patterns: [/ABCROM/gi, /ABCROMExtended/gi, /ABC\s*ROM/gi],
|
|
description: 'ABCROM proprietary font references'
|
|
},
|
|
// Telemetry checks - more specific patterns to avoid false positives
|
|
telemetry: {
|
|
patterns: [
|
|
/mixpanel\.init/gi,
|
|
/mixpanel\.identify/gi,
|
|
/MixpanelTelemetryProvider/gi,
|
|
/mp\.comfy\.org/gi,
|
|
/mixpanel-browser/gi,
|
|
// Only check for our specific tracking methods with context
|
|
/useTelemetry\(\).*?trackWorkflow/gs,
|
|
/useTelemetry\(\).*?trackEvent/gs,
|
|
// Check for Mixpanel tracking in a more specific way
|
|
/mixpanel\.track\s*\(/gi
|
|
],
|
|
description: 'Mixpanel telemetry code'
|
|
}
|
|
}
|
|
|
|
// File extensions to check
|
|
const JS_EXTENSIONS = ['.js', '.mjs', '.cjs']
|
|
const FONT_EXTENSIONS = ['.woff', '.woff2', '.ttf', '.otf']
|
|
|
|
/**
|
|
* Recursively get all files in a directory
|
|
*/
|
|
function getAllFiles(dir, extensions = null) {
|
|
const files = []
|
|
|
|
try {
|
|
const items = readdirSync(dir)
|
|
|
|
for (const item of items) {
|
|
const fullPath = join(dir, item)
|
|
const stat = statSync(fullPath)
|
|
|
|
if (stat.isDirectory()) {
|
|
files.push(...getAllFiles(fullPath, extensions))
|
|
} else if (stat.isFile()) {
|
|
if (!extensions || extensions.includes(extname(fullPath))) {
|
|
files.push(fullPath)
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(
|
|
`${COLORS.red}Error reading directory ${dir}: ${err.message}${COLORS.reset}`
|
|
)
|
|
}
|
|
|
|
return files
|
|
}
|
|
|
|
/**
|
|
* Check if file content contains violation patterns
|
|
*/
|
|
function checkFileForViolations(filePath, violationConfig) {
|
|
try {
|
|
const content = readFileSync(filePath, 'utf-8')
|
|
const violations = []
|
|
|
|
for (const pattern of violationConfig.patterns) {
|
|
const matches = content.match(pattern)
|
|
if (matches && matches.length > 0) {
|
|
violations.push({
|
|
pattern: pattern.toString(),
|
|
matches: matches.length,
|
|
sample: matches[0]
|
|
})
|
|
}
|
|
}
|
|
|
|
return violations
|
|
} catch (err) {
|
|
// Binary files or read errors - skip
|
|
return []
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for proprietary font files
|
|
*/
|
|
function checkForFontFiles() {
|
|
console.log(
|
|
`\n${COLORS.blue}Checking for proprietary font files...${COLORS.reset}`
|
|
)
|
|
|
|
const fontFiles = getAllFiles(DIST_DIR, FONT_EXTENSIONS)
|
|
const violations = []
|
|
|
|
for (const fontFile of fontFiles) {
|
|
const fileName = fontFile.toLowerCase()
|
|
if (fileName.includes('abcrom')) {
|
|
violations.push(fontFile)
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
console.log(
|
|
`${COLORS.red}✗ Found ${violations.length} proprietary font file(s):${COLORS.reset}`
|
|
)
|
|
violations.forEach((file) => {
|
|
console.log(` ${COLORS.red}- ${file}${COLORS.reset}`)
|
|
})
|
|
return false
|
|
} else {
|
|
console.log(
|
|
`${COLORS.green}✓ No proprietary font files found${COLORS.reset}`
|
|
)
|
|
return true
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check JavaScript files for code violations
|
|
*/
|
|
function checkJavaScriptFiles() {
|
|
console.log(
|
|
`\n${COLORS.blue}Checking JavaScript files for code violations...${COLORS.reset}`
|
|
)
|
|
|
|
const jsFiles = getAllFiles(DIST_DIR, JS_EXTENSIONS)
|
|
const allViolations = {}
|
|
|
|
for (const [violationType, config] of Object.entries(VIOLATION_PATTERNS)) {
|
|
allViolations[violationType] = []
|
|
|
|
for (const jsFile of jsFiles) {
|
|
const violations = checkFileForViolations(jsFile, config)
|
|
if (violations.length > 0) {
|
|
allViolations[violationType].push({
|
|
file: jsFile,
|
|
violations
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
let hasViolations = false
|
|
|
|
for (const [violationType, config] of Object.entries(VIOLATION_PATTERNS)) {
|
|
const violations = allViolations[violationType]
|
|
|
|
if (violations.length > 0) {
|
|
hasViolations = true
|
|
console.log(
|
|
`\n${COLORS.red}✗ Found ${config.description} in ${violations.length} file(s):${COLORS.reset}`
|
|
)
|
|
|
|
violations.forEach(({ file, violations: fileViolations }) => {
|
|
console.log(`\n ${COLORS.yellow}${file}${COLORS.reset}`)
|
|
fileViolations.forEach(({ pattern, matches, sample }) => {
|
|
console.log(` ${COLORS.red}Pattern: ${pattern}${COLORS.reset}`)
|
|
console.log(` ${COLORS.red}Matches: ${matches}${COLORS.reset}`)
|
|
console.log(` ${COLORS.red}Sample: "${sample}"${COLORS.reset}`)
|
|
})
|
|
})
|
|
} else {
|
|
console.log(
|
|
`${COLORS.green}✓ No ${config.description} found${COLORS.reset}`
|
|
)
|
|
}
|
|
}
|
|
|
|
return !hasViolations
|
|
}
|
|
|
|
/**
|
|
* Main verification function
|
|
*/
|
|
function main() {
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(`${COLORS.blue}OSS Build Verification${COLORS.reset}`)
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(`${COLORS.blue}Checking: ${DIST_DIR}${COLORS.reset}`)
|
|
|
|
// Check if dist directory exists
|
|
try {
|
|
statSync(DIST_DIR)
|
|
} catch (err) {
|
|
console.error(
|
|
`\n${COLORS.red}Error: dist/ directory not found. Please run 'pnpm build' first.${COLORS.reset}`
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
// Run checks
|
|
const fontCheckPassed = checkForFontFiles()
|
|
const codeCheckPassed = checkJavaScriptFiles()
|
|
|
|
// Summary
|
|
console.log(
|
|
`\n${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
console.log(`${COLORS.blue}Verification Summary${COLORS.reset}`)
|
|
console.log(
|
|
`${COLORS.blue}========================================${COLORS.reset}`
|
|
)
|
|
|
|
if (fontCheckPassed && codeCheckPassed) {
|
|
console.log(
|
|
`${COLORS.green}✓ All checks passed! OSS build is compliant.${COLORS.reset}\n`
|
|
)
|
|
process.exit(0)
|
|
} else {
|
|
console.log(
|
|
`${COLORS.red}✗ Verification failed! Please fix the violations above.${COLORS.reset}\n`
|
|
)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
main()
|