v0.7.0: Reminders-style theme redesign (replace Anthropic warm palette) #42
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" | |
| # Ad-hoc 签名(无 Apple Developer 账号):让 macOS Gatekeeper 显示 | |
| # "无法验证开发者"而非误导性的"已损坏"。用户右键打开即可运行。 | |
| - name: Ad-hoc code sign | |
| shell: bash | |
| run: | | |
| # 签名所有 Mach-O 二进制(self-contained 发布包含 .NET 运行时) | |
| find "Taskly.app/Contents/MacOS" -type f -exec sh -c ' | |
| file "$1" | grep -q "Mach-O" && codesign --force --sign - "$1" 2>/dev/null || true | |
| ' _ {} \; | |
| # 整体签名 .app bundle | |
| codesign --force --deep --sign - "Taskly.app" | |
| # 验证 | |
| codesign --verify --verbose=2 "Taskly.app" 2>&1 || true | |
| # 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 app icon | |
| run: | | |
| python3 -m pip install pillow | |
| python3 packaging/macos/make_icon.py /tmp/taskly-icon-build | |
| cp /tmp/taskly-icon-build/icon.icns "Taskly.app/Contents/Resources/icon.icns" | |
| - 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(--icon 让 Setup.exe 和安装后的快捷方式显示 Taskly 图标) | |
| vpk pack -u Taskly -v ${{ env.VERSION }} -p publish -e Taskly.exe -o build --icon src/Taskly/taskly.ico --verbose | |
| - name: Rename to match platform naming convention | |
| shell: pwsh | |
| run: | | |
| # Velopack 输出 Taskly-{version}-win-x64-Setup.exe 或类似名称, | |
| # 统一改为 taskly-{version}-windows-x64.exe 与其他平台一致。 | |
| $src = Get-ChildItem build/*-Setup.exe | Select-Object -First 1 | |
| if (-not $src) { $src = Get-ChildItem build/*.exe | Select-Object -First 1 } | |
| if ($src) { | |
| $dst = "taskly-${{ env.VERSION }}-windows-x64.exe" | |
| Copy-Item $src.FullName $dst | |
| Write-Host "Renamed: $($src.Name) -> $dst" | |
| } | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: taskly-windows-x64 | |
| path: 'taskly-*-windows-x64.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@/$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) | |
| > **首次打开提示**:Taskly 尚未经过 Apple 公证。安装后若提示"无法打开"或"已损坏", | |
| > 请在终端执行:`xattr -cr /Applications/Taskly.app` | |
| > 然后即可正常打开。 | |
| > | |
| > **First launch**: Taskly is not yet notarized by Apple. If macOS says the app | |
| > is "damaged" or "can't be opened", run this in Terminal: | |
| > `xattr -cr /Applications/Taskly.app` | |
| ### 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 }} |