@@ -49,89 +49,90 @@ jobs:
4949 pip install markdown==3.4.3
5050 pip install pyyaml==6.0
5151
52- - name : Create PyInstaller spec
52+ - name : Build macOS executable
5353 run : |
54- cat > Huntarr-macos-intel.spec << 'EOF'
55- # -*- mode: python ; coding: utf-8 -*-
56- from PyInstaller.building.api import PYZ, EXE, COLLECT, BUNDLE
57- from PyInstaller.building.build_main import Analysis
58- import os
59-
60- block_cipher = None
61-
62- # Data files to include
63- datas = [
64- ('frontend', 'frontend'),
65- ('version.txt', '.'),
66- ('README.md', '.'),
67- ('LICENSE', '.'),
68- ('src', 'src'),
69- ]
70-
71- # Add apprise data files
72- try:
73- import apprise
74- apprise_path = os.path.dirname(apprise.__file__)
75- apprise_attachment_path = os.path.join(apprise_path, 'attachment')
76- apprise_plugins_path = os.path.join(apprise_path, 'plugins')
77- apprise_config_path = os.path.join(apprise_path, 'config')
78-
79- if os.path.exists(apprise_attachment_path):
80- datas.append((apprise_attachment_path, 'apprise/attachment'))
81- if os.path.exists(apprise_plugins_path):
82- datas.append((apprise_plugins_path, 'apprise/plugins'))
83- if os.path.exists(apprise_config_path):
84- datas.append((apprise_config_path, 'apprise/config'))
85- except ImportError:
86- print("Warning: apprise not found, skipping apprise data files")
87-
88- a = Analysis(
89- ['main.py'],
90- pathex=['.'],
91- binaries=[],
92- datas=datas,
93- hiddenimports=[
94- 'flask', 'flask.json', 'requests', 'waitress', 'bcrypt', 'qrcode', 'PIL',
95- 'pyotp', 'qrcode.image.pil', 'routes', 'main', 'apprise', 'apprise.common',
96- 'apprise.conversion', 'apprise.decorators', 'apprise.locale', 'apprise.logger',
97- 'apprise.manager', 'apprise.utils', 'apprise.URLBase', 'apprise.AppriseAsset',
98- 'apprise.AppriseAttachment', 'apprise.AppriseConfig', 'apprise.cli',
99- 'apprise.config', 'apprise.attachment', 'apprise.plugins', 'markdown', 'yaml', 'cryptography',
100- ],
101- hookspath=[],
102- hooksconfig={},
103- runtime_hooks=[],
104- excludes=[],
105- cipher=block_cipher,
106- noarchive=False,
107- )
108-
109- pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
110-
111- exe = EXE(
112- pyz, a.scripts, [], exclude_binaries=True, name='Huntarr',
113- debug=False, bootloader_ignore_signals=False, strip=False, upx=True,
114- console=False, disable_windowed_traceback=False, argv_emulation=True,
115- target_arch='x86_64', codesign_identity=None, entitlements_file=None,
116- )
117-
118- coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='Huntarr')
119-
120- app = BUNDLE(
121- coll, name='Huntarr.app', bundle_identifier='io.huntarr.app',
122- info_plist={
123- 'CFBundleShortVersionString': '${{ steps.meta.outputs.VERSION }}',
124- 'CFBundleVersion': '${{ steps.meta.outputs.VERSION }}',
125- 'NSHighResolutionCapable': True,
126- 'NSRequiresAquaSystemAppearance': False,
127- 'LSUIElement': False,
128- 'CFBundleDocumentTypes': [],
129- 'NSPrincipalClass': 'NSApplication',
130- 'CFBundleExecutable': 'Huntarr',
131- 'CFBundleIconFile': 'icon.icns',
132- },
133- )
134- EOF
54+ # Use PyInstaller directly without spec file to avoid import issues
55+ python -m PyInstaller \
56+ --name="Huntarr" \
57+ --onedir \
58+ --windowed \
59+ --target-arch=x86_64 \
60+ --add-data="frontend:frontend" \
61+ --add-data="version.txt:." \
62+ --add-data="README.md:." \
63+ --add-data="LICENSE:." \
64+ --add-data="src:src" \
65+ --hidden-import="flask" \
66+ --hidden-import="flask.json" \
67+ --hidden-import="requests" \
68+ --hidden-import="waitress" \
69+ --hidden-import="bcrypt" \
70+ --hidden-import="qrcode" \
71+ --hidden-import="PIL" \
72+ --hidden-import="pyotp" \
73+ --hidden-import="qrcode.image.pil" \
74+ --hidden-import="routes" \
75+ --hidden-import="main" \
76+ --hidden-import="apprise" \
77+ --hidden-import="apprise.common" \
78+ --hidden-import="apprise.conversion" \
79+ --hidden-import="apprise.decorators" \
80+ --hidden-import="apprise.locale" \
81+ --hidden-import="apprise.logger" \
82+ --hidden-import="apprise.manager" \
83+ --hidden-import="apprise.utils" \
84+ --hidden-import="apprise.URLBase" \
85+ --hidden-import="apprise.AppriseAsset" \
86+ --hidden-import="apprise.AppriseAttachment" \
87+ --hidden-import="apprise.AppriseConfig" \
88+ --hidden-import="apprise.cli" \
89+ --hidden-import="apprise.config" \
90+ --hidden-import="apprise.attachment" \
91+ --hidden-import="apprise.plugins" \
92+ --hidden-import="markdown" \
93+ --hidden-import="yaml" \
94+ --hidden-import="cryptography" \
95+ --clean \
96+ --noconfirm \
97+ main.py
98+
99+ # Create a simple app bundle structure manually
100+ echo "Creating app bundle structure..."
101+ mkdir -p "dist/Huntarr.app/Contents/MacOS"
102+ mkdir -p "dist/Huntarr.app/Contents/Resources"
103+
104+ # Copy the executable
105+ cp -r "dist/Huntarr/"* "dist/Huntarr.app/Contents/MacOS/"
106+
107+ # Create Info.plist
108+ cat > "dist/Huntarr.app/Contents/Info.plist" << 'PLIST_EOF'
109+ <?xml version="1.0" encoding="UTF-8"?>
110+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
111+ <plist version="1.0">
112+ <dict>
113+ <key>CFBundleExecutable</key>
114+ <string>Huntarr</string>
115+ <key>CFBundleIdentifier</key>
116+ <string>io.huntarr.app</string>
117+ <key>CFBundleName</key>
118+ <string>Huntarr</string>
119+ <key>CFBundleVersion</key>
120+ <string>${{ steps.meta.outputs.VERSION }}</string>
121+ <key>CFBundleShortVersionString</key>
122+ <string>${{ steps.meta.outputs.VERSION }}</string>
123+ <key>CFBundleInfoDictionaryVersion</key>
124+ <string>6.0</string>
125+ <key>CFBundlePackageType</key>
126+ <string>APPL</string>
127+ <key>NSHighResolutionCapable</key>
128+ <true/>
129+ <key>NSRequiresAquaSystemAppearance</key>
130+ <false/>
131+ <key>LSUIElement</key>
132+ <false/>
133+ </dict>
134+ </plist>
135+ PLIST_EOF
135136
136137 - name : Create app icon
137138 run : |
@@ -186,19 +187,20 @@ jobs:
186187 cp /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericApplicationIcon.icns icon.icns 2>/dev/null || touch icon.icns
187188 fi
188189
189- - name : Build macOS app
190+ - name : Finalize app bundle
190191 run : |
191- # Build the app
192- python -m PyInstaller Huntarr-macos-intel.spec --clean --noconfirm
193-
194192 # Copy icon into the app bundle
195193 if [ -f "icon.icns" ]; then
196194 cp icon.icns dist/Huntarr.app/Contents/Resources/icon.icns || true
197195 fi
198196
197+ # Make sure the main executable is executable
198+ chmod +x dist/Huntarr.app/Contents/MacOS/Huntarr
199+
199200 # Verify the build
200201 echo "Checking built app:"
201202 ls -la dist/
203+ ls -la dist/Huntarr.app/Contents/MacOS/
202204 file dist/Huntarr.app/Contents/MacOS/Huntarr
203205
204206 # Test that the app can at least start (basic smoke test)
0 commit comments