Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/build-mac.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Build macOS App

on:
release:
types: [created]
workflow_dispatch:

jobs:
build-macos:
runs-on: macos-latest
strategy:
matrix:
arch: [x86_64, arm64]
include:
- arch: x86_64
name: Intel
- arch: arm64
name: Apple Silicon

steps:
- uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller

- name: Build App (${{ matrix.name }})
run: |
ICON_PARAM=""
if [ -f "static/images/icon.icns" ]; then
ICON_PARAM="--icon static/images/icon.icns"
fi

pyinstaller \
--name "Infinite Canvas" \
--windowed \
--onedir \
$ICON_PARAM \
--add-data "static:static" \
--add-data "workflows:workflows" \
--add-data "tools:tools" \
--add-data "VERSION:." \
--add-data "requirements.txt:." \
--hidden-import uvicorn.logging \
--hidden-import uvicorn.loops \
--hidden-import uvicorn.loops.auto \
--hidden-import uvicorn.protocols \
--hidden-import uvicorn.protocols.http \
--hidden-import uvicorn.protocols.http.auto \
--hidden-import uvicorn.protocols.websockets \
--hidden-import uvicorn.protocols.websockets.auto \
--hidden-import uvicorn.lifespan \
--hidden-import uvicorn.lifespan.on \
--noconfirm \
--clean \
main.py

- name: Create DMG
run: |
hdiutil create \
-volname "Infinite Canvas" \
-srcfolder "dist/Infinite Canvas" \
-ov \
-format UDZO \
"dist/Infinite Canvas-${{ matrix.arch }}.dmg"

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: Infinite-Canvas-macOS-${{ matrix.arch }}
path: dist/Infinite Canvas-${{ matrix.arch }}.dmg
retention-days: 30

- name: Upload to Release
if: github.event_name == 'release'
uses: softprops/action-gh-release@v1
with:
files: dist/Infinite Canvas-${{ matrix.arch }}.dmg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47 changes: 47 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
venv/
ENV/
env/
*.egg-info/
dist/
build/

# Environment variables
.env
.env.local
.env.*.local
API/.env

# Data files (user data)
data/
*.db
*.sqlite3

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Temporary files
*.tmp
*.temp

# PyInstaller
*.spec
*.app
*.dmg
78 changes: 78 additions & 0 deletions build_mac.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
#
# Infinite Canvas - macOS 打包脚本
# 使用 PyInstaller 将项目打包为独立 .app 应用
#

set -e

echo "============================================"
echo " Infinite Canvas - macOS 打包工具"
echo "============================================"
echo ""

# 检查 Python 版本
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
echo "Python 版本: $PYTHON_VERSION"

# 检查并安装依赖
echo ""
echo "[1/4] 安装项目依赖..."
pip3 install -r requirements.txt

echo ""
echo "[2/4] 安装 PyInstaller..."
pip3 install pyinstaller

echo ""
echo "[3/4] 开始打包..."
echo ""

# 检查图标文件
ICON_PARAM=""
if [ -f "static/images/icon.icns" ]; then
ICON_PARAM="--icon static/images/icon.icns"
echo "使用自定义图标: static/images/icon.icns"
else
echo "提示: 未找到 icon.icns,将使用默认图标"
echo "如需自定义图标,请将 .icns 文件放置在 static/images/icon.icns"
fi

# 使用 PyInstaller 打包
pyinstaller \
--name "Infinite Canvas" \
--windowed \
--onedir \
$ICON_PARAM \
--add-data "static:static" \
--add-data "workflows:workflows" \
--add-data "tools:tools" \
--add-data "VERSION:." \
--add-data "requirements.txt:." \
--hidden-import uvicorn.logging \
--hidden-import uvicorn.loops \
--hidden-import uvicorn.loops.auto \
--hidden-import uvicorn.protocols \
--hidden-import uvicorn.protocols.http \
--hidden-import uvicorn.protocols.http.auto \
--hidden-import uvicorn.protocols.websockets \
--hidden-import uvicorn.protocols.websockets.auto \
--hidden-import uvicorn.lifespan \
--hidden-import uvicorn.lifespan.on \
--noconfirm \
--clean \
main.py

echo ""
echo "[4/4] 打包完成!"
echo ""
echo "输出目录: dist/Infinite Canvas/"
echo "应用位置: dist/Infinite Canvas/Infinite Canvas.app"
echo ""
echo "运行方式:"
echo " 1. 双击 dist/Infinite Canvas/Infinite Canvas.app"
echo " 2. 或终端运行: open 'dist/Infinite Canvas/Infinite Canvas.app'"
echo ""
echo "创建 DMG 安装包:"
echo " hdiutil create -volname 'Infinite Canvas' -srcfolder 'dist/Infinite Canvas' -ov -format UDZO 'dist/Infinite Canvas.dmg'"
echo ""