Skip to content

chore(release): v0.14.0 #56

chore(release): v0.14.0

chore(release): v0.14.0 #56

Workflow file for this run

name: "Release"
on:
push:
tags:
- "v*"
jobs:
release:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
args: "--target aarch64-apple-darwin"
rust-targets: aarch64-apple-darwin
bun-target: bun-darwin-arm64
sidecar-name: stockai-backend-aarch64-apple-darwin
- platform: ubuntu-24.04
args: "--bundles deb,appimage"
bun-target: bun-linux-x64
sidecar-name: stockai-backend-x86_64-unknown-linux-gnu
- platform: windows-latest
bun-target: bun-windows-x64
sidecar-name: stockai-backend-x86_64-pc-windows-msvc.exe
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v6
- name: Setup Bun
uses: oven-sh/setup-bun@v2.2.0
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust-targets }}
- name: Rust cache
uses: swatinem/rust-cache@v2.9.1
with:
workspaces: src-tauri
- name: Install Linux system dependencies
if: matrix.platform == 'ubuntu-24.04'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.1-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf
# Tauri 内置的 linuxdeploy(2024-07 老版)给 AppDir 解析依赖时,对 sidecar
# (Bun 编译的大二进制)跑 ldd 失败会直接 abort,导致 AppImage 打包 "failed to run linuxdeploy"。
# 预置较新版 linuxdeploy(遇 ldd 失败改为警告跳过)到 Tauri 缓存覆盖之。
# pin SHA256 防供应链篡改:哈希不符则构建 loud 失败,需人工复核后更新此值。
- name: Pre-seed pinned linuxdeploy (Linux AppImage)
if: matrix.platform == 'ubuntu-24.04'
env:
LD_SHA256: 514d4ffe2a2f757369b41863a4f63fbbb222c429652803ebc081cb16ba21ac25
run: |
mkdir -p ~/.cache/tauri
curl -fsSL --retry 5 -o ~/.cache/tauri/linuxdeploy-x86_64.AppImage \
https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
echo "${LD_SHA256} ${HOME}/.cache/tauri/linuxdeploy-x86_64.AppImage" | sha256sum -c -
chmod +x ~/.cache/tauri/linuxdeploy-x86_64.AppImage
- name: Install frontend dependencies
run: bun install
- name: Check macOS signing availability
id: check-signing
if: matrix.platform == 'macos-latest'
run: |
if [ -n "$APPLE_CERT" ]; then
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "available=false" >> "$GITHUB_OUTPUT"
echo "⚠️ APPLE_CERTIFICATE not configured, skipping code signing"
fi
env:
APPLE_CERT: ${{ secrets.APPLE_CERTIFICATE }}
- name: Import Apple Certificate
if: matrix.platform == 'macos-latest' && steps.check-signing.outputs.available == 'true'
uses: apple-actions/import-codesign-certs@v3
with:
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Build sidecar binary
shell: bash
env:
BUN_TARGET: ${{ matrix.bun-target }}
OUTFILE: src-tauri/bin/${{ matrix.sidecar-name }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
mkdir -p src-tauri/bin
# build-script.ts 内部已经处理了 BUN_NO_CODESIGN_MACHO_BINARY=1 和 xattr -cr 以及 codesign
bun sidecar/build-script.ts
# 验证二进制是否生成且已签名
ls -la src-tauri/bin/${{ matrix.sidecar-name }}
- name: Verify Sidecar Integrity & Signature
shell: bash
run: |
BINARY="src-tauri/bin/${{ matrix.sidecar-name }}"
bun scripts/verify-bundle.ts "$BINARY"
- name: Sidecar Self-Check
shell: bash
run: |
BINARY="src-tauri/bin/${{ matrix.sidecar-name }}"
echo "🚀 Running Sidecar Self-Check..."
# 检查二进制依赖 (macOS)
if [ "${{ matrix.platform }}" = "macos-latest" ]; then
echo "📚 Dependencies (otool -L):"
otool -L "$BINARY"
echo "🖋️ Signature Check (Pre-bundle):"
codesign -vvv --deep --strict "$BINARY"
fi
echo "✅ Sidecar binary verified (signature + dependencies checked above)."
- name: Check Signing Secrets
shell: bash
run: |
SIGNING_READY=true
if [ -z "${{ secrets.APPLE_CERTIFICATE }}" ]; then echo "⚠️ APPLE_CERTIFICATE missing"; SIGNING_READY=false; fi
if [ -z "${{ secrets.APPLE_CERTIFICATE_PASSWORD }}" ]; then echo "⚠️ APPLE_CERTIFICATE_PASSWORD missing"; SIGNING_READY=false; fi
if [ -z "${{ secrets.APPLE_SIGNING_IDENTITY }}" ]; then echo "⚠️ APPLE_SIGNING_IDENTITY missing"; SIGNING_READY=false; fi
if [ -z "${{ secrets.APPLE_ID }}" ]; then echo "⚠️ APPLE_ID missing"; SIGNING_READY=false; fi
if [ -z "${{ secrets.APPLE_PASSWORD }}" ]; then echo "⚠️ APPLE_PASSWORD missing"; SIGNING_READY=false; fi
if [ -z "${{ secrets.APPLE_TEAM_ID }}" ]; then echo "⚠️ APPLE_TEAM_ID missing"; SIGNING_READY=false; fi
if [ "$SIGNING_READY" = true ]; then
echo "✅ All macOS signing secrets are present. Pipeline will attempt signing and notarization."
else
echo "❌ Signing secrets incomplete. macOS build will be unsigned and may be marked as 'damaged'."
fi
- name: Deep Cleanup of Extended Attributes
if: matrix.platform == 'macos-latest'
shell: bash
run: |
echo "🧹 Cleaning up attributes for signing..."
find . -type f -exec xattr -c {} \; || true
- name: Build and publish release (signed)
if: matrix.platform != 'macos-latest' || steps.check-signing.outputs.available == 'true'
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
# 自动更新器签名私钥,缺失时 tauri-action 仍会构建但不生成 .sig/latest.json
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
# linuxdeploy(AppImage 格式)嵌套调用时需自解压运行,避免 runner 无 FUSE
APPIMAGE_EXTRACT_AND_RUN: 1
with:
tagName: ${{ github.ref_name }}
releaseName: "StockAI ${{ github.ref_name }}"
releaseBody: |
See the [CHANGELOG](https://github.com/hyhmrright/StockAI/blob/main/CHANGELOG.md) for what's new in this release.
releaseDraft: false
prerelease: false
args: ${{ matrix.args }}
- name: Build and publish release (unsigned macOS)
if: matrix.platform == 'macos-latest' && steps.check-signing.outputs.available != 'true'
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 即便 Apple 证书缺失,更新器仍需用 minisign 私钥签名产物
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
tagName: ${{ github.ref_name }}
releaseName: "StockAI ${{ github.ref_name }}"
releaseBody: |
See the [CHANGELOG](https://github.com/hyhmrright/StockAI/blob/main/CHANGELOG.md) for what's new in this release.
releaseDraft: false
prerelease: false
args: ${{ matrix.args }}
- name: Staple and Final Verify (macOS)
if: matrix.platform == 'macos-latest' && steps.check-signing.outputs.available == 'true'
shell: bash
run: |
echo "🔍 Searching for generated DMG..."
DMG_PATH=$(find src-tauri/target -name "StockAI_*_aarch64.dmg" | head -n 1)
if [ -z "$DMG_PATH" ]; then
echo "❌ DMG not found! Skipping staple check."
exit 1
fi
echo "✅ Found DMG: $DMG_PATH"
# 显式尝试装订公证票据 (Stapling)
echo "📨 Stapling notarization ticket..."
xcrun stapler staple "$DMG_PATH" || echo "⚠️ Stapling failed, maybe already stapled or notarization pending."
echo "📂 Mounting DMG for deep verification..."
mkdir -p /tmp/stockai_mnt
hdiutil attach "$DMG_PATH" -mountpoint /tmp/stockai_mnt
echo "🔍 Running Deep Integrity Check..."
bun scripts/verify-bundle.ts /tmp/stockai_mnt/StockAI.app
echo "🛡️ Verifying Gatekeeper Assessment..."
spctl --assess --type exec --context context:primary-signature --verbose /tmp/stockai_mnt/StockAI.app
echo "📤 Detaching DMG..."
hdiutil detach /tmp/stockai_mnt
echo "✨ Bundle integrity verified successfully."