Skip to content

你的提交说明

你的提交说明 #37

Workflow file for this run

name: Release Build
on:
push:
branches:
- main
- dev
tags:
- "v*"
paths:
- "apps/omninova-tauri/**"
- "crates/omninova-core/**"
- ".github/workflows/release.yml"
pull_request:
paths:
- "apps/omninova-tauri/**"
- "crates/omninova-core/**"
- ".github/workflows/release.yml"
workflow_dispatch:
concurrency:
group: release-build-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
permissions:
contents: write
pull-requests: write
packages: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
desktop:
name: Desktop ${{ matrix.name }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- name: Linux
os: ubuntu-latest
script: build:linux
check: linux
target: x86_64-unknown-linux-gnu
asset_platform: linux-x64
- name: macOS (Intel)
os: macos-latest
script: build:macos:intel
check: macos
target: x86_64-apple-darwin
asset_platform: macos-intel
- name: macOS (Apple Silicon)
os: macos-14
script: build:macos:apple
check: macos
target: aarch64-apple-darwin
asset_platform: macos-arm64
- name: Windows
os: windows-latest
script: build:windows
check: windows
target: x86_64-pc-windows-msvc
asset_platform: windows-x64
defaults:
run:
working-directory: apps/omninova-tauri
env:
APPLE_API_PRIVATE_KEY: ${{ secrets.APPLE_API_PRIVATE_KEY }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
APPLE_API_KEY: ${{ secrets.APPLE_API_KEY }}
# Rename to avoid auto-detection by Tauri
_APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
_APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup MSVC
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
- name: Fix Windows link.exe conflict
if: runner.os == 'Windows'
shell: powershell
run: |
$paths = @(
"C:\Program Files\Git\usr\bin\link.exe",
"C:\Program Files\Git\mingw64\bin\link.exe"
)
foreach ($path in $paths) {
if (Test-Path $path) {
Write-Host "Renaming conflict: $path"
Move-Item -Path $path -Destination "$path.bak" -Force
}
}
# Verify link.exe resolution
try {
$linkPath = (Get-Command link).Source
Write-Host "link.exe resolves to: $linkPath"
} catch {
Write-Host "link.exe not found in PATH (this is okay if MSVC sets it up later, but usually it should be there)"
}
- name: Install create-dmg
if: runner.os == 'macOS'
run: brew install create-dmg
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: apps/omninova-tauri/package-lock.json
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
. -> target
apps/omninova-tauri/src-tauri -> target
- name: Install Linux system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
pkg-config \
build-essential
- name: Install frontend dependencies
run: npm ci
- name: Setup Apple API key
if: runner.os == 'macOS' && env.APPLE_API_PRIVATE_KEY != '' && env.APPLE_API_ISSUER != '' && env.APPLE_API_KEY != ''
shell: bash
run: |
APPLE_API_KEY_PATH="$RUNNER_TEMP/AuthKey_${APPLE_API_KEY}.p8"
printf '%s' "$APPLE_API_PRIVATE_KEY" > "$APPLE_API_KEY_PATH"
echo "APPLE_API_KEY=$APPLE_API_KEY" >> "$GITHUB_ENV"
echo "APPLE_API_ISSUER=$APPLE_API_ISSUER" >> "$GITHUB_ENV"
echo "APPLE_API_KEY_PATH=$APPLE_API_KEY_PATH" >> "$GITHUB_ENV"
- name: Import macOS signing certificate
if: runner.os == 'macOS' && env._APPLE_CERTIFICATE != '' && env._APPLE_CERTIFICATE_PASSWORD != ''
shell: bash
run: |
KEYCHAIN_PATH="$RUNNER_TEMP/omninova-signing.keychain-db"
CERT_PATH="$RUNNER_TEMP/omninova-signing.p12"
printf '%s' "$_APPLE_CERTIFICATE" | base64 --decode > "$CERT_PATH"
security create-keychain -p "" "$KEYCHAIN_PATH"
security set-keychain-settings -t 3600 -u "$KEYCHAIN_PATH"
security unlock-keychain -p "" "$KEYCHAIN_PATH"
security import "$CERT_PATH" -P "$_APPLE_CERTIFICATE_PASSWORD" -A -f pkcs12 -k "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | sed s/\"//g)
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" "$KEYCHAIN_PATH"
- name: Prepare release metadata
id: meta
shell: bash
run: |
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
VERSION="${GITHUB_REF_NAME#v}"
else
BRANCH_NAME="${GITHUB_REF_NAME:-branch}"
SANITIZED_BRANCH=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | sed 's#[^a-z0-9._-]#-#g')
VERSION="${SANITIZED_BRANCH}-sha-${GITHUB_SHA::7}"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check build environment
run: node ./scripts/check-build-env.mjs ${{ matrix.check }}
- name: Build Tauri app
shell: bash
env:
_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
_APPLE_ID: ${{ secrets.APPLE_ID }}
_APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
_APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_API_KEY: ${{ env.APPLE_API_KEY }}
APPLE_API_KEY_PATH: ${{ env.APPLE_API_KEY_PATH }}
APPLE_API_ISSUER: ${{ env.APPLE_API_ISSUER }}
run: |
if [ -n "$_SIGNING_IDENTITY" ]; then export APPLE_SIGNING_IDENTITY="$_SIGNING_IDENTITY"; fi
if [ -n "$_APPLE_ID" ]; then export APPLE_ID="$_APPLE_ID"; fi
if [ -n "$_APPLE_PASSWORD" ]; then export APPLE_PASSWORD="$_APPLE_PASSWORD"; fi
if [ -n "$_APPLE_TEAM_ID" ]; then export APPLE_TEAM_ID="$_APPLE_TEAM_ID"; fi
npm run ${{ matrix.script }}
- name: Resolve bundle path
id: resolve_path
shell: bash
run: |
# Check workspace root target (standard for workspace members)
WS_TARGET_PATH="../../target/${{ matrix.target }}/release/bundle"
WS_FLAT_PATH="../../target/release/bundle"
# Check package local target (if configured or standalone)
PKG_TARGET_PATH="./src-tauri/target/${{ matrix.target }}/release/bundle"
PKG_FLAT_PATH="./src-tauri/target/release/bundle"
if [ -d "$WS_TARGET_PATH" ]; then
echo "Found bundle at workspace target path: $WS_TARGET_PATH"
echo "bundle_path=$WS_TARGET_PATH" >> "$GITHUB_OUTPUT"
elif [ -d "$WS_FLAT_PATH" ]; then
echo "Found bundle at workspace flat path: $WS_FLAT_PATH"
echo "bundle_path=$WS_FLAT_PATH" >> "$GITHUB_OUTPUT"
elif [ -d "$PKG_TARGET_PATH" ]; then
echo "Found bundle at package target path: $PKG_TARGET_PATH"
echo "bundle_path=$PKG_TARGET_PATH" >> "$GITHUB_OUTPUT"
elif [ -d "$PKG_FLAT_PATH" ]; then
echo "Found bundle at package flat path: $PKG_FLAT_PATH"
echo "bundle_path=$PKG_FLAT_PATH" >> "$GITHUB_OUTPUT"
else
echo "Error: Bundle directory not found."
echo "Searched locations:"
echo "- $WS_TARGET_PATH"
echo "- $WS_FLAT_PATH"
echo "- $PKG_TARGET_PATH"
echo "- $PKG_FLAT_PATH"
echo "Listing workspace target directory:"
ls -F ../../target/release || echo "workspace target/release not found"
ls -F ../../target/${{ matrix.target }}/release || echo "workspace target/${{ matrix.target }}/release not found"
exit 1
fi
- name: Stage desktop release assets
run: >
node ./scripts/stage-release-assets.mjs
${{ steps.resolve_path.outputs.bundle_path }}
./release-assets
${{ matrix.asset_platform }}
${{ steps.meta.outputs.version }}
- name: Upload desktop bundle
uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.asset_platform }}
path: apps/omninova-tauri/release-assets/**
if-no-files-found: warn
release:
name: Publish GitHub Release
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs:
- desktop
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: release-*
path: release-assets
merge-multiple: true
- name: Collect and deduplicate artifacts
working-directory: release-assets
run: |
rm -f SHA256SUMS.txt
find . -mindepth 2 -name "SHA256SUMS.txt" -type f -delete
mapfile -t release_files < <(
find . -type f \
\( -name "*.dmg" -o -name "*.deb" -o -name "*.appimage" -o -name "*.rpm" -o -name "*.exe" -o -name "*.msi" -o -name "*.tar.gz" \) \
-print | sort
)
if [ "${#release_files[@]}" -eq 0 ]; then
echo "No release artifacts found after download."
exit 1
fi
sha256sum "${release_files[@]}" > SHA256SUMS.txt
if [ ! -s SHA256SUMS.txt ]; then
echo "Generated SHA256SUMS.txt is empty."
exit 1
fi
- name: Publish release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
prerelease: ${{ contains(github.ref_name, '-') }}
overwrite_files: true
files: |
release-assets/**/*.dmg
release-assets/**/*.deb
release-assets/**/*.appimage
release-assets/**/*.rpm
release-assets/**/*.exe
release-assets/**/*.msi
release-assets/**/*.tar.gz
release-assets/SHA256SUMS.txt