Skip to content

fix: improve manual report export and linux appimage build #73

fix: improve manual report export and linux appimage build

fix: improve manual report export and linux appimage build #73

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
jobs:
build-tauri:
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
args: "--target aarch64-apple-darwin"
target: aarch64-apple-darwin
- platform: macos-latest
args: "--target x86_64-apple-darwin"
target: x86_64-apple-darwin
- platform: ubuntu-22.04
args: "--target x86_64-unknown-linux-gnu"
target: x86_64-unknown-linux-gnu
- platform: windows-latest
args: ""
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- name: Install Linux build dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
patchelf \
libfuse2
- name: Install frontend dependencies
run: npm install
- name: Build application
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: npm run tauri build -- ${{ matrix.args }}
- name: Rename macOS updater assets
if: startsWith(matrix.platform, 'macos')
shell: bash
run: |
set -euo pipefail
normalize_name() {
local filename="$1"
printf '%s' "${filename// /_}"
}
if [[ "${{ matrix.target }}" == "aarch64-apple-darwin" ]]; then
ARCH_SUFFIX="aarch64"
else
ARCH_SUFFIX="x64"
fi
find src-tauri/target -type f -path "*/release/bundle/macos/*.app.tar.gz" | while read -r file; do
dir="$(dirname "$file")"
base="$(basename "$file" ".app.tar.gz")"
normalized_base="$(normalize_name "$base")"
renamed="${dir}/${normalized_base}_${ARCH_SUFFIX}.app.tar.gz"
mv "$file" "$renamed"
if [[ -f "${file}.sig" ]]; then
mv "${file}.sig" "${renamed}.sig"
fi
done
find src-tauri/target -type f -path "*/release/bundle/dmg/*.dmg" | while read -r file; do
dir="$(dirname "$file")"
name="$(basename "$file")"
normalized_name="$(normalize_name "$name")"
renamed="${dir}/${normalized_name}"
if [[ "$file" != "$renamed" ]]; then
mv "$file" "$renamed"
fi
done
- name: Rename Windows installer assets
if: startsWith(matrix.platform, 'windows')
shell: bash
run: |
set -euo pipefail
normalize_name() {
local filename="$1"
printf '%s' "${filename// /_}"
}
find src-tauri/target -type f -path "*/release/bundle/nsis/*.exe" | while read -r file; do
dir="$(dirname "$file")"
name="$(basename "$file")"
normalized_name="$(normalize_name "$name")"
renamed="${dir}/${normalized_name}"
if [[ "$file" != "$renamed" ]]; then
mv "$file" "$renamed"
fi
if [[ -f "${file}.sig" ]]; then
mv "${file}.sig" "${renamed}.sig"
fi
done
- name: Rename Linux bundle assets
if: startsWith(matrix.platform, 'ubuntu')
shell: bash
run: |
set -euo pipefail
normalize_name() {
local filename="$1"
printf '%s' "${filename// /_}"
}
find src-tauri/target -type f -path "*/release/bundle/appimage/*.AppImage" | while read -r file; do
dir="$(dirname "$file")"
name="$(basename "$file")"
normalized_name="$(normalize_name "$name")"
renamed="${dir}/${normalized_name}"
if [[ "$file" != "$renamed" ]]; then
mv "$file" "$renamed"
fi
done
find src-tauri/target -type f -path "*/release/bundle/deb/*.deb" | while read -r file; do
dir="$(dirname "$file")"
name="$(basename "$file")"
normalized_name="$(normalize_name "$name")"
renamed="${dir}/${normalized_name}"
if [[ "$file" != "$renamed" ]]; then
mv "$file" "$renamed"
fi
done
- name: Verify required artifacts
shell: bash
run: |
set -euo pipefail
require_file() {
local pattern="$1"
local label="$2"
local match
match="$(find src-tauri/target -type f -path "$pattern" | sort | head -n 1 || true)"
if [[ -z "$match" ]]; then
echo "缺少 ${label}: ${pattern}" >&2
exit 1
fi
echo "${label}: ${match}"
}
case "${{ matrix.target }}" in
aarch64-apple-darwin)
require_file "*/release/bundle/macos/*_aarch64.app.tar.gz" "macOS aarch64 自动更新包"
require_file "*/release/bundle/macos/*_aarch64.app.tar.gz.sig" "macOS aarch64 自动更新签名"
require_file "*/release/bundle/dmg/*.dmg" "macOS aarch64 DMG"
;;
x86_64-apple-darwin)
require_file "*/release/bundle/macos/*_x64.app.tar.gz" "macOS x64 自动更新包"
require_file "*/release/bundle/macos/*_x64.app.tar.gz.sig" "macOS x64 自动更新签名"
require_file "*/release/bundle/dmg/*.dmg" "macOS x64 DMG"
;;
x86_64-unknown-linux-gnu)
require_file "*/release/bundle/appimage/*.AppImage" "Linux AppImage"
require_file "*/release/bundle/deb/*.deb" "Linux DEB"
;;
x86_64-pc-windows-msvc)
require_file "*/release/bundle/nsis/*.exe" "Windows 安装包"
require_file "*/release/bundle/nsis/*.sig" "Windows 安装包签名"
;;
esac
- name: Upload release assets
uses: actions/upload-artifact@v4
with:
name: release-assets-${{ matrix.platform }}-${{ strategy.job-index }}
path: |
src-tauri/target/**/release/bundle/dmg/*.dmg
src-tauri/target/**/release/bundle/dmg/*.sig
src-tauri/target/**/release/bundle/macos/*.app.tar.gz
src-tauri/target/**/release/bundle/macos/*.app.tar.gz.sig
src-tauri/target/**/release/bundle/nsis/*.exe
src-tauri/target/**/release/bundle/nsis/*.sig
src-tauri/target/**/release/bundle/appimage/*.AppImage
src-tauri/target/**/release/bundle/deb/*.deb
if-no-files-found: error
publish-release:
needs: build-tauri
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: all-artifacts
pattern: "release-assets-*"
merge-multiple: true
- name: Extract changelog
shell: bash
run: |
set -euo pipefail
VERSION="${GITHUB_REF_NAME#v}"
BODY=$(awk "/^## \[${VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md)
if [[ -z "$BODY" ]]; then
BODY="版本 ${VERSION} 更新"
fi
BODY="${BODY}
### macOS 安装说明
首次打开可能提示「已损坏,无法打开」,请执行:
\`\`\`bash
sudo xattr -rd com.apple.quarantine '/Applications/Work Review.app'
\`\`\`"
printf '%s\n' "$BODY" > release_notes.md
- name: Build updater.json from signatures
shell: bash
env:
VERSION: ${{ github.ref_name }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
DOWNLOAD_BASE="https://github.com/${REPO}/releases/download/${VERSION}"
VER="${VERSION#v}"
NOTES="$(cat release_notes.md)"
PUB_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
MAC_AARCH64_FILE="$(find all-artifacts -type f -name '*_aarch64.app.tar.gz' | sort | head -n 1 || true)"
MAC_X64_FILE="$(find all-artifacts -type f -name '*_x64.app.tar.gz' | sort | head -n 1 || true)"
WINDOWS_FILE="$(find all-artifacts -type f \( -name '*setup.exe' -o -name '*installer.exe' \) ! -name '*.sig' | sort | head -n 1 || true)"
require_asset() {
local asset_file="$1"
local signature_file="$2"
local label="$3"
if [[ -z "$asset_file" || ! -f "$asset_file" ]]; then
echo "缺少 ${label} 产物" >&2
exit 1
fi
if [[ ! -f "$signature_file" ]]; then
echo "缺少 ${label} 签名: ${signature_file}" >&2
exit 1
fi
echo "${label}: ${asset_file}"
}
require_asset "$MAC_AARCH64_FILE" "${MAC_AARCH64_FILE}.sig" "darwin-aarch64"
require_asset "$MAC_X64_FILE" "${MAC_X64_FILE}.sig" "darwin-x86_64"
require_asset "$WINDOWS_FILE" "${WINDOWS_FILE}.sig" "windows-x86_64"
json="$(jq -n \
--arg version "$VER" \
--arg notes "$NOTES" \
--arg pub_date "$PUB_DATE" \
'{version: $version, notes: $notes, pub_date: $pub_date, platforms: {}}')"
add_platform() {
local platform_key="$1"
local asset_file="$2"
local signature_file="$3"
local base_url="$4"
if [[ -z "$asset_file" || ! -f "$asset_file" || ! -f "$signature_file" ]]; then
echo "skip ${platform_key}"
return
fi
local signature
signature="$(tr -d '\r\n' < "$signature_file")"
local asset_name
asset_name="$(basename "$asset_file")"
variant_json="$(jq \
--arg key "$platform_key" \
--arg url "${base_url}/${asset_name}" \
--arg signature "$signature" \
'.platforms[$key] = { url: $url, signature: $signature }' \
<<<"$variant_json")"
}
# 为每个代理前缀生成独立的 updater JSON 文件
# 格式: "前缀 文件名"(前缀为空表示直连 GitHub)
PROXY_VARIANTS=(
" updater.json"
"https://ghproxy.cn/ updater-ghproxy.json"
"https://ghp.ci/ updater-ghp.json"
)
for variant in "${PROXY_VARIANTS[@]}"; do
proxy_prefix="${variant%% *}"
output_file="${variant##* }"
if [[ -z "$proxy_prefix" ]]; then
VARIANT_BASE="${DOWNLOAD_BASE}"
else
VARIANT_BASE="${proxy_prefix}${DOWNLOAD_BASE}"
fi
variant_json="$json"
add_platform "darwin-aarch64" "$MAC_AARCH64_FILE" "${MAC_AARCH64_FILE}.sig" "$VARIANT_BASE"
add_platform "darwin-x86_64" "$MAC_X64_FILE" "${MAC_X64_FILE}.sig" "$VARIANT_BASE"
add_platform "windows-x86_64" "$WINDOWS_FILE" "${WINDOWS_FILE}.sig" "$VARIANT_BASE"
if [[ "$(jq '.platforms | length' <<<"$variant_json")" -ne 3 ]]; then
echo "自动更新平台数量异常 (${output_file}),期望 3 个,实际为 $(jq '.platforms | length' <<<"$variant_json")" >&2
exit 1
fi
printf '%s\n' "$variant_json" > "$output_file"
echo "=== ${output_file} ==="
cat "$output_file"
done
- name: Create or update GitHub Release
uses: ncipollo/release-action@v1
with:
allowUpdates: true
name: "Work_Review ${{ github.ref_name }}"
bodyFile: release_notes.md
token: ${{ secrets.GITHUB_TOKEN }}
artifacts: "all-artifacts/**/*,updater.json,updater-ghproxy.json,updater-ghp.json"
artifactErrorsFailBuild: false
replacesArtifacts: true
makeLatest: legacy