mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-31 21:39:28 +00:00
Merge branch 'main' into chore/duplicate_actions_panel
This commit is contained in:
commit
d487f724b8
6 changed files with 461 additions and 13 deletions
|
|
@ -29,7 +29,13 @@
|
|||
{
|
||||
"from": "resources/prebuilt",
|
||||
"to": "prebuilt",
|
||||
"filter": ["**/*", "!cache/**/*", "!**/.npm-cache/**/*"]
|
||||
"filter": [
|
||||
"**/*",
|
||||
"!cache/**/*",
|
||||
"!**/.npm-cache/**/*",
|
||||
"!uv_python/**/*.pyc",
|
||||
"!uv_python/**/__pycache__"
|
||||
]
|
||||
}
|
||||
],
|
||||
"protocols": [
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { getBackendPath, getBinaryPath, getCachePath, getVenvPath, getUvEnv, isBinaryExists, runInstallScript, killProcessByName } from "./utils/process";
|
||||
import { getBackendPath, getBinaryPath, getCachePath, getVenvPath, getUvEnv, isBinaryExists, runInstallScript, killProcessByName, getPrebuiltPythonDir, getPrebuiltVenvPath } from "./utils/process";
|
||||
import { spawn, exec } from 'child_process'
|
||||
import log from 'electron-log'
|
||||
import fs from 'fs'
|
||||
|
|
@ -225,21 +225,34 @@ export async function startBackend(setPort?: (port: number) => void): Promise<an
|
|||
log.warn(`Failed to remove lock file: ${e}`);
|
||||
}
|
||||
|
||||
// Cleanup corrupted python cache
|
||||
// Cleanup corrupted python cache ONLY if we don't have bundled Python
|
||||
// If we have bundled Python, we want to keep it and reuse it
|
||||
const prebuiltPythonDir = getPrebuiltPythonDir();
|
||||
try {
|
||||
const pythonCacheDir = getCachePath('uv_python');
|
||||
if (fs.existsSync(pythonCacheDir)) {
|
||||
// Only remove cache if we DON'T have prebuilt Python available
|
||||
// When prebuilt Python exists, UV will use it via UV_PYTHON_INSTALL_DIR
|
||||
if (fs.existsSync(pythonCacheDir) && !prebuiltPythonDir) {
|
||||
log.info(`Removing potentially corrupted Python cache: ${pythonCacheDir}`);
|
||||
fs.rmSync(pythonCacheDir, { recursive: true, force: true });
|
||||
} else if (prebuiltPythonDir) {
|
||||
log.info(`Preserving bundled Python at: ${prebuiltPythonDir}`);
|
||||
}
|
||||
} catch (e) {
|
||||
log.warn(`Failed to remove Python cache: ${e}`);
|
||||
}
|
||||
|
||||
// Cleanup corrupted venv (pyvenv.cfg may reference non-existent Python version)
|
||||
// This is especially important for prebuilt venvs with hardcoded paths from CI
|
||||
const prebuiltVenvPath = getPrebuiltVenvPath();
|
||||
try {
|
||||
// If the broken venv is the prebuilt venv, we need to remove it
|
||||
// and let UV recreate it from the bundled Python
|
||||
if (fs.existsSync(venvPath)) {
|
||||
log.info(`Removing potentially corrupted venv: ${venvPath}`);
|
||||
if (venvPath === prebuiltVenvPath) {
|
||||
log.info(`This is the prebuilt venv with hardcoded paths - will recreate from bundled Python`);
|
||||
}
|
||||
fs.rmSync(venvPath, { recursive: true, force: true });
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -149,8 +149,21 @@ export function getPrebuiltVenvPath(): string | null {
|
|||
if (fs.existsSync(prebuiltVenvPath)) {
|
||||
const pyvenvCfg = path.join(prebuiltVenvPath, 'pyvenv.cfg');
|
||||
if (fs.existsSync(pyvenvCfg)) {
|
||||
log.info(`Using prebuilt venv: ${prebuiltVenvPath}`);
|
||||
return prebuiltVenvPath;
|
||||
// Verify Python executable exists (Windows: Scripts/python.exe, Unix: bin/python)
|
||||
const isWindows = process.platform === 'win32';
|
||||
const pythonExePath = isWindows
|
||||
? path.join(prebuiltVenvPath, 'Scripts', 'python.exe')
|
||||
: path.join(prebuiltVenvPath, 'bin', 'python');
|
||||
|
||||
if (fs.existsSync(pythonExePath)) {
|
||||
log.info(`Using prebuilt venv: ${prebuiltVenvPath}`);
|
||||
return prebuiltVenvPath;
|
||||
} else {
|
||||
log.warn(
|
||||
`Prebuilt venv found but Python executable missing at: ${pythonExePath}. ` +
|
||||
`Falling back to user venv.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -272,6 +285,23 @@ export async function isBinaryExists(name: string): Promise<boolean> {
|
|||
return fs.existsSync(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to prebuilt Python installation (if available in packaged app)
|
||||
*/
|
||||
export function getPrebuiltPythonDir(): string | null {
|
||||
if (!app.isPackaged) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const prebuiltPythonDir = path.join(process.resourcesPath, 'prebuilt', 'uv_python');
|
||||
if (fs.existsSync(prebuiltPythonDir)) {
|
||||
log.info(`Using prebuilt Python: ${prebuiltPythonDir}`);
|
||||
return prebuiltPythonDir;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get unified UV environment variables for consistent Python environment management.
|
||||
* This ensures both installation and runtime use the same paths.
|
||||
|
|
@ -279,8 +309,12 @@ export async function isBinaryExists(name: string): Promise<boolean> {
|
|||
* @returns Environment variables for UV commands
|
||||
*/
|
||||
export function getUvEnv(version: string): Record<string, string> {
|
||||
// Use prebuilt Python if available (packaged app)
|
||||
const prebuiltPython = getPrebuiltPythonDir();
|
||||
const pythonInstallDir = prebuiltPython || getCachePath('uv_python');
|
||||
|
||||
return {
|
||||
UV_PYTHON_INSTALL_DIR: getCachePath('uv_python'),
|
||||
UV_PYTHON_INSTALL_DIR: pythonInstallDir,
|
||||
UV_TOOL_DIR: getCachePath('uv_tool'),
|
||||
UV_PROJECT_ENVIRONMENT: getVenvPath(version),
|
||||
UV_HTTP_TIMEOUT: '300',
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ function isValidSymlink(symlinkPath, bundleRoot) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Fix Python symlinks in venv/bin
|
||||
* Fix Python symlinks in venv/bin (Unix) or venv/Scripts (Windows)
|
||||
* Remove symlinks that point outside the bundle (to cache directory)
|
||||
*/
|
||||
function fixPythonSymlinks(venvBinDir, bundleRoot) {
|
||||
|
|
@ -55,7 +55,10 @@ function fixPythonSymlinks(venvBinDir, bundleRoot) {
|
|||
}
|
||||
|
||||
const bundlePath = path.resolve(bundleRoot);
|
||||
const pythonNames = ['python', 'python3', 'python3.10', 'python3.11', 'python3.12'];
|
||||
const isWindows = process.platform === 'win32';
|
||||
const pythonNames = isWindows
|
||||
? ['python.exe', 'python3.exe', 'python3.10.exe', 'python3.11.exe', 'python3.12.exe']
|
||||
: ['python', 'python3', 'python3.10', 'python3.11', 'python3.12'];
|
||||
|
||||
for (const pythonName of pythonNames) {
|
||||
const pythonSymlink = path.join(venvBinDir, pythonName);
|
||||
|
|
@ -127,7 +130,8 @@ function main() {
|
|||
console.log('🧹 Cleaning invalid symbolic links...');
|
||||
|
||||
const bundleRoot = path.join(projectRoot, 'resources', 'prebuilt');
|
||||
const venvBinDir = path.join(bundleRoot, 'venv', 'bin');
|
||||
const isWindows = process.platform === 'win32';
|
||||
const venvBinDir = path.join(bundleRoot, 'venv', isWindows ? 'Scripts' : 'bin');
|
||||
|
||||
// First, try to fix Python symlinks specifically
|
||||
if (fs.existsSync(venvBinDir)) {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ const __filename = fileURLToPath(import.meta.url);
|
|||
const __dirname = path.dirname(__filename);
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
|
||||
const BIN_DIR = path.join(projectRoot, 'resources', 'prebuilt', 'bin');
|
||||
const VENV_DIR = path.join(projectRoot, 'resources', 'prebuilt', 'venv');
|
||||
const PREBUILT_DIR = path.join(projectRoot, 'resources', 'prebuilt');
|
||||
const BIN_DIR = path.join(PREBUILT_DIR, 'bin');
|
||||
const VENV_DIR = path.join(PREBUILT_DIR, 'venv');
|
||||
const BACKEND_DIR = path.join(projectRoot, 'backend');
|
||||
|
||||
console.log('🚀 Starting pre-installation of dependencies...');
|
||||
|
|
@ -197,6 +198,45 @@ async function downloadFileWithValidation(urlsToTry, dest, validateFn, fileType
|
|||
throw new Error(`Failed to download ${fileType} from all sources`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively copy directory, handling symlinks properly
|
||||
*/
|
||||
function copyDirRecursiveSync(src, dest) {
|
||||
if (!fs.existsSync(src)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create destination directory
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
|
||||
// Get all files and directories
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
copyDirRecursiveSync(srcPath, destPath);
|
||||
} else if (entry.isSymbolicLink()) {
|
||||
try {
|
||||
const realPath = fs.realpathSync(srcPath);
|
||||
const realStat = fs.statSync(realPath);
|
||||
if (realStat.isDirectory()) {
|
||||
copyDirRecursiveSync(realPath, destPath);
|
||||
} else {
|
||||
fs.copyFileSync(realPath, destPath);
|
||||
}
|
||||
} catch (err) {
|
||||
// If symlink target doesn't exist, skip it
|
||||
console.log(` Skipping broken symlink: ${srcPath}`);
|
||||
}
|
||||
} else {
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bun download URL list
|
||||
*/
|
||||
|
|
@ -613,11 +653,66 @@ async function installPythonDeps(uvPath) {
|
|||
console.log('📦 Creating Python venv...');
|
||||
}
|
||||
|
||||
// Ensure Python is installed before syncing
|
||||
// This is critical for Windows where Python might not be in the venv
|
||||
console.log('🐍 Ensuring Python is installed...');
|
||||
try {
|
||||
execSync(
|
||||
`"${uvPath}" python install 3.10`,
|
||||
{ cwd: BACKEND_DIR, env: env, stdio: 'inherit' }
|
||||
);
|
||||
} catch (error) {
|
||||
console.log('⚠️ Python install command failed, continuing with sync (Python may already be installed)...');
|
||||
}
|
||||
|
||||
// Use --python-preference only-managed to ensure uv uses its own managed Python
|
||||
// This makes the venv more portable
|
||||
execSync(
|
||||
`"${uvPath}" sync --no-dev --cache-dir "${cacheDir}"`,
|
||||
`"${uvPath}" sync --no-dev --cache-dir "${cacheDir}" --python-preference only-managed`,
|
||||
{ cwd: BACKEND_DIR, env: env, stdio: 'inherit' }
|
||||
);
|
||||
|
||||
// Verify Python executable exists in the virtual environment
|
||||
const isWindows = process.platform === 'win32';
|
||||
const pythonExePath = isWindows
|
||||
? path.join(venvPath, 'Scripts', 'python.exe')
|
||||
: path.join(venvPath, 'bin', 'python');
|
||||
|
||||
if (!fs.existsSync(pythonExePath)) {
|
||||
throw new Error(
|
||||
`Python executable not found in virtual environment at: ${pythonExePath}\n` +
|
||||
`Virtual environment may be corrupted. Please ensure uv sync completed successfully.`
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`✅ Python executable verified: ${pythonExePath}`);
|
||||
|
||||
// Bundle the actual Python installation from UV cache into prebuilt
|
||||
console.log('📦 Bundling Python installation...');
|
||||
try {
|
||||
const uvPythonDir = pythonCacheDir;
|
||||
const prebuiltPythonDir = path.join(PREBUILT_DIR, 'uv_python');
|
||||
|
||||
if (fs.existsSync(uvPythonDir)) {
|
||||
console.log(` Copying from: ${uvPythonDir}`);
|
||||
console.log(` Copying to: ${prebuiltPythonDir}`);
|
||||
|
||||
// Remove existing python dir if it exists
|
||||
if (fs.existsSync(prebuiltPythonDir)) {
|
||||
fs.rmSync(prebuiltPythonDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
// Copy the Python installation
|
||||
copyDirRecursiveSync(uvPythonDir, prebuiltPythonDir);
|
||||
console.log('✅ Python installation bundled');
|
||||
} else {
|
||||
console.log('⚠️ UV Python cache not found, venv may not be portable');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`⚠️ Failed to bundle Python: ${error.message}`);
|
||||
console.log(' The app may fail to start without internet connection');
|
||||
}
|
||||
|
||||
console.log('✅ Python dependencies installed');
|
||||
|
||||
console.log('📝 Compiling babel...');
|
||||
|
|
|
|||
296
scripts/test-notarization.js
Normal file
296
scripts/test-notarization.js
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Test script for macOS notarization issues
|
||||
* This script checks for common issues that cause notarization to fail:
|
||||
* 1. .npm-cache directories
|
||||
* 2. flac-mac binary (outdated SDK)
|
||||
* 3. Unsigned native binaries (.node files)
|
||||
* 4. Other problematic files
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { execSync } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
|
||||
const RELEASE_DIR = path.join(projectRoot, 'release');
|
||||
const APP_BUNDLE_PATTERN = /Eigent\.app$/;
|
||||
|
||||
/**
|
||||
* Find the app bundle in release directory
|
||||
*/
|
||||
function findAppBundle() {
|
||||
if (!fs.existsSync(RELEASE_DIR)) {
|
||||
console.log('❌ Release directory does not exist. Please build the app first.');
|
||||
console.log(' Run: npm run build:mac');
|
||||
return null;
|
||||
}
|
||||
|
||||
const entries = fs.readdirSync(RELEASE_DIR, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory() && entry.name.match(APP_BUNDLE_PATTERN)) {
|
||||
return path.join(RELEASE_DIR, entry.name);
|
||||
}
|
||||
|
||||
// Check subdirectories (e.g., mac-arm64/Eigent.app)
|
||||
if (entry.isDirectory()) {
|
||||
const subDir = path.join(RELEASE_DIR, entry.name);
|
||||
const subEntries = fs.readdirSync(subDir, { withFileTypes: true });
|
||||
for (const subEntry of subEntries) {
|
||||
if (subEntry.isDirectory() && subEntry.name.match(APP_BUNDLE_PATTERN)) {
|
||||
return path.join(subDir, subEntry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for .npm-cache directories
|
||||
*/
|
||||
function checkNpmCache(bundlePath) {
|
||||
console.log('\n🔍 Checking for .npm-cache directories...');
|
||||
const issues = [];
|
||||
|
||||
function scanDir(dir) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.name === '.npm-cache' && entry.isDirectory()) {
|
||||
issues.push(fullPath);
|
||||
} else if (entry.isDirectory()) {
|
||||
// Skip node_modules to avoid deep scanning
|
||||
if (entry.name !== 'node_modules' && entry.name !== '__pycache__') {
|
||||
scanDir(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
const resourcesPath = path.join(bundlePath, 'Contents', 'Resources');
|
||||
const prebuiltPath = path.join(resourcesPath, 'prebuilt');
|
||||
|
||||
if (fs.existsSync(prebuiltPath)) {
|
||||
scanDir(prebuiltPath);
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
console.log(`❌ Found ${issues.length} .npm-cache directory(ies):`);
|
||||
issues.forEach(issue => console.log(` - ${issue}`));
|
||||
return false;
|
||||
} else {
|
||||
console.log('✅ No .npm-cache directories found');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for flac-mac binary
|
||||
*/
|
||||
function checkFlacMac(bundlePath) {
|
||||
console.log('\n🔍 Checking for flac-mac binary...');
|
||||
const issues = [];
|
||||
|
||||
const resourcesPath = path.join(bundlePath, 'Contents', 'Resources');
|
||||
const prebuiltPath = path.join(resourcesPath, 'prebuilt');
|
||||
const venvLibPath = path.join(prebuiltPath, 'venv', 'lib');
|
||||
|
||||
if (fs.existsSync(venvLibPath)) {
|
||||
try {
|
||||
const entries = fs.readdirSync(venvLibPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory() && entry.name.startsWith('python')) {
|
||||
const flacMacPath = path.join(venvLibPath, entry.name, 'site-packages', 'speech_recognition', 'flac-mac');
|
||||
if (fs.existsSync(flacMacPath)) {
|
||||
issues.push(flacMacPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
console.log(`❌ Found ${issues.length} flac-mac binary(ies) (outdated SDK):`);
|
||||
issues.forEach(issue => console.log(` - ${issue}`));
|
||||
return false;
|
||||
} else {
|
||||
console.log('✅ No flac-mac binaries found');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for unsigned native binaries
|
||||
*/
|
||||
function checkUnsignedBinaries(bundlePath) {
|
||||
console.log('\n🔍 Checking for unsigned native binaries (.node files)...');
|
||||
const issues = [];
|
||||
|
||||
function scanForNodeFiles(dir) {
|
||||
if (!fs.existsSync(dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isFile() && entry.name.endsWith('.node')) {
|
||||
// Check if file is signed
|
||||
try {
|
||||
const output = execSync(`codesign -dv "${fullPath}" 2>&1 || true`, { encoding: 'utf-8' });
|
||||
if (output.includes('code object is not signed')) {
|
||||
issues.push({
|
||||
path: fullPath,
|
||||
reason: 'Not signed'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// If codesign fails, assume it's not signed
|
||||
issues.push({
|
||||
path: fullPath,
|
||||
reason: 'Could not verify signature'
|
||||
});
|
||||
}
|
||||
} else if (entry.isDirectory()) {
|
||||
// Skip certain directories
|
||||
if (entry.name !== 'node_modules' && entry.name !== '__pycache__' && !entry.name.startsWith('.')) {
|
||||
scanForNodeFiles(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
const resourcesPath = path.join(bundlePath, 'Contents', 'Resources');
|
||||
const prebuiltPath = path.join(resourcesPath, 'prebuilt');
|
||||
|
||||
if (fs.existsSync(prebuiltPath)) {
|
||||
scanForNodeFiles(prebuiltPath);
|
||||
}
|
||||
|
||||
if (issues.length > 0) {
|
||||
console.log(`❌ Found ${issues.length} unsigned .node file(s):`);
|
||||
issues.forEach(issue => {
|
||||
console.log(` - ${issue.path}`);
|
||||
console.log(` Reason: ${issue.reason}`);
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
console.log('✅ No unsigned .node files found');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check app bundle size
|
||||
*/
|
||||
function checkBundleSize(bundlePath) {
|
||||
console.log('\n🔍 Checking app bundle size...');
|
||||
|
||||
try {
|
||||
function getDirSize(dir) {
|
||||
let size = 0;
|
||||
try {
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
if (entry.isFile()) {
|
||||
size += fs.statSync(fullPath).size;
|
||||
} else if (entry.isDirectory()) {
|
||||
size += getDirSize(fullPath);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore errors
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
const size = getDirSize(bundlePath);
|
||||
const sizeInMB = (size / (1024 * 1024)).toFixed(2);
|
||||
console.log(` App bundle size: ${sizeInMB} MB`);
|
||||
|
||||
if (size > 500 * 1024 * 1024) {
|
||||
console.log(` ⚠️ Large bundle size (>500MB) may cause slow notarization (30-60 minutes)`);
|
||||
} else if (size > 200 * 1024 * 1024) {
|
||||
console.log(` ⚠️ Medium bundle size (200-500MB) may take 15-30 minutes to notarize`);
|
||||
} else {
|
||||
console.log(` ✅ Bundle size is reasonable for notarization`);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` ⚠️ Could not calculate bundle size: ${error.message}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
function main() {
|
||||
console.log('🧪 macOS Notarization Test Script\n');
|
||||
|
||||
const appBundle = findAppBundle();
|
||||
|
||||
if (!appBundle) {
|
||||
console.log('\n💡 To build the app for testing:');
|
||||
console.log(' npm run build:mac');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`📦 Found app bundle: ${appBundle}\n`);
|
||||
|
||||
const results = {
|
||||
npmCache: checkNpmCache(appBundle),
|
||||
flacMac: checkFlacMac(appBundle),
|
||||
unsignedBinaries: checkUnsignedBinaries(appBundle),
|
||||
bundleSize: checkBundleSize(appBundle),
|
||||
};
|
||||
|
||||
console.log('\n📊 Summary:');
|
||||
console.log(` .npm-cache directories: ${results.npmCache ? '✅' : '❌'}`);
|
||||
console.log(` flac-mac binaries: ${results.flacMac ? '✅' : '❌'}`);
|
||||
console.log(` Unsigned .node files: ${results.unsignedBinaries ? '✅' : '❌'}`);
|
||||
console.log(` Bundle size: ${results.bundleSize ? '✅' : '⚠️'}`);
|
||||
|
||||
const allPassed = Object.values(results).every(r => r);
|
||||
|
||||
if (allPassed) {
|
||||
console.log('\n✅ All checks passed! The app should be ready for notarization.');
|
||||
console.log('\n💡 Note: This script only checks for common issues.');
|
||||
console.log(' Actual notarization may still fail for other reasons.');
|
||||
console.log(' To test actual notarization, you need:');
|
||||
console.log(' - Valid Apple Developer ID certificate');
|
||||
console.log(' - APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID environment variables');
|
||||
} else {
|
||||
console.log('\n❌ Some checks failed. Please fix the issues above before notarization.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue