Files
clide/clide.spec
T
Jeroen SchweitzerandClaude Opus 4.5 aff03a2e9b feat: add multi-platform packaging and auto-update infrastructure
- Add PyInstaller configuration (clide.spec) for cross-platform builds
- Add build scripts for macOS (DMG), Linux (AppImage), and Windows (Inno Setup)
- Add Gitea Actions CI/CD workflow for automated releases
- Add auto-update service with Gitea API integration
- Add 'clide update' CLI command for checking and installing updates

Packaging outputs:
- macOS: Signed/notarized .app bundle in DMG
- Linux: Portable AppImage (glibc 2.17+)
- Windows: Inno Setup installer

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 22:51:36 +01:00

150 lines
3.4 KiB
RPMSpec

# -*- mode: python ; coding: utf-8 -*-
"""PyInstaller spec file for Clide.
Cross-platform configuration that produces:
- macOS: .app bundle (universal2 for Intel + Apple Silicon)
- Linux: Single executable (for AppImage packaging)
- Windows: Single executable (for Inno Setup packaging)
"""
import sys
block_cipher = None
# Collect data files
datas = [
('clide/templates', 'clide/templates'), # Skill templates (SKILL.md files)
]
# Hidden imports for dynamic modules
hiddenimports = [
# Textual internals
'textual._context',
'textual.css',
# Tree-sitter grammars
'tree_sitter_python',
'tree_sitter_javascript',
'tree_sitter_typescript',
'tree_sitter_html',
'tree_sitter_css',
'tree_sitter_json',
'tree_sitter_yaml',
'tree_sitter_toml',
'tree_sitter_markdown',
'tree_sitter_rust',
'tree_sitter_go',
'tree_sitter_java',
'tree_sitter_bash',
# Watchdog backends
'watchdog.observers.fsevents', # macOS
'watchdog.observers.inotify', # Linux
'watchdog.observers.read_directory_changes', # Windows
# Pydantic
'pydantic',
'pydantic_settings',
# Vendored pyte
'clide.vendor.pyte',
]
# Exclude dev/test dependencies
excludes = [
'pytest',
'mypy',
'ruff',
'pre_commit',
'pytest_asyncio',
'pytest_textual_snapshot',
'pytest_cov',
]
a = Analysis(
['clide/__main__.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=excludes,
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure, cipher=block_cipher)
# Platform-specific executable settings
if sys.platform == 'darwin':
# macOS: Create .app bundle
# Use CLIDE_UNIVERSAL=1 env var for universal binary (requires fat Python)
import os
target_arch = 'universal2' if os.environ.get('CLIDE_UNIVERSAL') else None
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='clide',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False, # UPX breaks macOS code signing
console=True,
target_arch=target_arch,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=False,
name='Clide',
)
app = BUNDLE(
coll,
name='Clide.app',
icon=None, # TODO: Add icon.icns
bundle_identifier='net.schweitz.clide',
info_plist={
'CFBundleShortVersionString': '1.0.0',
'CFBundleName': 'Clide',
'CFBundleDisplayName': 'Clide',
'NSHighResolutionCapable': True,
'LSEnvironment': {
'TERM': 'xterm-256color',
},
},
)
elif sys.platform == 'win32':
# Windows: Single executable
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='clide',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
icon=None, # TODO: Add icon.ico
)
else:
# Linux: Single executable (for AppImage packaging)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='clide',
debug=False,
bootloader_ignore_signals=False,
strip=True,
upx=True,
console=True,
)