Skip to content

Build Standalone Application #36

Build Standalone Application

Build Standalone Application #36

Workflow file for this run

name: Build Standalone Application
on:
# Manual trigger
workflow_dispatch:
# Key: Give GITHUB_TOKEN write permissions (contents: write), otherwise unable to 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.11
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
# 3. Verify Python framework installation
- name: Verify Python framework
run: |
echo "Python version:"
python --version
echo "Python executable path:"
which python
echo "Python framework location:"
python -c "import sys; print(sys.prefix)"
echo "Available Python frameworks:"
ls -la /Library/Frameworks/Python.framework/Versions/ || echo "No Python frameworks found in /Library/Frameworks"
# 4. Install dependencies
- name: Install dependencies
run: |
# Clear pip cache to avoid Python version conflicts
pip cache purge || true
# Upgrade pip
pip install --upgrade pip
# Install dependencies with no cache to ensure fresh build against Python 3.11
pip install --no-cache-dir -r requirements.txt
pip install --no-cache-dir py2app
# Install librsvg for SVG conversion
brew install librsvg
# 5. Create app icon from SVG
- name: Create app icon from SVG
run: |
# Create different sizes of PNG
rsvg-convert -w 16 -h 16 icon.svg -o icon_16x16.png
rsvg-convert -w 32 -h 32 icon.svg -o icon_32x32.png
rsvg-convert -w 64 -h 64 icon.svg -o icon_64x64.png
rsvg-convert -w 128 -h 128 icon.svg -o icon_128x128.png
rsvg-convert -w 256 -h 256 icon.svg -o icon_256x256.png
rsvg-convert -w 512 -h 512 icon.svg -o icon_512x512.png
rsvg-convert -w 1024 -h 1024 icon.svg -o icon_1024x1024.png
# Create iconset directory structure
mkdir icon.iconset
cp icon_16x16.png icon.iconset/icon_16x16.png
cp icon_32x32.png icon.iconset/icon_16x16@2x.png
cp icon_32x32.png icon.iconset/icon_32x32.png
cp icon_64x64.png icon.iconset/icon_32x32@2x.png
cp icon_128x128.png icon.iconset/icon_128x128.png
cp icon_256x256.png icon.iconset/icon_128x128@2x.png
cp icon_256x256.png icon.iconset/icon_256x256.png
cp icon_512x512.png icon.iconset/icon_256x256@2x.png
cp icon_512x512.png icon.iconset/icon_512x512.png
cp icon_1024x1024.png icon.iconset/icon_512x512@2x.png
# Use iconutil to create .icns file
iconutil -c icns icon.iconset
# Verify icon file creation success
ls -la icon.icns
# 6. Create setup.py configuration file
- name: Create setup.py for py2app
run: |
cat > setup.py << 'EOF'
from setuptools import setup
import sys
APP = ['everything.py']
DATA_FILES = [
('', ['LICENSE.md', 'README.md']),
]
OPTIONS = {
'argv_emulation': False,
'packages': ['PyQt6'],
'excludes': [],
'iconfile': 'icon.icns',
'plist': {
'CFBundleName': 'Everything',
'CFBundleDisplayName': 'Everything',
'CFBundleVersion': '1.4.2',
'CFBundleShortVersionString': '1.4.2',
'CFBundleIdentifier': 'com.appledragon.everythingbymdfind',
'LSMinimumSystemVersion': '10.14',
'NSHighResolutionCapable': True,
},
# Use alias mode to avoid copying Python framework
'alias': False,
# This ensures we use the installed Python and don't try to bundle multiple versions
'strip': True,
'optimize': 2,
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
EOF
# 7. Build universal application
- name: Build universal application
env:
ARCHFLAGS: "-arch x86_64 -arch arm64"
run: |
# Clean previous builds
rm -rf build dist
# Debug: Show Python and PyQt6 information
echo "=== Python Information ==="
python --version
python -c "import sys; print('Python prefix:', sys.prefix)"
python -c "import sys; print('Python executable:', sys.executable)"
echo "=== PyQt6 Information ==="
python -c "import PyQt6; print('PyQt6 location:', PyQt6.__file__)"
python -c "import PyQt6.QtCore; print('Qt version:', PyQt6.QtCore.qVersion())"
# Build universal version (supports both x86_64 and arm64)
# Using --no-strip to preserve debugging symbols and see what's included
python setup.py py2app --arch universal2 2>&1 | tee build.log || {
echo "=== Build failed, showing last 100 lines of output ==="
tail -100 build.log
exit 1
}
# Create archive
cd dist
zip -r ../everything.zip "Everything.app"
cd ..
# 8. 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.4.1'
release_name: 'v1.4.1'
draft: false
prerelease: false
# 9. Upload release asset
- name: Upload release asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: everything.zip
asset_name: everything.zip
asset_content_type: application/zip