chore: release 1.2.12 #17
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 Tauri (cross-platform) | |
| # 触发条件: | |
| # - 推 v*.*.*-tauri 形式的 tag(与老 Swift 版的 vX.Y.Z 区分开,不冲突) | |
| # - 手动 dispatch(用于测试构建,不发版) | |
| # | |
| # 输出: | |
| # macOS arm64 .dmg + Windows x64 .msi/.exe + Linux x64 .deb/.rpm/.AppImage,自动作为 GitHub Release 资产上传。 | |
| # | |
| # macOS 分发: | |
| # - 配好 APPLE_CERTIFICATE / APPLE_CERTIFICATE_PASSWORD / APPLE_ID / | |
| # APPLE_PASSWORD / APPLE_TEAM_ID 后,Tauri 会做 Developer ID 签名和公证。 | |
| # 用户从浏览器下载后不需要手工 xattr。 | |
| # - 未配置 Apple secrets 时自动回退 ad-hoc 签名,GitHub Actions 会打印 warning。 | |
| # - Windows 没签名(无证书),Win 11 SmartScreen 会警告 "未识别的发布者",用户点"仍要运行"。 | |
| # - 任意一个 platform 失败不影响另一个继续构建(fail-fast: false)。 | |
| on: | |
| push: | |
| tags: | |
| - 'v*-tauri' | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: macos-latest | |
| rust-target: aarch64-apple-darwin | |
| updater-target: darwin | |
| updater-arch: aarch64 | |
| - platform: windows-latest | |
| rust-target: x86_64-pc-windows-msvc | |
| updater-target: windows | |
| updater-arch: x86_64 | |
| - platform: ubuntu-22.04 | |
| rust-target: x86_64-unknown-linux-gnu | |
| updater-target: linux | |
| updater-arch: x86_64 | |
| runs-on: ${{ matrix.platform }} | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: 'openless-all/app/package-lock.json' | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.rust-target }} | |
| - name: Cache Cargo | |
| uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: 'openless-all/app/src-tauri -> target' | |
| - name: Install Linux bundle deps | |
| if: matrix.platform == 'ubuntu-22.04' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| build-essential \ | |
| curl \ | |
| file \ | |
| libasound2-dev \ | |
| libayatana-appindicator3-dev \ | |
| libfuse2 \ | |
| librsvg2-dev \ | |
| libssl-dev \ | |
| libwebkit2gtk-4.1-dev \ | |
| libxdo-dev \ | |
| patchelf \ | |
| rpm \ | |
| wget | |
| - name: Install npm deps | |
| working-directory: 'openless-all/app' | |
| run: npm ci | |
| - name: Check updater signing availability | |
| if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri') | |
| shell: bash | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| run: | | |
| if [ -z "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then | |
| echo "::error::TAURI_SIGNING_PRIVATE_KEY is required for signed auto-update artifacts." | |
| exit 1 | |
| fi | |
| - name: Check Apple signing availability | |
| if: matrix.platform == 'macos-latest' && startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri') | |
| shell: bash | |
| env: | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| run: | | |
| missing=() | |
| for name in APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID; do | |
| if [ -z "${!name:-}" ]; then | |
| missing+=("$name") | |
| fi | |
| done | |
| if [ "${#missing[@]}" -gt 0 ]; then | |
| echo "::warning::macOS release will use ad-hoc signing because Apple signing/notarization secrets are missing: ${missing[*]}" | |
| fi | |
| - name: Import Apple Developer ID certificate | |
| if: matrix.platform == 'macos-latest' | |
| shell: bash | |
| env: | |
| APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} | |
| run: | | |
| if [ -z "${APPLE_CERTIFICATE:-}" ] || [ -z "${APPLE_CERTIFICATE_PASSWORD:-}" ]; then | |
| echo "No Apple certificate secrets configured; macOS build will use ad-hoc signing." | |
| exit 0 | |
| fi | |
| KEYCHAIN_PASSWORD="${KEYCHAIN_PASSWORD:-$(openssl rand -base64 32)}" | |
| CERT_PATH="$RUNNER_TEMP/openless-certificate.p12" | |
| KEYCHAIN_PATH="$RUNNER_TEMP/openless-build.keychain-db" | |
| echo "$APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH" | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| security default-keychain -s "$KEYCHAIN_PATH" | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| security set-keychain-settings -t 3600 -u "$KEYCHAIN_PATH" | |
| security import "$CERT_PATH" -k "$KEYCHAIN_PATH" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| DEVELOPER_ID_INFO="$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep 'Developer ID Application' | head -n 1)" | |
| if [ -n "$DEVELOPER_ID_INFO" ]; then | |
| CERT_INFO="$DEVELOPER_ID_INFO" | |
| else | |
| CERT_INFO="$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep -E 'Apple Distribution|Apple Development' | head -n 1)" | |
| fi | |
| if [ -z "$CERT_INFO" ]; then | |
| echo "Apple certificate imported, but no usable code-signing identity was found." | |
| security find-identity -v -p codesigning "$KEYCHAIN_PATH" | |
| exit 1 | |
| fi | |
| CERT_ID="$(echo "$CERT_INFO" | awk -F'"' '{print $2}')" | |
| echo "APPLE_SIGNING_IDENTITY=$CERT_ID" >> "$GITHUB_ENV" | |
| echo "Imported Apple signing identity: $CERT_ID" | |
| - name: Configure Apple notarization | |
| if: matrix.platform == 'macos-latest' | |
| shell: bash | |
| env: | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| APPLE_PROVIDER_SHORT_NAME: ${{ secrets.APPLE_PROVIDER_SHORT_NAME }} | |
| run: | | |
| for name in APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID APPLE_PROVIDER_SHORT_NAME; do | |
| value="${!name:-}" | |
| if [ -n "$value" ]; then | |
| echo "$name=$value" >> "$GITHUB_ENV" | |
| fi | |
| done | |
| # ── macOS:用我们自己的 build-mac.sh,统一处理签名、公证和 artifact 清理 ── | |
| - name: Build (macOS) | |
| if: matrix.platform == 'macos-latest' | |
| working-directory: 'openless-all/app' | |
| env: | |
| INSTALL: '0' # CI 不要装到 /Applications,也不要 reset TCC | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| run: bash scripts/build-mac.sh | |
| # ── Windows:仅 Windows 跑通用 tauri build(Linux 用下方专用 step,避免重复构建)── | |
| - name: Build (Windows) | |
| if: matrix.platform == 'windows-latest' | |
| shell: bash | |
| working-directory: 'openless-all/app' | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| run: | | |
| if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then | |
| npm run tauri -- build --config '{"bundle":{"createUpdaterArtifacts":true}}' | |
| else | |
| npm run tauri build | |
| fi | |
| # ── Linux:产 deb / rpm / AppImage ── | |
| - name: Build (Linux) | |
| if: matrix.platform == 'ubuntu-22.04' | |
| shell: bash | |
| working-directory: 'openless-all/app' | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| run: | | |
| if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then | |
| npm run tauri -- build --bundles deb,rpm,appimage --config '{"bundle":{"createUpdaterArtifacts":true}}' | |
| else | |
| npm run tauri -- build --bundles deb,rpm,appimage | |
| fi | |
| - name: Write updater manifest | |
| if: env.TAURI_SIGNING_PRIVATE_KEY != '' | |
| shell: bash | |
| working-directory: 'openless-all/app' | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| OPENLESS_UPDATE_TARGET: ${{ matrix.updater-target }} | |
| OPENLESS_UPDATE_ARCH: ${{ matrix.updater-arch }} | |
| OPENLESS_UPDATE_REPO: appergb/openless | |
| OPENLESS_UPDATE_MIRROR_BASE_URL: https://fastgit.cc/https://github.com | |
| run: node scripts/write-updater-manifest.mjs | |
| # ── 收集产物 ── | |
| - name: List artifacts (debug) | |
| shell: bash | |
| working-directory: 'openless-all/app/src-tauri/target/release/bundle' | |
| run: ls -la macos/ dmg/ nsis/ msi/ deb/ rpm/ appimage/ 2>/dev/null || true | |
| # 防御性步骤:剥掉 macOS 产物上任何残留扩展属性 / quarantine。 | |
| # 理论上 GitHub Actions 输出的 .app/.dmg 不会带 com.apple.quarantine | |
| # (xattr 也不会通过 actions/upload-artifact 跨机器持久化),但保留这一步 | |
| # 让"云端 artifact 一定干净"成为可验证的承诺。用户下载后再被本地浏览器 | |
| # 加 quarantine 时,按 release notes 的 `xattr -cr` 一行即可消除。 | |
| - name: Strip xattr / quarantine on macOS bundles | |
| if: matrix.platform == 'macos-latest' | |
| shell: bash | |
| working-directory: 'openless-all/app/src-tauri/target/release/bundle' | |
| run: | | |
| for path in macos/*.app dmg/*.dmg; do | |
| if [ -e "$path" ]; then | |
| echo "▶ stripping xattr: $path" | |
| xattr -cr "$path" || true | |
| xattr -lr "$path" || true | |
| fi | |
| done | |
| - name: Upload macOS artifacts | |
| if: matrix.platform == 'macos-latest' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-macos-arm64 | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/dmg/*.dmg | |
| if-no-files-found: error | |
| - name: Upload macOS updater artifacts | |
| if: matrix.platform == 'macos-latest' && env.TAURI_SIGNING_PRIVATE_KEY != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-macos-arm64-updater | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz | |
| openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz.sig | |
| openless-all/app/src-tauri/target/release/bundle/latest-darwin-aarch64.json | |
| openless-all/app/src-tauri/target/release/bundle/latest-darwin-aarch64-mirror.json | |
| if-no-files-found: error | |
| - name: Upload Windows artifacts | |
| if: matrix.platform == 'windows-latest' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-windows-x64 | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/nsis/*.exe | |
| openless-all/app/src-tauri/target/release/bundle/msi/*.msi | |
| if-no-files-found: error | |
| - name: Upload Windows updater artifacts | |
| if: matrix.platform == 'windows-latest' && env.TAURI_SIGNING_PRIVATE_KEY != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-windows-x64-updater | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig | |
| openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig | |
| openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64.json | |
| openless-all/app/src-tauri/target/release/bundle/latest-windows-x86_64-mirror.json | |
| if-no-files-found: error | |
| - name: Upload Linux artifacts | |
| if: matrix.platform == 'ubuntu-22.04' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-linux-x64 | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/deb/*.deb | |
| openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm | |
| openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage | |
| if-no-files-found: error | |
| - name: Upload Linux updater artifacts | |
| if: matrix.platform == 'ubuntu-22.04' && env.TAURI_SIGNING_PRIVATE_KEY != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: openless-linux-x64-updater | |
| path: | | |
| openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig | |
| openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64.json | |
| openless-all/app/src-tauri/target/release/bundle/latest-linux-x86_64-mirror.json | |
| if-no-files-found: error | |
| # ── tag 推送时,同步上传到 GitHub Release ── | |
| - name: Create / update release | |
| if: startsWith(github.ref, 'refs/tags/v') && endsWith(github.ref, '-tauri') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: 'OpenLess ${{ github.ref_name }}' | |
| draft: false | |
| prerelease: false | |
| # Matrix jobs all upload assets to the same release. Generate notes once | |
| # so macOS, Windows, and Linux jobs do not duplicate the release body. | |
| generate_release_notes: ${{ matrix.platform == 'macos-latest' }} | |
| files: | | |
| openless-all/app/src-tauri/target/release/bundle/dmg/*.dmg | |
| openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz | |
| openless-all/app/src-tauri/target/release/bundle/macos/*.app.tar.gz.sig | |
| openless-all/app/src-tauri/target/release/bundle/nsis/*.exe | |
| openless-all/app/src-tauri/target/release/bundle/nsis/*.exe.sig | |
| openless-all/app/src-tauri/target/release/bundle/msi/*.msi | |
| openless-all/app/src-tauri/target/release/bundle/msi/*.msi.sig | |
| openless-all/app/src-tauri/target/release/bundle/deb/*.deb | |
| openless-all/app/src-tauri/target/release/bundle/rpm/*.rpm | |
| openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage | |
| openless-all/app/src-tauri/target/release/bundle/appimage/*.AppImage.sig | |
| openless-all/app/src-tauri/target/release/bundle/latest-*.json |