Fix DMG background: use setup-python for reliable Pillow install #20
Workflow file for this run
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: Release Build | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| # ============================================================ | |
| # macOS: .app bundle + .dmg (arm64 + x64) | |
| # ============================================================ | |
| build-macos: | |
| name: macOS ${{ matrix.arch }} | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: arm64 | |
| runner: macos-14 | |
| rid: osx-arm64 | |
| - arch: x64 | |
| runner: macos-15 | |
| rid: osx-x64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Get version | |
| shell: bash | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| [[ "$VERSION" == refs/* ]] && VERSION=0.0.0-dev | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| - name: Publish (self-contained) | |
| run: dotnet publish src/Taskly/Taskly.csproj -c Release -r ${{ matrix.rid }} --self-contained true -p:PublishSingleFile=true -p:Version=${{ env.VERSION }} -o publish | |
| - name: Assemble .app bundle | |
| shell: bash | |
| run: | | |
| mkdir -p "Taskly.app/Contents/MacOS" | |
| mkdir -p "Taskly.app/Contents/Resources" | |
| cp -R publish/* "Taskly.app/Contents/MacOS/" | |
| # 写 Info.plist(用实际版本号替换占位) | |
| sed 's/0\.3\.0/${{ env.VERSION }}/' packaging/macos/Info.plist > "Taskly.app/Contents/Info.plist" | |
| chmod +x "Taskly.app/Contents/MacOS/Taskly" | |
| # appdmg writes the .DS_Store binary directly (no Finder/AppleScript), | |
| # producing a decorated DMG (background + /Applications link) in headless CI. | |
| - name: Setup Node for appdmg | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Setup Python for background generation | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install appdmg | |
| run: npm install -g appdmg | |
| - name: Generate DMG background | |
| run: | | |
| python3 -m pip install pillow | |
| python3 packaging/macos/dmg/make_background.py packaging/macos/dmg | |
| - name: Create .dmg (decorated, with retry) | |
| shell: bash | |
| run: | | |
| chmod +x packaging/macos/create-dmg.sh | |
| packaging/macos/create-dmg.sh \ | |
| "packaging/macos/dmg/spec.json" \ | |
| "taskly-${{ env.VERSION }}-macos-${{ matrix.arch }}.dmg" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: taskly-macos-${{ matrix.arch }} | |
| path: '*.dmg' | |
| # ============================================================ | |
| # Windows: Setup.exe (Velopack) | |
| # ============================================================ | |
| build-windows: | |
| name: Windows x64 | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Get version | |
| shell: bash | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| [[ "$VERSION" == refs/* ]] && VERSION=0.0.0-dev | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| - name: Publish (self-contained) | |
| run: dotnet publish src/Taskly/Taskly.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:Version=${{ env.VERSION }} -o publish | |
| - name: Install Velopack | |
| run: dotnet tool install -g vpk | |
| - name: Create Setup.exe | |
| shell: pwsh | |
| run: | | |
| $env:PATH = "$env:USERPROFILE\.dotnet\tools;$env:PATH" | |
| # 诊断:确认 publish 目录内容 | |
| Write-Host "=== publish 目录 ===" | |
| Get-ChildItem publish/*.exe | Format-Table Name, Length | |
| # 运行 vpk(出错了能看到完整输出) | |
| vpk pack -u Taskly -v ${{ env.VERSION }} -p publish -e Taskly.exe -o build --verbose | |
| Write-Host "=== build 产物 ===" | |
| Get-ChildItem build/*.exe | Format-Table Name, Length | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: taskly-windows-x64 | |
| path: 'build/*.exe' | |
| # ============================================================ | |
| # Linux: .AppImage + .deb | |
| # ============================================================ | |
| build-linux: | |
| name: Linux x64 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Get version | |
| shell: bash | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| [[ "$VERSION" == refs/* ]] && VERSION=0.0.0-dev | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| - name: Publish (self-contained) | |
| run: dotnet publish src/Taskly/Taskly.csproj -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -p:Version=${{ env.VERSION }} -o publish | |
| # --- AppImage --- | |
| - name: Install FUSE for AppImage | |
| run: sudo apt-get update && sudo apt-get install -y libfuse2 | |
| - name: Build AppImage | |
| shell: bash | |
| run: | | |
| # 组装 AppDir(appimagetool 要求 .desktop 在根目录) | |
| mkdir -p AppDir/usr/bin | |
| cp -R publish/* AppDir/usr/bin/ | |
| chmod +x AppDir/usr/bin/Taskly | |
| # .desktop 必须在 AppDir 根目录 | |
| cp packaging/linux/taskly.desktop AppDir/taskly.desktop | |
| # 图标(appimagetool 要求 Icon=taskly 对应 taskly.png 存在) | |
| cp packaging/linux/taskly.png AppDir/taskly.png | |
| cp packaging/linux/AppRun AppDir/AppRun | |
| chmod +x AppDir/AppRun | |
| # 下载 appimagetool | |
| wget -q "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O appimagetool | |
| chmod +x appimagetool | |
| # 生成 AppImage(CI 环境用 APPIMAGE_EXTRACT_AND_RUN 绕过 FUSE) | |
| ARCH=x86_64 APPIMAGE_EXTRACT_AND_RUN=1 ./appimagetool AppDir "taskly-${{ env.VERSION }}-linux-x64.AppImage" | |
| ls -la *.AppImage | |
| # --- .deb --- | |
| - name: Build .deb | |
| shell: bash | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| STAGING="deb-staging" | |
| mkdir -p "$STAGING/usr/bin" | |
| mkdir -p "$STAGING/usr/lib/taskly" | |
| mkdir -p "$STAGING/usr/share/applications" | |
| mkdir -p "$STAGING/DEBIAN" | |
| # 可执行文件 + 运行时(self-contained) | |
| cp -R publish/* "$STAGING/usr/lib/taskly/" | |
| chmod +x "$STAGING/usr/lib/taskly/Taskly" | |
| # 启动脚本(转发到 self-contained 可执行文件) | |
| cat > "$STAGING/usr/bin/taskly" << 'EOF' | |
| #!/bin/sh | |
| exec /usr/lib/taskly/Taskly "$@" | |
| EOF | |
| chmod +x "$STAGING/usr/bin/taskly" | |
| # .desktop 文件(Exec 指向启动脚本) | |
| sed 's|Exec=Taskly|Exec=/usr/bin/taskly|' packaging/linux/taskly.desktop > "$STAGING/usr/share/applications/taskly.desktop" | |
| # control 文件(用实际版本号) | |
| sed "s/Version: 0.3.0/Version: $VERSION/" packaging/linux/control > "$STAGING/DEBIAN/control" | |
| # 构建 .deb | |
| dpkg-deb --root-owner-group --build "$STAGING" "taskly-${{ env.VERSION }}-linux-x64.deb" | |
| ls -la *.deb | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: taskly-linux-x64 | |
| path: | | |
| *.AppImage | |
| *.deb | |
| # ============================================================ | |
| # Release: 收集所有产物,创建 GitHub Release | |
| # ============================================================ | |
| release: | |
| name: Create Release | |
| needs: [build-macos, build-windows, build-linux] | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/tags/') | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Get version | |
| shell: bash | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: List artifacts | |
| shell: bash | |
| run: find artifacts -type f | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| artifacts/*.dmg | |
| artifacts/*.exe | |
| artifacts/*.AppImage | |
| artifacts/*.deb | |
| name: Release v${{ env.VERSION }} | |
| body: | | |
| ## Downloads | |
| ### macOS | |
| - `taskly-${{ env.VERSION }}-macos-arm64.dmg` (Apple Silicon) | |
| - `taskly-${{ env.VERSION }}-macos-x64.dmg` (Intel) | |
| ### Windows | |
| - `taskly-${{ env.VERSION }}-windows-x64.exe` (Setup installer) | |
| ### Linux | |
| - `taskly-${{ env.VERSION }}-linux-x64.AppImage` (zero-install) | |
| - `taskly-${{ env.VERSION }}-linux-x64.deb` (Debian/Ubuntu) | |
| --- | |
| *Release notes are automatically generated.* | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |