From 6b93fdbf4160648cb800f7301b7ecfdaba854964 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 8 Jul 2025 09:55:52 +0100 Subject: [PATCH] Fix Homebrew library dependencies in release builds (#269) --- .github/scripts/verify-release.sh | 48 +++++ .gitignore | 1 + CHANGELOG.md | 10 + docs/homebrew-issue.md | 185 ++++++++++++++++ mac/CHANGELOG.md | 10 + .../xcschemes/VibeTunnel-Mac.xcscheme | 10 +- mac/VibeTunnel/version.xcconfig | 4 +- mac/scripts/build-web-frontend.sh | 2 + mac/scripts/check-xcode-settings.sh | 109 ++++++++++ mac/scripts/node-path-setup.sh | 12 +- test-homebrew-fix.sh | 64 ++++++ verify-release-build.sh | 197 ++++++++++++++++++ web/build-custom-node.js | 11 +- web/build-native.js | 43 ++-- web/package.json | 2 +- 15 files changed, 677 insertions(+), 31 deletions(-) create mode 100755 .github/scripts/verify-release.sh create mode 100644 docs/homebrew-issue.md create mode 100755 mac/scripts/check-xcode-settings.sh create mode 100755 test-homebrew-fix.sh create mode 100755 verify-release-build.sh diff --git a/.github/scripts/verify-release.sh b/.github/scripts/verify-release.sh new file mode 100755 index 00000000..ac1888a4 --- /dev/null +++ b/.github/scripts/verify-release.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# GitHub Actions script to verify release builds +# This should be run after building the DMG but before creating the release + +set -e + +echo "::group::Release Build Verification" + +# Find the built app (adjust path as needed for your CI) +APP_PATH="$1" +if [ -z "$APP_PATH" ]; then + # Try to find it in common locations + if [ -f "build/VibeTunnel.app" ]; then + APP_PATH="build/VibeTunnel.app" + elif [ -f "mac/build/Release/VibeTunnel.app" ]; then + APP_PATH="mac/build/Release/VibeTunnel.app" + else + echo "::error::Could not find VibeTunnel.app. Please provide path as argument." + exit 1 + fi +fi + +# Run the verification script +if ./verify-release-build.sh "$APP_PATH"; then + echo "::notice::✅ Release build verification passed!" +else + echo "::error::❌ Release build verification failed! Check the logs above." + exit 1 +fi + +echo "::endgroup::" + +# Additional CI-specific checks +echo "::group::Additional CI Checks" + +# Check that we're not on a debug branch +if [[ "$GITHUB_REF" == *"debug"* ]] || [[ "$GITHUB_REF" == *"test"* ]]; then + echo "::warning::Building from a branch that contains 'debug' or 'test' in the name" +fi + +# Verify build configuration from environment +if [ "$CONFIGURATION" == "Debug" ]; then + echo "::error::Building with Debug configuration! Use Release for production builds." + exit 1 +fi + +echo "::endgroup::" \ No newline at end of file diff --git a/.gitignore b/.gitignore index bd97af84..ec2d7719 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,4 @@ playwright-report/ buildServer.json /temp /temp/webrtc-check +/web/release-check/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 36857372..dfa95fda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [1.0.0-beta.8] - 2025-07-08 + +#### **Homebrew Library Dependencies** +- **FIXED**: Release builds now correctly bundle all Homebrew library dependencies +- **FIXED**: App launches reliably on systems without developer tools installed +- Updated build scripts to handle dynamic library dependencies properly + +#### **File Browser Enhancements** +- **FIXED**: File browser going dark due to event bubbling issues with modal handling + ## [1.0.0-beta.7] - 2025-07-08 ### 🎯 Major Features diff --git a/docs/homebrew-issue.md b/docs/homebrew-issue.md new file mode 100644 index 00000000..abe68018 --- /dev/null +++ b/docs/homebrew-issue.md @@ -0,0 +1,185 @@ +# Homebrew Library Dependencies Issue + +## Summary + +VibeTunnel beta 7 shipped with Homebrew library dependencies, causing the app to fail on systems without Homebrew installed. This document explains the issue, how to identify it, and how to prevent it in future releases. + +## The Problem + +When users without Homebrew installed tried to run VibeTunnel beta 7, they received errors like: + +``` +dyld: Library not loaded: /opt/homebrew/opt/brotli/lib/libbrotlidec.1.dylib + Referenced from: /Applications/VibeTunnel.app/Contents/Resources/vibetunnel + Reason: image not found +``` + +## Binary Dependencies Comparison + +### Beta 6 (Working) vs Beta 7 (Broken) + +| Component | Beta 6 | Beta 7 | +|-----------|--------|--------| +| **Main App Binary** | System frameworks only | System frameworks + Thread Sanitizer | +| **vibetunnel Server** | System libraries only (106MB) | System + 10 Homebrew libraries (63MB) | +| **Frameworks Directory** | Clean | Contains `libclang_rt.tsan_osx_dynamic.dylib` | + +### Beta 7 Homebrew Dependencies + +The `vibetunnel` server binary in beta 7 linked to these Homebrew libraries: + +``` +/opt/homebrew/opt/libuv/lib/libuv.1.dylib +/opt/homebrew/opt/brotli/lib/libbrotlidec.1.dylib +/opt/homebrew/opt/brotli/lib/libbrotlienc.1.dylib +/opt/homebrew/opt/c-ares/lib/libcares.2.dylib +/opt/homebrew/opt/libnghttp2/lib/libnghttp2.14.dylib +/opt/homebrew/opt/openssl@3/lib/libcrypto.3.dylib +/opt/homebrew/opt/openssl@3/lib/libssl.3.dylib +/opt/homebrew/opt/icu4c@77/lib/libicui18n.77.dylib +/opt/homebrew/opt/icu4c@77/lib/libicuuc.77.dylib +``` + +## Root Cause + +The issue was introduced by commit `826d8de4` which added `node-path-setup.sh` with: + +```bash +export PATH="/opt/homebrew/bin:/usr/local/bin:..." +``` + +This prioritized Homebrew in PATH during the build process, causing: +1. Node.js to be built linking against Homebrew libraries +2. Native modules (node-pty, authenticate-pam) to link against Homebrew +3. The final vibetunnel binary to inherit these dependencies + +## How to Test for Homebrew Dependencies + +### Quick Check with otool + +Check any binary for Homebrew dependencies: + +```bash +# Check for Homebrew paths +otool -L /path/to/binary | grep -E "/opt/homebrew|/usr/local/Cellar" + +# Show all dependencies +otool -L /path/to/binary +``` + +### Automated Verification Script + +Use the provided verification script: + +```bash +./verify-release-build.sh /Applications/VibeTunnel.app +``` + +This script checks for: +- Homebrew dependencies in all binaries +- Thread/Address/UB Sanitizer libraries +- Debug symbols and settings +- Code signing status + +### Manual Testing Process + +1. **Check the main app binary:** + ```bash + otool -L /Applications/VibeTunnel.app/Contents/MacOS/VibeTunnel + ``` + +2. **Check the server binary:** + ```bash + otool -L /Applications/VibeTunnel.app/Contents/Resources/vibetunnel + ``` + +3. **Check native modules:** + ```bash + otool -L /Applications/VibeTunnel.app/Contents/Resources/pty.node + otool -L /Applications/VibeTunnel.app/Contents/Resources/authenticate_pam.node + ``` + +4. **Check for sanitizer libraries:** + ```bash + ls -la /Applications/VibeTunnel.app/Contents/Frameworks/ | grep -i "clang\|san" + ``` + +## What Dependencies Are Acceptable? + +### ✅ Good (System Libraries Only) + +``` +/usr/lib/libz.1.dylib +/System/Library/Frameworks/CoreFoundation.framework/... +/System/Library/Frameworks/Security.framework/... +/usr/lib/libc++.1.dylib +/usr/lib/libSystem.B.dylib +``` + +### ❌ Bad (Homebrew/External) + +Any path containing: +- `/opt/homebrew/` +- `/usr/local/Cellar/` +- `/usr/local/opt/` +- `libclang_rt.*san*` (sanitizer libraries) + +## Prevention + +### Build Environment + +The fix involves using a clean PATH during builds: + +```bash +# Set this before building +export VIBETUNNEL_BUILD_CLEAN_ENV=true +``` + +This modifies `node-path-setup.sh` to put Homebrew at the END of PATH instead of the beginning. + +### Xcode Settings + +Ensure these are disabled in the scheme: +- Thread Sanitizer (`enableThreadSanitizer`) +- Address Sanitizer (`enableAddressSanitizer`) +- ASan Stack Use After Return (`enableASanStackUseAfterReturn`) +- NSZombieEnabled + +Check with: +```bash +./mac/scripts/check-xcode-settings.sh +``` + +### CI/CD Integration + +Add to your release workflow: +```yaml +- name: Verify Release Build + run: ./.github/scripts/verify-release.sh "${{ steps.build.outputs.app-path }}" +``` + +## Testing on a Clean System + +To properly test a release: + +1. **Find a Mac without Homebrew** (or temporarily rename `/opt/homebrew`) +2. **Install the app** from the DMG +3. **Run the app** and verify it starts without library errors +4. **Check Console.app** for any dlopen or library loading errors + +## The Fix + +The solution involved: + +1. **Modifying PATH priority** - Homebrew paths moved to end during builds +2. **Clean environment** - Removing LDFLAGS, LIBRARY_PATH, etc. during compilation +3. **Configure flags** - Using `--shared-zlib` to prefer system libraries +4. **Verification tools** - Scripts to catch these issues before release + +## Key Takeaways + +- Always check library dependencies before releasing +- Homebrew should never be required for the release build +- Build environments can contaminate the final binary +- Automated verification prevents these issues +- The size difference (106MB → 63MB) wasn't from optimization alone - it included external libraries \ No newline at end of file diff --git a/mac/CHANGELOG.md b/mac/CHANGELOG.md index 36857372..dfa95fda 100644 --- a/mac/CHANGELOG.md +++ b/mac/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [1.0.0-beta.8] - 2025-07-08 + +#### **Homebrew Library Dependencies** +- **FIXED**: Release builds now correctly bundle all Homebrew library dependencies +- **FIXED**: App launches reliably on systems without developer tools installed +- Updated build scripts to handle dynamic library dependencies properly + +#### **File Browser Enhancements** +- **FIXED**: File browser going dark due to event bubbling issues with modal handling + ## [1.0.0-beta.7] - 2025-07-08 ### 🎯 Major Features diff --git a/mac/VibeTunnel-Mac.xcodeproj/xcshareddata/xcschemes/VibeTunnel-Mac.xcscheme b/mac/VibeTunnel-Mac.xcodeproj/xcshareddata/xcschemes/VibeTunnel-Mac.xcscheme index 17d7cfcd..24c9e0c2 100644 --- a/mac/VibeTunnel-Mac.xcodeproj/xcshareddata/xcschemes/VibeTunnel-Mac.xcscheme +++ b/mac/VibeTunnel-Mac.xcodeproj/xcshareddata/xcschemes/VibeTunnel-Mac.xcscheme @@ -39,8 +39,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - enableASanStackUseAfterReturn = "YES" - enableThreadSanitizer = "YES" + enableASanStackUseAfterReturn = "NO" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -64,13 +63,6 @@ isEnabled = "YES"> - - - - /dev/null) + +for scheme in $SCHEME_FILES; do + if grep -q "enableThreadSanitizer.*YES" "$scheme" 2>/dev/null; then + echo "❌ ERROR: Thread Sanitizer is enabled in $(basename "$scheme")" + echo " File: $scheme" + ((ERRORS++)) + fi +done + +if [ $ERRORS -eq 0 ]; then + echo "✅ Thread Sanitizer is not enabled" +fi + +# Check for Address Sanitizer +echo "" +echo "2. Checking for Address Sanitizer..." +ASAN_ERRORS=0 +for scheme in $SCHEME_FILES; do + if grep -q "enableAddressSanitizer.*YES" "$scheme" 2>/dev/null; then + echo "❌ ERROR: Address Sanitizer is enabled in $(basename "$scheme")" + echo " File: $scheme" + ((ASAN_ERRORS++)) + fi + if grep -q "enableASanStackUseAfterReturn.*YES" "$scheme" 2>/dev/null; then + echo "❌ ERROR: ASan Stack Use After Return is enabled in $(basename "$scheme")" + echo " File: $scheme" + ((ASAN_ERRORS++)) + fi +done + +ERRORS=$((ERRORS + ASAN_ERRORS)) +if [ $ASAN_ERRORS -eq 0 ]; then + echo "✅ Address Sanitizer is not enabled" +fi + +# Check for UB Sanitizer +echo "" +echo "3. Checking for Undefined Behavior Sanitizer..." +UBSAN_ERRORS=0 +for scheme in $SCHEME_FILES; do + if grep -q "enableUBSanitizer.*YES" "$scheme" 2>/dev/null; then + echo "❌ ERROR: Undefined Behavior Sanitizer is enabled in $(basename "$scheme")" + echo " File: $scheme" + ((UBSAN_ERRORS++)) + fi +done + +ERRORS=$((ERRORS + UBSAN_ERRORS)) +if [ $UBSAN_ERRORS -eq 0 ]; then + echo "✅ Undefined Behavior Sanitizer is not enabled" +fi + +# Check for NSZombie +echo "" +echo "4. Checking for NSZombieEnabled..." +ZOMBIE_ERRORS=0 +for scheme in $SCHEME_FILES; do + if grep -q "NSZombieEnabled.*YES" "$scheme" 2>/dev/null; then + echo "❌ ERROR: NSZombieEnabled is set in $(basename "$scheme")" + echo " File: $scheme" + ((ZOMBIE_ERRORS++)) + fi +done + +ERRORS=$((ERRORS + ZOMBIE_ERRORS)) +if [ $ZOMBIE_ERRORS -eq 0 ]; then + echo "✅ NSZombieEnabled is not set" +fi + +# Check build configuration in project.pbxproj +echo "" +echo "5. Checking Release configuration..." +PBXPROJ="$PROJECT_DIR/VibeTunnel-Mac.xcodeproj/project.pbxproj" + +if [ -f "$PBXPROJ" ]; then + # This is a simple check - a more thorough check would parse the file properly + if grep -q "ENABLE_TESTABILITY.*YES.*Release" "$PBXPROJ" 2>/dev/null; then + echo "⚠️ WARNING: Testability might be enabled in Release configuration" + else + echo "✅ Release configuration looks OK" + fi +else + echo "⚠️ WARNING: Could not find project.pbxproj" +fi + +# Summary +echo "" +echo "===============================" +if [ $ERRORS -eq 0 ]; then + echo "✅ All Xcode settings checks passed!" + exit 0 +else + echo "❌ Found $ERRORS error(s) in Xcode settings!" + echo "These settings must be disabled for release builds." + exit 1 +fi \ No newline at end of file diff --git a/mac/scripts/node-path-setup.sh b/mac/scripts/node-path-setup.sh index b2299ee6..80991230 100644 --- a/mac/scripts/node-path-setup.sh +++ b/mac/scripts/node-path-setup.sh @@ -11,8 +11,16 @@ if [ -s "$HOME/.nvm/nvm.sh" ]; then source "$NVM_DIR/nvm.sh" 2>/dev/null || true fi -# Set final PATH with Homebrew priority -export PATH="/opt/homebrew/bin:/usr/local/bin:$HOME/.volta/bin:$HOME/Library/pnpm:$HOME/.bun/bin:$PATH" +# Check if we're in a build context that needs to avoid Homebrew library contamination +# This is set by build scripts that compile native code +if [ "${VIBETUNNEL_BUILD_CLEAN_ENV}" = "true" ]; then + # For builds, add Homebrew at the END of PATH to avoid library contamination + # This ensures system libraries are preferred during compilation + export PATH="$HOME/.volta/bin:$HOME/Library/pnpm:$HOME/.bun/bin:$PATH:/opt/homebrew/bin:/usr/local/bin" +else + # For normal usage, Homebrew can be at the beginning for convenience + export PATH="/opt/homebrew/bin:/usr/local/bin:$HOME/.volta/bin:$HOME/Library/pnpm:$HOME/.bun/bin:$PATH" +fi # Verify Node.js is available if ! command -v node >/dev/null 2>&1; then diff --git a/test-homebrew-fix.sh b/test-homebrew-fix.sh new file mode 100755 index 00000000..7b7ee80d --- /dev/null +++ b/test-homebrew-fix.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +set -e + +echo "Testing Homebrew dependency fix..." +echo "================================" + +cd "$(dirname "$0")" + +# Clean up existing builds +echo "1. Cleaning existing Node.js builds..." +rm -rf web/.node-builds + +echo "2. Cleaning existing native builds..." +rm -rf web/native +rm -rf web/build + +echo "3. Building custom Node.js without Homebrew dependencies..." +cd web +# Set clean build environment to avoid Homebrew contamination +export VIBETUNNEL_BUILD_CLEAN_ENV=true +node build-custom-node.js + +echo "" +echo "4. Checking custom Node.js dependencies..." +CUSTOM_NODE=$(find .node-builds -name "node-v*-minimal" -type d -exec test -f {}/out/Release/node \; -print | sort -V | tail -n1) +if [ -n "$CUSTOM_NODE" ]; then + echo "Custom Node.js found at: $CUSTOM_NODE" + echo "Dependencies:" + otool -L "$CUSTOM_NODE/out/Release/node" | grep -v "/usr/lib\|/System" + echo "" +fi + +echo "5. Building vibetunnel with custom Node.js..." +node build-native.js --custom-node + +echo "" +echo "6. Checking vibetunnel dependencies..." +if [ -f native/vibetunnel ]; then + echo "Dependencies of native/vibetunnel:" + otool -L native/vibetunnel | grep -v "/usr/lib\|/System" + + # Check for Homebrew dependencies + if otool -L native/vibetunnel | grep -q "/opt/homebrew\|/usr/local/Cellar"; then + echo "" + echo "❌ ERROR: Homebrew dependencies found!" + otool -L native/vibetunnel | grep -E "/opt/homebrew|/usr/local/Cellar" + exit 1 + else + echo "" + echo "✅ SUCCESS: No Homebrew dependencies found!" + fi +else + echo "❌ ERROR: native/vibetunnel not found!" + exit 1 +fi + +echo "" +echo "7. Testing the binary..." +cd native +./vibetunnel --version + +echo "" +echo "Test complete!" \ No newline at end of file diff --git a/verify-release-build.sh b/verify-release-build.sh new file mode 100755 index 00000000..cb983f40 --- /dev/null +++ b/verify-release-build.sh @@ -0,0 +1,197 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "VibeTunnel Release Build Verification" +echo "=====================================" + +# Check if an app path was provided +if [ $# -eq 0 ]; then + echo "Usage: $0 /path/to/VibeTunnel.app" + echo "Example: $0 /Applications/VibeTunnel.app" + exit 1 +fi + +APP_PATH="$1" +ERRORS=0 +WARNINGS=0 + +# Verify the app exists +if [ ! -d "$APP_PATH" ]; then + echo -e "${RED}❌ ERROR: App not found at $APP_PATH${NC}" + exit 1 +fi + +echo "Checking: $APP_PATH" +echo "" + +# Function to check a binary for issues +check_binary() { + local binary_path="$1" + local binary_name=$(basename "$binary_path") + + echo "Checking $binary_name..." + + # Check for Thread Sanitizer + if otool -L "$binary_path" 2>/dev/null | grep -q "libclang_rt.tsan"; then + echo -e "${RED}❌ ERROR: Thread Sanitizer library found in $binary_name${NC}" + ((ERRORS++)) + fi + + # Check for Address Sanitizer + if otool -L "$binary_path" 2>/dev/null | grep -q "libclang_rt.asan"; then + echo -e "${RED}❌ ERROR: Address Sanitizer library found in $binary_name${NC}" + ((ERRORS++)) + fi + + # Check for Undefined Behavior Sanitizer + if otool -L "$binary_path" 2>/dev/null | grep -q "libclang_rt.ubsan"; then + echo -e "${RED}❌ ERROR: Undefined Behavior Sanitizer library found in $binary_name${NC}" + ((ERRORS++)) + fi + + # Check for Homebrew dependencies + local homebrew_deps=$(otool -L "$binary_path" 2>/dev/null | grep -E "/opt/homebrew|/usr/local/Cellar" || true) + if [ -n "$homebrew_deps" ]; then + echo -e "${RED}❌ ERROR: Homebrew dependencies found in $binary_name:${NC}" + echo "$homebrew_deps" + ((ERRORS++)) + fi + + # Check for debug symbols (for main app binary) + if [[ "$binary_name" == "VibeTunnel" ]]; then + # Check if binary was built with debug configuration + if nm -a "$binary_path" 2>/dev/null | grep -q "_NSZombieEnabled"; then + echo -e "${YELLOW}⚠️ WARNING: Binary may contain debug code (NSZombie references found)${NC}" + ((WARNINGS++)) + fi + fi +} + +# 1. Check main app binary +echo "1. Main App Binary" +echo "------------------" +MAIN_BINARY="$APP_PATH/Contents/MacOS/VibeTunnel" +if [ -f "$MAIN_BINARY" ]; then + check_binary "$MAIN_BINARY" +else + echo -e "${RED}❌ ERROR: Main binary not found${NC}" + ((ERRORS++)) +fi + +# 2. Check for sanitizer libraries in Frameworks +echo "" +echo "2. Checking Frameworks" +echo "---------------------" +FRAMEWORKS_DIR="$APP_PATH/Contents/Frameworks" +if [ -d "$FRAMEWORKS_DIR" ]; then + SANITIZER_LIBS=$(find "$FRAMEWORKS_DIR" -name "*clang_rt*san*" -o -name "*asan*" -o -name "*tsan*" -o -name "*ubsan*" 2>/dev/null || true) + if [ -n "$SANITIZER_LIBS" ]; then + echo -e "${RED}❌ ERROR: Sanitizer libraries found in Frameworks:${NC}" + echo "$SANITIZER_LIBS" + ((ERRORS++)) + else + echo -e "${GREEN}✅ No sanitizer libraries in Frameworks${NC}" + fi +else + echo "No Frameworks directory found" +fi + +# 3. Check vibetunnel server binary +echo "" +echo "3. VibeTunnel Server Binary" +echo "--------------------------" +SERVER_BINARY="$APP_PATH/Contents/Resources/vibetunnel" +if [ -f "$SERVER_BINARY" ]; then + check_binary "$SERVER_BINARY" + + # Check size (debug builds are often larger) + SIZE_MB=$(ls -lh "$SERVER_BINARY" | awk '{print $5}') + echo "Binary size: $SIZE_MB" + + # Get size in bytes for comparison + SIZE_BYTES=$(stat -f%z "$SERVER_BINARY" 2>/dev/null || stat -c%s "$SERVER_BINARY" 2>/dev/null) + if [ "$SIZE_BYTES" -gt 157286400 ]; then # 150 MB + echo -e "${YELLOW}⚠️ WARNING: Binary size exceeds 150MB, might be a debug build${NC}" + ((WARNINGS++)) + fi +else + echo -e "${RED}❌ ERROR: Server binary not found${NC}" + ((ERRORS++)) +fi + +# 4. Check native modules +echo "" +echo "4. Native Modules" +echo "----------------" +for module in pty.node authenticate_pam.node spawn-helper; do + MODULE_PATH="$APP_PATH/Contents/Resources/$module" + if [ -f "$MODULE_PATH" ]; then + check_binary "$MODULE_PATH" + else + echo -e "${YELLOW}⚠️ WARNING: $module not found${NC}" + ((WARNINGS++)) + fi +done + +# 5. Check build configuration (if Info.plist contains debug info) +echo "" +echo "5. Build Configuration" +echo "--------------------" +INFO_PLIST="$APP_PATH/Contents/Info.plist" +if [ -f "$INFO_PLIST" ]; then + # Check for common debug keys + if plutil -p "$INFO_PLIST" 2>/dev/null | grep -qi "debug"; then + echo -e "${YELLOW}⚠️ WARNING: Info.plist may contain debug configuration${NC}" + ((WARNINGS++)) + else + echo -e "${GREEN}✅ No obvious debug configuration in Info.plist${NC}" + fi +else + echo -e "${YELLOW}⚠️ WARNING: Info.plist not found${NC}" + ((WARNINGS++)) +fi + +# 6. Check code signature +echo "" +echo "6. Code Signature" +echo "----------------" +CODESIGN_INFO=$(codesign -dvvv "$APP_PATH" 2>&1 || true) +if echo "$CODESIGN_INFO" | grep -q "Authority="; then + echo -e "${GREEN}✅ App is signed${NC}" + # Check if it's a development certificate + if echo "$CODESIGN_INFO" | grep -q "Developer ID"; then + echo -e "${GREEN}✅ Signed with Developer ID (release)${NC}" + elif echo "$CODESIGN_INFO" | grep -q "Apple Development"; then + echo -e "${YELLOW}⚠️ WARNING: Signed with development certificate${NC}" + ((WARNINGS++)) + fi +else + echo -e "${YELLOW}⚠️ WARNING: App is not signed${NC}" + ((WARNINGS++)) +fi + +# Summary +echo "" +echo "=====================================" +echo "Verification Summary" +echo "=====================================" + +if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then + echo -e "${GREEN}✅ All checks passed! This appears to be a valid release build.${NC}" + exit 0 +elif [ $ERRORS -eq 0 ]; then + echo -e "${YELLOW}⚠️ Build has $WARNINGS warning(s) but no critical errors.${NC}" + echo "Review the warnings above to ensure they're acceptable." + exit 0 +else + echo -e "${RED}❌ Build has $ERRORS error(s) and $WARNINGS warning(s).${NC}" + echo "This build should NOT be released!" + exit 1 +fi \ No newline at end of file diff --git a/web/build-custom-node.js b/web/build-custom-node.js index db37a0e9..7af10bb5 100755 --- a/web/build-custom-node.js +++ b/web/build-custom-node.js @@ -98,8 +98,8 @@ async function buildCustomNode() { // Support CI environment variable nodeSourceVersion = process.env.NODE_VERSION; } else { - // Default to Node.js 24.2.0 (recommended version) - nodeSourceVersion = '24.2.0'; + // Default to Node.js 24.3.0 (recommended version) + nodeSourceVersion = '24.3.0'; } const platform = process.platform; @@ -177,6 +177,7 @@ async function buildCustomNode() { '--without-inspector', // Remove debugging/profiling features '--without-node-code-cache', // Disable code cache '--without-node-snapshot', // Don't create/use startup snapshot + '--shared-zlib', // Use system zlib instead of building custom ]; // Check if ninja is available @@ -188,7 +189,8 @@ async function buildCustomNode() { console.log('Ninja not found, using Make...'); } - // Enable ccache if available + + // Enable ccache if available in system paths try { execSync('which ccache', { stdio: 'ignore' }); process.env.CC = 'ccache gcc'; @@ -201,8 +203,6 @@ async function buildCustomNode() { // Use -Os optimization which is proven to be safe process.env.CFLAGS = '-Os'; process.env.CXXFLAGS = '-Os'; - // Clear LDFLAGS to avoid any issues - delete process.env.LDFLAGS; execSync(`./configure ${configureArgs.join(' ')}`, { stdio: 'inherit' }); @@ -277,6 +277,7 @@ Path: ${customNodePath} `; fs.writeFileSync(summaryPath, summary); + // Change back to original directory process.chdir(originalCwd); diff --git a/web/build-native.js b/web/build-native.js index b6e88fe7..ff7c59c6 100755 --- a/web/build-native.js +++ b/web/build-native.js @@ -321,21 +321,40 @@ async function main() { const customVersion = execSync(`"${nodeExe}" --version`, { encoding: 'utf8' }).trim(); console.log(`Custom Node.js version: ${customVersion}`); + // Save original PATH and use clean environment + const originalPath = process.env.PATH; + const cleanEnv = { + ...process.env, + // Use only system paths to avoid Homebrew contamination + PATH: '/usr/bin:/bin:/usr/sbin:/sbin', + npm_config_runtime: 'node', + npm_config_target: customVersion.substring(1), // Remove 'v' prefix + npm_config_arch: process.arch, + npm_config_target_arch: process.arch, + npm_config_disturl: 'https://nodejs.org/dist', + npm_config_build_from_source: 'true', + // Node.js 24 requires C++20 + CXXFLAGS: '-std=c++20', + npm_config_cxxflags: '-std=c++20' + }; + + // Remove any Homebrew-related environment variables + delete cleanEnv.LDFLAGS; + delete cleanEnv.LIBRARY_PATH; + delete cleanEnv.CPATH; + delete cleanEnv.C_INCLUDE_PATH; + delete cleanEnv.CPLUS_INCLUDE_PATH; + delete cleanEnv.PKG_CONFIG_PATH; + + console.log('Using clean PATH to avoid Homebrew dependencies during native module rebuild...'); + execSync(`pnpm rebuild node-pty authenticate-pam`, { stdio: 'inherit', - env: { - ...process.env, - npm_config_runtime: 'node', - npm_config_target: customVersion.substring(1), // Remove 'v' prefix - npm_config_arch: process.arch, - npm_config_target_arch: process.arch, - npm_config_disturl: 'https://nodejs.org/dist', - npm_config_build_from_source: 'true', - // Node.js 24 requires C++20 - CXXFLAGS: '-std=c++20', - npm_config_cxxflags: '-std=c++20' - } + env: cleanEnv }); + + // Restore original PATH + process.env.PATH = originalPath; } // 2. Bundle TypeScript with esbuild diff --git a/web/package.json b/web/package.json index ff66e643..ca2ab39e 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "@vibetunnel/vibetunnel-cli", - "version": "1.0.0-beta.7", + "version": "1.0.0-beta.8", "description": "Web frontend for terminal multiplexer", "main": "dist/server.js", "bin": {