Files
Aperant/apps/frontend/scripts/verify-python-bundling.cjs
T
Andy 0b2cf9b06c ci: migrate ESLint to Biome, optimize workflows, fix tar vulnerability (#1289)
* ci: migrate ESLint to Biome, optimize workflows, fix tar vulnerability

- Replace ESLint with Biome (15-25x faster linting)
- Pin Biome to 2.3.11 for consistent behavior across local/CI
- Disable useArrowFunction rule (breaks vitest constructor mocks)
- Add composite actions for DRY workflow setup
- Fix tar vulnerability (CVE-2026-23745) by upgrading to v7.5.3
- Add @electron/rebuild override to ensure consistent tar version
- Update electron-builder to 26.4.0

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(workflows): address all 15 PR review findings

HIGH priority fixes:
- Add tar@7.5.3 override to frontend package.json (CVE-2026-23745)
- Use setup-node-frontend composite action in release.yml (4 build jobs)
- Use setup-node-frontend composite action in beta-release.yml (4 build jobs)

MEDIUM priority fixes:
- Add notarization status verification ('Accepted') before stapling
- Add blockmap files to beta-release asset copying (delta updates)
- Add DMG validation with fallback in release.yml
- Extract yq checksum to env block, single definition per step
- Fix snake_case to kebab-case in notarization action outputs

LOW priority fixes:
- Add config files (pyproject.toml, tsconfig*.json, biome.jsonc) to CI paths
- Document yq checksum requirement in merge-macos-manifests
- Always use jq for notarization ID parsing (no regex fallback)
- Add blockmap files to dry-run-summary job
- Change noControlCharactersInRegex from off to warn
- Rename biome.json to biome.jsonc, add comments explaining disabled rules

noSecrets rule kept off due to 2700+ false positives on normal strings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(lint): correct biome.jsonc path in workflow triggers

The lint workflow path filter referenced 'biome.json' but the actual
config file is 'biome.jsonc' (renamed to support comments). This fix
ensures the lint workflow triggers when the Biome config is modified.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(workflows): address 6 PR review findings

- QUAL-001/002: Add DMG file existence checks before stapling
- QUAL-003: Quote all path variables in merge-macos-manifests
- QUAL-004: Add semver validation in update-readme.py
- QUAL-005: Document noDangerouslySetInnerHtml security rule decision
- LOGIC-001: Add warning when both notarization IDs are empty

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(workflows): add gate jobs for branch protection

Add summary/gate jobs to match existing branch protection rules:
- CI Complete: aggregates test-python and test-frontend results
- Lint Complete: aggregates python and typescript lint results
- Security Summary: aggregates codeql and python-security results

These jobs provide a single status check for branch protection instead
of requiring individual job names which can change with matrix configs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 14:29:50 +01:00

103 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
/**
* Verify Python bundling configuration is correct.
* Run this before packaging to ensure Python will be properly bundled.
*/
const fs = require('fs');
const path = require('path');
const { execSync, spawnSync } = require('child_process');
const FRONTEND_DIR = path.resolve(__dirname, '..');
const PYTHON_RUNTIME_DIR = path.join(FRONTEND_DIR, 'python-runtime');
console.log('=== Python Bundling Verification ===\n');
// Check 1: Python runtime downloaded?
console.log('1. Checking if Python runtime is downloaded...');
const platform = process.platform === 'win32' ? 'win' : process.platform === 'darwin' ? 'mac' : 'linux';
const arch = process.arch;
const runtimePath = path.join(PYTHON_RUNTIME_DIR, `${platform}-${arch}`, 'python');
if (fs.existsSync(runtimePath)) {
const pythonExe = process.platform === 'win32'
? path.join(runtimePath, 'python.exe')
: path.join(runtimePath, 'bin', 'python3');
if (fs.existsSync(pythonExe)) {
console.log(` ✓ Found bundled Python at: ${pythonExe}`);
// Test version
try {
const version = execSync(`"${pythonExe}" --version`, { encoding: 'utf8' }).trim();
console.log(` ✓ Version: ${version}`);
} catch (e) {
console.log(` ✗ Failed to get version: ${e.message}`);
}
} else {
console.log(` ✗ Python executable not found at: ${pythonExe}`);
}
} else {
console.log(` ✗ Python runtime not downloaded. Run: npm run python:download`);
}
// Check 2: package.json extraResources configured?
console.log('\n2. Checking package.json extraResources configuration...');
const packageJson = require(path.join(FRONTEND_DIR, 'package.json'));
const extraResources = packageJson.build?.extraResources || [];
const pythonResource = extraResources.find(r =>
(typeof r === 'string' && r.includes('python')) ||
(typeof r === 'object' && r.from?.includes('python'))
);
if (pythonResource) {
console.log(' ✓ Python is configured in extraResources:');
console.log(` ${JSON.stringify(pythonResource)}`);
} else {
console.log(' ✗ Python not found in extraResources configuration');
}
// Check 3: Test venv creation simulation
console.log('\n3. Checking venv creation capability...');
try {
// Find system Python for testing
const pythonCmd = process.platform === 'win32' ? 'python' : 'python3';
const result = spawnSync(pythonCmd, ['-m', 'venv', '--help'], { encoding: 'utf8' });
if (result.status === 0) {
console.log(` ✓ venv module is available`);
} else {
console.log(` ✗ venv module not available: ${result.stderr}`);
}
} catch (e) {
console.log(` ✗ Failed to check venv: ${e.message}`);
}
// Check 4: Verify requirements.txt exists
console.log('\n4. Checking requirements.txt...');
const backendDir = path.join(FRONTEND_DIR, '..', 'backend');
const requirementsPath = path.join(backendDir, 'requirements.txt');
if (fs.existsSync(requirementsPath)) {
const content = fs.readFileSync(requirementsPath, 'utf8');
const hasDotenv = content.includes('python-dotenv');
const hasSDK = content.includes('claude-agent-sdk');
console.log(` ✓ requirements.txt found`);
console.log(` ${hasDotenv ? '✓' : '✗'} python-dotenv: ${hasDotenv ? 'present' : 'MISSING!'}`);
console.log(` ${hasSDK ? '✓' : '✗'} claude-agent-sdk: ${hasSDK ? 'present' : 'MISSING!'}`);
} else {
console.log(` ✗ requirements.txt not found at: ${requirementsPath}`);
}
// Summary
console.log('\n=== Summary ===');
console.log('To fully test Python bundling:');
console.log('1. Run: npm run python:download');
console.log('2. Run: npm run package:win (or :mac/:linux)');
console.log('3. Launch the packaged app and check Dev Tools console for:');
console.log(' - "[Python] Found bundled Python at: ..."');
console.log(' - "[PythonEnvManager] Ready with Python path: ..."');
console.log('4. Try creating and running a task - should work without dotenv errors');