Build Standalone Application #17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Standalone Application | |
| on: | |
| # Manual trigger | |
| workflow_dispatch: | |
| # Key: Give GITHUB_TOKEN write permissions (contents: write), otherwise cannot create releases | |
| permissions: | |
| contents: write | |
| jobs: | |
| build_and_release: | |
| runs-on: macos-latest | |
| steps: | |
| # 1. Check out repository code | |
| - name: Check out repository | |
| uses: actions/checkout@v2 | |
| # 2. Set up Python 3.9 | |
| - name: Set up Python | |
| uses: actions/setup-python@v2 | |
| with: | |
| python-version: '3.9' | |
| # 3. Install dependencies | |
| - name: Install dependencies | |
| run: | | |
| pip install --upgrade pip | |
| pip install -r requirements.txt | |
| pip install pyinstaller | |
| # Install Pillow for icon conversion if needed | |
| pip install Pillow | |
| # 3.5. Create app icon if not exists | |
| - name: Create app icon | |
| run: | | |
| # Create a simple icon using Python if no icon file exists | |
| if [ ! -f "icon.icns" ]; then | |
| python3 << 'EOF' | |
| import os | |
| try: | |
| from PIL import Image, ImageDraw, ImageFont | |
| # Create a 1024x1024 icon with a search magnifying glass | |
| size = 1024 | |
| img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| # Draw a modern search icon | |
| center = size // 2 | |
| circle_radius = size // 3 | |
| handle_width = size // 20 | |
| # Main circle (magnifying glass lens) | |
| circle_bbox = [ | |
| center - circle_radius, | |
| center - circle_radius - size // 10, | |
| center + circle_radius, | |
| center + circle_radius - size // 10 | |
| ] | |
| draw.ellipse(circle_bbox, outline=(70, 130, 220, 255), width=size//40) | |
| # Handle of magnifying glass | |
| handle_start_x = center + circle_radius * 0.7 | |
| handle_start_y = center + circle_radius * 0.7 - size // 10 | |
| handle_end_x = center + circle_radius * 1.3 | |
| handle_end_y = center + circle_radius * 1.3 - size // 10 | |
| draw.line([ | |
| (handle_start_x, handle_start_y), | |
| (handle_end_x, handle_end_y) | |
| ], fill=(70, 130, 220, 255), width=handle_width) | |
| # Add a subtle gradient background circle | |
| bg_circle = [50, 50, size-50, size-50] | |
| draw.ellipse(bg_circle, fill=(245, 245, 250, 100)) | |
| # Save as PNG first | |
| img.save('icon.png') | |
| print("Created icon.png") | |
| # Convert to different sizes for icns | |
| sizes = [16, 32, 64, 128, 256, 512, 1024] | |
| icon_images = [] | |
| for s in sizes: | |
| resized = img.resize((s, s), Image.Resampling.LANCZOS) | |
| icon_images.append(resized) | |
| # Save the largest as the main icon | |
| img.save('icon.icns') | |
| print("Created icon.icns") | |
| except ImportError: | |
| print("Pillow not available, will use default icon") | |
| except Exception as e: | |
| print(f"Icon creation failed: {e}, will use default icon") | |
| EOF | |
| fi | |
| # 4. Build standalone applications for both architectures | |
| - name: Build standalone application | |
| run: | | |
| # Check if icon exists and add icon parameter | |
| ICON_PARAM="" | |
| if [ -f "icon.icns" ]; then | |
| ICON_PARAM="--icon=icon.icns" | |
| echo "Using custom icon: icon.icns" | |
| else | |
| echo "No custom icon found, using default" | |
| fi | |
| # Create x86_64 version - use --onedir for faster startup | |
| pyinstaller --target-architecture x86_64 --onedir --windowed --noconsole $ICON_PARAM everything.py | |
| mkdir -p dist_x86_64 | |
| mv dist/everything dist_x86_64/ | |
| # Clean build files | |
| rm -rf build dist | |
| # Create arm64 version - use --onedir for faster startup | |
| pyinstaller --target-architecture arm64 --onedir --windowed --noconsole $ICON_PARAM everything.py | |
| mkdir -p dist_arm64 | |
| mv dist/everything dist_arm64/ | |
| # 5. Create macOS app bundles and installers | |
| - name: Create macOS app bundles and installers | |
| run: | | |
| # Create app bundle structure for x86_64 | |
| mkdir -p "Everything by mdfind x86_64.app/Contents/MacOS" | |
| mkdir -p "Everything by mdfind x86_64.app/Contents/Resources" | |
| mkdir -p "Everything by mdfind x86_64.app/Contents/Frameworks" | |
| # Copy entire application directory (onedir output includes all dependencies) | |
| cp -R dist_x86_64/everything/* "Everything by mdfind x86_64.app/Contents/MacOS/" | |
| # Copy icon to Resources if it exists | |
| if [ -f "icon.icns" ]; then | |
| cp icon.icns "Everything by mdfind x86_64.app/Contents/Resources/" | |
| fi | |
| # Create Info.plist for x86_64 | |
| cat > "Everything by mdfind x86_64.app/Contents/Info.plist" << EOF | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>CFBundleExecutable</key> | |
| <string>everything</string> | |
| <key>CFBundleIdentifier</key> | |
| <string>com.appledragon.everythingbymdfind</string> | |
| <key>CFBundleName</key> | |
| <string>Everything by mdfind</string> | |
| <key>CFBundleDisplayName</key> | |
| <string>Everything by mdfind</string> | |
| <key>CFBundleVersion</key> | |
| <string>1.3.3</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>1.3.3</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>CFBundleIconFile</key> | |
| <string>icon</string> | |
| <key>LSMinimumSystemVersion</key> | |
| <string>10.15</string> | |
| <key>NSHighResolutionCapable</key> | |
| <true/> | |
| <key>LSApplicationCategoryType</key> | |
| <string>public.app-category.utilities</string> | |
| <key>NSAppleEventsUsageDescription</key> | |
| <string>This app needs Apple Events access to interact with Spotlight for file searching.</string> | |
| <key>NSDesktopFolderUsageDescription</key> | |
| <string>This app needs access to your Desktop folder to search for files.</string> | |
| <key>NSDocumentsFolderUsageDescription</key> | |
| <string>This app needs access to your Documents folder to search for files.</string> | |
| <key>NSDownloadsFolderUsageDescription</key> | |
| <string>This app needs access to your Downloads folder to search for files.</string> | |
| </dict> | |
| </plist> | |
| EOF | |
| # Create app bundle structure for arm64 | |
| mkdir -p "Everything by mdfind arm64.app/Contents/MacOS" | |
| mkdir -p "Everything by mdfind arm64.app/Contents/Resources" | |
| mkdir -p "Everything by mdfind arm64.app/Contents/Frameworks" | |
| # Copy entire application directory (onedir output includes all dependencies) | |
| cp -R dist_arm64/everything/* "Everything by mdfind arm64.app/Contents/MacOS/" | |
| # Copy icon to Resources if it exists | |
| if [ -f "icon.icns" ]; then | |
| cp icon.icns "Everything by mdfind arm64.app/Contents/Resources/" | |
| fi | |
| # Create Info.plist for arm64 | |
| cat > "Everything by mdfind arm64.app/Contents/Info.plist" << EOF | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
| <plist version="1.0"> | |
| <dict> | |
| <key>CFBundleExecutable</key> | |
| <string>everything</string> | |
| <key>CFBundleIdentifier</key> | |
| <string>com.appledragon.everythingbymdfind</string> | |
| <key>CFBundleName</key> | |
| <string>Everything by mdfind</string> | |
| <key>CFBundleDisplayName</key> | |
| <string>Everything by mdfind</string> | |
| <key>CFBundleVersion</key> | |
| <string>1.3.3</string> | |
| <key>CFBundleShortVersionString</key> | |
| <string>1.3.3</string> | |
| <key>CFBundlePackageType</key> | |
| <string>APPL</string> | |
| <key>CFBundleIconFile</key> | |
| <string>icon</string> | |
| <key>LSMinimumSystemVersion</key> | |
| <string>10.15</string> | |
| <key>NSHighResolutionCapable</key> | |
| <true/> | |
| <key>LSApplicationCategoryType</key> | |
| <string>public.app-category.utilities</string> | |
| <key>NSAppleEventsUsageDescription</key> | |
| <string>This app needs Apple Events access to interact with Spotlight for file searching.</string> | |
| <key>NSDesktopFolderUsageDescription</key> | |
| <string>This app needs access to your Desktop folder to search for files.</string> | |
| <key>NSDocumentsFolderUsageDescription</key> | |
| <string>This app needs access to your Documents folder to search for files.</string> | |
| <key>NSDownloadsFolderUsageDescription</key> | |
| <string>This app needs access to your Downloads folder to search for files.</string> | |
| </dict> | |
| </plist> | |
| EOF | |
| # Create installer packages | |
| pkgbuild --root "Everything by mdfind x86_64.app" \ | |
| --identifier "com.appledragon.everythingbymdfind.x86_64" \ | |
| --version "1.3.3" \ | |
| --install-location "/Applications/Everything by mdfind x86_64.app" \ | |
| "everything-x86_64.pkg" | |
| pkgbuild --root "Everything by mdfind arm64.app" \ | |
| --identifier "com.appledragon.everythingbymdfind.arm64" \ | |
| --version "1.3.3" \ | |
| --install-location "/Applications/Everything by mdfind arm64.app" \ | |
| "everything-arm64.pkg" | |
| # Also create zip files for direct download | |
| zip -r "everything-x86_64-app.zip" "Everything by mdfind x86_64.app" | |
| zip -r "everything-arm64-app.zip" "Everything by mdfind arm64.app" | |
| # 6. Create GitHub Release | |
| - name: Create GitHub release | |
| id: create_release | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: 'v1.3.3' | |
| release_name: 'Everything by mdfind v1.3.3' | |
| body: | | |
| ## Everything by mdfind v1.3.3 | |
| ### New Features | |
| - Added file compression functionality with ZIP support | |
| - Enhanced dialog with "Open in Finder" option after compression | |
| - **PERFORMANCE IMPROVEMENT**: Fixed slow startup issue by using directory-based packaging instead of single-file | |
| ### Installation Options | |
| **Option 1: macOS Installer Package (.pkg)** - RECOMMENDED | |
| - Download the .pkg file for your architecture | |
| - Double-click to install like any standard Mac application | |
| - The app will be installed to /Applications folder | |
| - **Fast startup** - no more extraction delays! | |
| **Option 2: App Bundle (.zip)** | |
| - Download the .zip file for your architecture | |
| - Extract and drag to Applications folder manually | |
| - **Fast startup** - optimized for performance | |
| ### Architecture Support | |
| - **Intel Macs (x86_64)**: Download files with "x86_64" in the name | |
| - **Apple Silicon Macs (arm64)**: Download files with "arm64" in the name | |
| ### Performance Notes | |
| - This version uses directory-based packaging instead of single-file | |
| - **Startup time improved significantly** (from ~3-5 seconds to instant) | |
| - Slightly larger download size but much better user experience | |
| ### System Requirements | |
| - macOS 10.15 (Catalina) or later | |
| - Python runtime is included (no separate installation needed) | |
| draft: false | |
| prerelease: false | |
| # 7. Upload release assets | |
| - name: Upload x86_64 installer package | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| asset_path: everything-x86_64.pkg | |
| asset_name: everything-x86_64.pkg | |
| asset_content_type: application/octet-stream | |
| - name: Upload arm64 installer package | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| asset_path: everything-arm64.pkg | |
| asset_name: everything-arm64.pkg | |
| asset_content_type: application/octet-stream | |
| - name: Upload x86_64 app bundle | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| asset_path: everything-x86_64-app.zip | |
| asset_name: everything-x86_64-app.zip | |
| asset_content_type: application/zip | |
| - name: Upload arm64 app bundle | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| asset_path: everything-arm64-app.zip | |
| asset_name: everything-arm64-app.zip | |
| asset_content_type: application/zip |