🎨 調整發布流程

This commit is contained in:
Minidoracat 2025-06-15 18:17:45 +08:00
parent ff5a6c317d
commit 94aa415648
6 changed files with 664 additions and 73 deletions

148
.github/workflows/build-and-release.yml vendored Normal file
View File

@ -0,0 +1,148 @@
name: Build Desktop & Release
on:
workflow_dispatch:
inputs:
version_type:
description: 'Version bump type (ignored if custom_version is provided)'
required: false
default: 'patch'
type: choice
options:
- patch # 2.0.0 -> 2.0.1 (bug fixes, security patches, documentation updates)
- minor # 2.0.0 -> 2.1.0 (new features, enhancements, backward-compatible changes)
- major # 2.0.0 -> 3.0.0 (breaking changes, architecture refactoring, API changes)
custom_version:
description: 'Custom version number (e.g., 2.5.0) - overrides version_type if provided'
required: false
type: string
platforms:
description: '選擇要構建的平台'
required: true
default: 'all'
type: choice
options:
- all
- windows
- macos
- linux
skip_release:
description: '只構建桌面應用,不進行發佈'
required: false
default: false
type: boolean
jobs:
# 第一步:構建桌面應用
build-desktop:
name: Build Desktop Applications
uses: ./.github/workflows/build-desktop.yml
with:
platforms: ${{ github.event.inputs.platforms }}
upload_artifacts: true
# 第二步:等待構建完成並檢查結果
check-build:
name: Check Build Results
needs: build-desktop
runs-on: ubuntu-latest
outputs:
can_release: ${{ steps.check.outputs.can_release }}
build_run_id: ${{ steps.check.outputs.build_run_id }}
steps:
- name: Check build results
id: check
run: |
echo "🔍 檢查桌面應用構建結果..."
# 檢查構建是否成功
if [ "${{ needs.build-desktop.result }}" = "success" ]; then
echo "✅ 桌面應用構建成功"
echo "can_release=true" >> $GITHUB_OUTPUT
echo "build_run_id=${{ github.run_id }}" >> $GITHUB_OUTPUT
else
echo "❌ 桌面應用構建失敗"
echo "can_release=false" >> $GITHUB_OUTPUT
exit 1
fi
- name: Generate summary
run: |
echo "## 🖥️ 桌面應用構建完成" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ✅ 構建結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **狀態**: 成功 ✅" >> $GITHUB_STEP_SUMMARY
echo "- **平台**: ${{ github.event.inputs.platforms }}" >> $GITHUB_STEP_SUMMARY
echo "- **Run ID**: ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event.inputs.skip_release }}" = "true" ]; then
echo "### ⏭️ 跳過發佈" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "根據設置,已跳過自動發佈。" >> $GITHUB_STEP_SUMMARY
echo "如需發佈,請手動運行 [Auto Release to PyPI](../../actions/workflows/publish.yml) 工作流程。" >> $GITHUB_STEP_SUMMARY
else
echo "### 🚀 準備發佈" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "桌面應用構建成功,正在準備自動發佈..." >> $GITHUB_STEP_SUMMARY
fi
# 第三步:自動發佈(如果沒有跳過)
release:
name: Auto Release to PyPI
needs: [build-desktop, check-build]
if: ${{ needs.check-build.outputs.can_release == 'true' && github.event.inputs.skip_release != 'true' }}
uses: ./.github/workflows/publish.yml
with:
version_type: ${{ github.event.inputs.version_type }}
custom_version: ${{ github.event.inputs.custom_version }}
include_desktop: true
desktop_build_run_id: ${{ needs.check-build.outputs.build_run_id }}
secrets: inherit
# 最終摘要
summary:
name: Workflow Summary
needs: [build-desktop, check-build, release]
runs-on: ubuntu-latest
if: always()
steps:
- name: Generate final summary
run: |
echo "## 🎯 構建和發佈摘要" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 桌面構建狀態
echo "### 🖥️ 桌面應用構建" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.build-desktop.result }}" = "success" ]; then
echo "- ✅ **成功** - 所有選定平台構建完成" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ **失敗** - 構建過程中出現錯誤" >> $GITHUB_STEP_SUMMARY
fi
# 發佈狀態
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 發佈狀態" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event.inputs.skip_release }}" = "true" ]; then
echo "- ⏭️ **已跳過** - 根據用戶設置跳過發佈" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.release.result }}" = "success" ]; then
echo "- ✅ **成功** - 已發佈到 PyPI 和 GitHub Releases" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.release.result }}" = "failure" ]; then
echo "- ❌ **失敗** - 發佈過程中出現錯誤" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.release.result }}" = "skipped" ]; then
echo "- ⏭️ **已跳過** - 由於桌面構建失敗而跳過" >> $GITHUB_STEP_SUMMARY
else
echo "- ⏳ **進行中** - 發佈正在進行中" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔗 相關鏈接" >> $GITHUB_STEP_SUMMARY
echo "- [桌面構建工作流程](../../actions/workflows/build-desktop.yml)" >> $GITHUB_STEP_SUMMARY
echo "- [發佈工作流程](../../actions/workflows/publish.yml)" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.release.result }}" = "success" ]; then
echo "- [PyPI 頁面](https://pypi.org/project/mcp-feedback-enhanced/)" >> $GITHUB_STEP_SUMMARY
echo "- [GitHub Releases](../../releases)" >> $GITHUB_STEP_SUMMARY
fi

View File

@ -97,18 +97,47 @@ jobs:
${{ runner.os }}-cargo-${{ matrix.target }}- ${{ runner.os }}-cargo-${{ matrix.target }}-
${{ runner.os }}-cargo- ${{ runner.os }}-cargo-
- name: Install platform-specific dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libgtk-3-dev \
libayatana-appindicator3-dev
- name: Build desktop application for ${{ matrix.name }} - name: Build desktop application for ${{ matrix.name }}
run: | run: |
cd src-tauri cd src-tauri
echo "🔨 開始構建 ${{ matrix.name }} (${{ matrix.target }})..."
cargo build --release --target ${{ matrix.target }} --bin mcp-feedback-enhanced-desktop cargo build --release --target ${{ matrix.target }} --bin mcp-feedback-enhanced-desktop
echo "✅ 構建完成"
- name: Verify build output - name: Verify build output
run: | run: |
echo "🔍 檢查構建產物..." echo "🔍 檢查構建產物..."
if [ "${{ matrix.os }}" = "windows-latest" ]; then BINARY_PATH="src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}"
ls -la "src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}" || echo "❌ Windows 二進制文件不存在"
if [ -f "$BINARY_PATH" ]; then
echo "✅ 找到二進制文件: $BINARY_PATH"
ls -la "$BINARY_PATH"
# 檢查文件大小
FILE_SIZE=$(stat -f%z "$BINARY_PATH" 2>/dev/null || stat -c%s "$BINARY_PATH" 2>/dev/null || echo "unknown")
echo "📏 文件大小: $FILE_SIZE bytes"
# 檢查文件類型 (僅在 Linux/macOS)
if [ "${{ matrix.os }}" != "windows-latest" ]; then
file "$BINARY_PATH" || echo "無法檢查文件類型"
fi
else else
ls -la "src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}" || echo "❌ ${{ matrix.name }} 二進制文件不存在" echo "❌ ${{ matrix.name }} 二進制文件不存在: $BINARY_PATH"
echo "🔍 檢查目標目錄內容:"
ls -la "src-tauri/target/${{ matrix.target }}/release/" || echo "目標目錄不存在"
exit 1
fi fi
shell: bash shell: bash
@ -120,14 +149,38 @@ jobs:
path: src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }} path: src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}
retention-days: 30 # 保留 30 天 retention-days: 30 # 保留 30 天
compression-level: 6 compression-level: 6
if-no-files-found: error # 如果沒有找到文件則失敗
# 構建摘要 # 構建摘要和驗證
build-summary: build-summary:
needs: build-desktop needs: build-desktop
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: always() if: always()
outputs:
build_success: ${{ steps.check_results.outputs.success }}
platforms_built: ${{ steps.check_results.outputs.platforms }}
steps: steps:
- name: Check build results
id: check_results
run: |
echo "🔍 檢查構建結果..."
# 檢查構建狀態
BUILD_SUCCESS="false"
PLATFORMS_BUILT=""
if [ "${{ needs.build-desktop.result }}" = "success" ]; then
BUILD_SUCCESS="true"
PLATFORMS_BUILT="windows,macos-intel,macos-arm64,linux"
echo "✅ 所有平台構建成功"
else
echo "❌ 構建失敗或部分失敗"
fi
echo "success=$BUILD_SUCCESS" >> $GITHUB_OUTPUT
echo "platforms=$PLATFORMS_BUILT" >> $GITHUB_OUTPUT
- name: Generate build summary - name: Generate build summary
run: | run: |
echo "## 🖥️ 桌面應用構建摘要" >> $GITHUB_STEP_SUMMARY echo "## 🖥️ 桌面應用構建摘要" >> $GITHUB_STEP_SUMMARY
@ -137,16 +190,43 @@ jobs:
# 檢查各平台構建狀態 # 檢查各平台構建狀態
if [ "${{ needs.build-desktop.result }}" = "success" ]; then if [ "${{ needs.build-desktop.result }}" = "success" ]; then
echo "✅ 所有平台構建成功" >> $GITHUB_STEP_SUMMARY echo "✅ **所有平台構建成功**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| 平台 | 狀態 | 產物名稱 |" >> $GITHUB_STEP_SUMMARY
echo "|------|------|----------|" >> $GITHUB_STEP_SUMMARY
echo "| Windows x64 | ✅ 成功 | \`desktop-windows\` |" >> $GITHUB_STEP_SUMMARY
echo "| macOS Intel | ✅ 成功 | \`desktop-macos-intel\` |" >> $GITHUB_STEP_SUMMARY
echo "| macOS ARM64 | ✅ 成功 | \`desktop-macos-arm64\` |" >> $GITHUB_STEP_SUMMARY
echo "| Linux x64 | ✅ 成功 | \`desktop-linux\` |" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.build-desktop.result }}" = "failure" ]; then elif [ "${{ needs.build-desktop.result }}" = "failure" ]; then
echo "❌ 部分平台構建失敗" >> $GITHUB_STEP_SUMMARY echo "❌ **部分平台構建失敗**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "請檢查各平台的構建日誌以了解失敗原因。" >> $GITHUB_STEP_SUMMARY
else else
echo "⚠️ 構建狀態: ${{ needs.build-desktop.result }}" >> $GITHUB_STEP_SUMMARY echo "⚠️ **構建狀態**: ${{ needs.build-desktop.result }}" >> $GITHUB_STEP_SUMMARY
fi fi
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### 下一步" >> $GITHUB_STEP_SUMMARY echo "### 📦 產物信息" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "- 構建產物已上傳到 GitHub Artifacts" >> $GITHUB_STEP_SUMMARY echo "- **保留期限**: 30 天" >> $GITHUB_STEP_SUMMARY
echo "- 可以在發佈流程中使用這些二進制文件" >> $GITHUB_STEP_SUMMARY echo "- **下載位置**: GitHub Actions Artifacts" >> $GITHUB_STEP_SUMMARY
echo "- 如需重新構建,請手動觸發此工作流程" >> $GITHUB_STEP_SUMMARY echo "- **使用方式**: 在發佈工作流程中自動下載" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🚀 下一步" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.build-desktop.result }}" = "success" ]; then
echo "✅ **可以進行發佈**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "1. 前往 [Auto Release to PyPI](../../actions/workflows/publish.yml)" >> $GITHUB_STEP_SUMMARY
echo "2. 點擊 'Run workflow'" >> $GITHUB_STEP_SUMMARY
echo "3. 設置 'include_desktop' 為 true" >> $GITHUB_STEP_SUMMARY
echo "4. 可選:指定此次構建的 Run ID: \`${{ github.run_id }}\`" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **請修復構建問題後重新運行**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- 檢查構建日誌中的錯誤信息" >> $GITHUB_STEP_SUMMARY
echo "- 修復問題後重新觸發此工作流程" >> $GITHUB_STEP_SUMMARY
echo "- 確保所有平台都能成功構建後再進行發佈" >> $GITHUB_STEP_SUMMARY
fi

View File

@ -287,93 +287,170 @@ jobs:
- Auto-generated release from workflow" - Auto-generated release from workflow"
git tag "v${{ steps.bump_version.outputs.new }}" git tag "v${{ steps.bump_version.outputs.new }}"
- name: Download desktop binaries from latest build - name: Check desktop build availability
if: ${{ github.event.inputs.include_desktop == 'true' }}
id: check_desktop
run: |
echo "🔍 檢查桌面應用構建可用性..."
# 如果指定了 run_id使用指定的構建
if [ -n "${{ github.event.inputs.desktop_build_run_id }}" ]; then
echo "🎯 使用指定的構建 Run ID: ${{ github.event.inputs.desktop_build_run_id }}"
echo "run_id=${{ github.event.inputs.desktop_build_run_id }}" >> $GITHUB_OUTPUT
else
echo "🔍 查找最新的成功桌面構建..."
# 使用 GitHub API 查找最新的成功構建
LATEST_RUN=$(curl -s \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-desktop.yml/runs?status=success&per_page=1" \
| jq -r '.workflow_runs[0].id // empty')
if [ -n "$LATEST_RUN" ] && [ "$LATEST_RUN" != "null" ]; then
echo "✅ 找到最新成功構建: $LATEST_RUN"
echo "run_id=$LATEST_RUN" >> $GITHUB_OUTPUT
else
echo "❌ 沒有找到成功的桌面構建"
echo "💡 請先運行 'Build Desktop Applications' 工作流程"
exit 1
fi
fi
- name: Download desktop binaries
if: ${{ github.event.inputs.include_desktop == 'true' }} if: ${{ github.event.inputs.include_desktop == 'true' }}
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@v6
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-desktop.yml workflow: build-desktop.yml
run_id: ${{ github.event.inputs.desktop_build_run_id }} run_id: ${{ steps.check_desktop.outputs.run_id }}
path: desktop-artifacts path: desktop-artifacts
if_no_artifact_found: warn if_no_artifact_found: error
- name: Prepare multi-platform desktop binaries - name: Prepare multi-platform desktop binaries
if: ${{ github.event.inputs.include_desktop == 'true' }} if: ${{ github.event.inputs.include_desktop == 'true' }}
run: | run: |
# 檢查是否有桌面應用構建產物 echo "📦 準備多平台桌面應用二進制文件..."
if [ ! -d "desktop-artifacts" ] || [ -z "$(ls -A desktop-artifacts 2>/dev/null)" ]; then
echo "⚠️ 警告:沒有找到桌面應用構建產物" # 檢查下載的產物
echo "💡 提示:請先運行 'Build Desktop Applications' 工作流程" echo "🔍 檢查下載的桌面應用產物..."
echo "🔧 或者設置 include_desktop 為 false 來跳過桌面應用" if [ ! -d "desktop-artifacts" ]; then
echo "❌ 桌面產物目錄不存在"
exit 1 exit 1
fi fi
echo "📁 產物目錄內容:"
find desktop-artifacts -type f -name "*" | head -20
# 創建桌面應用目錄 # 創建桌面應用目錄
mkdir -p src/mcp_feedback_enhanced/desktop_release mkdir -p src/mcp_feedback_enhanced/desktop_release
# 複製所有平台的二進制文件並重命名 # 定義平台映射
echo "📦 準備多平台桌面應用二進制文件..." declare -A PLATFORM_MAP=(
["desktop-windows"]="mcp-feedback-enhanced-desktop.exe"
["desktop-macos-intel"]="mcp-feedback-enhanced-desktop-macos-intel"
["desktop-macos-arm64"]="mcp-feedback-enhanced-desktop-macos-arm64"
["desktop-linux"]="mcp-feedback-enhanced-desktop-linux"
)
# 檢查並複製各平台文件 # 複製並重命名二進制文件
if [ -f "desktop-artifacts/desktop-windows/mcp-feedback-enhanced-desktop.exe" ]; then COPIED_COUNT=0
cp desktop-artifacts/desktop-windows/mcp-feedback-enhanced-desktop.exe src/mcp_feedback_enhanced/desktop_release/ TOTAL_PLATFORMS=4
echo "✅ Windows 二進制文件已複製"
else
echo "⚠️ Windows 二進制文件不存在"
fi
if [ -f "desktop-artifacts/desktop-macos-intel/mcp-feedback-enhanced-desktop" ]; then for platform_dir in desktop-windows desktop-macos-intel desktop-macos-arm64 desktop-linux; do
cp desktop-artifacts/desktop-macos-intel/mcp-feedback-enhanced-desktop src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel echo "🔍 處理平台: $platform_dir"
echo "✅ macOS Intel 二進制文件已複製"
else
echo "⚠️ macOS Intel 二進制文件不存在"
fi
if [ -f "desktop-artifacts/desktop-macos-arm64/mcp-feedback-enhanced-desktop" ]; then # 查找該平台的二進制文件
cp desktop-artifacts/desktop-macos-arm64/mcp-feedback-enhanced-desktop src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-arm64 BINARY_FILE=""
echo "✅ macOS ARM64 二進制文件已複製" if [ -d "desktop-artifacts/$platform_dir" ]; then
else # 查找二進制文件(可能是 .exe 或無擴展名)
echo "⚠️ macOS ARM64 二進制文件不存在" BINARY_FILE=$(find "desktop-artifacts/$platform_dir" -name "mcp-feedback-enhanced-desktop*" -type f | head -1)
fi fi
if [ -f "desktop-artifacts/desktop-linux/mcp-feedback-enhanced-desktop" ]; then if [ -n "$BINARY_FILE" ] && [ -f "$BINARY_FILE" ]; then
cp desktop-artifacts/desktop-linux/mcp-feedback-enhanced-desktop src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux TARGET_NAME="${PLATFORM_MAP[$platform_dir]}"
echo "✅ Linux 二進制文件已複製" cp "$BINARY_FILE" "src/mcp_feedback_enhanced/desktop_release/$TARGET_NAME"
else
echo "⚠️ Linux 二進制文件不存在"
fi
# 設置執行權限 # 設置執行權限(非 Windows
chmod +x src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-* 2>/dev/null || true if [[ "$TARGET_NAME" != *.exe ]]; then
chmod +x "src/mcp_feedback_enhanced/desktop_release/$TARGET_NAME"
fi
echo "✅ $platform_dir: $BINARY_FILE -> $TARGET_NAME"
COPIED_COUNT=$((COPIED_COUNT + 1))
else
echo "⚠️ $platform_dir: 未找到二進制文件"
fi
done
# 創建 __init__.py # 創建 __init__.py
echo '"""桌面應用程式二進制檔案"""' > src/mcp_feedback_enhanced/desktop_release/__init__.py echo '"""桌面應用程式二進制檔案"""' > src/mcp_feedback_enhanced/desktop_release/__init__.py
# 顯示文件列表 # 驗證結果
echo ""
echo "📊 複製結果統計:"
echo " 成功複製: $COPIED_COUNT/$TOTAL_PLATFORMS 個平台"
if [ $COPIED_COUNT -eq 0 ]; then
echo "❌ 沒有成功複製任何平台的二進制文件"
exit 1
elif [ $COPIED_COUNT -lt $TOTAL_PLATFORMS ]; then
echo "⚠️ 部分平台缺失,但繼續發佈"
else
echo "✅ 所有平台都已成功複製"
fi
# 顯示最終文件列表
echo ""
echo "📦 最終的桌面應用二進制文件:" echo "📦 最終的桌面應用二進制文件:"
ls -la src/mcp_feedback_enhanced/desktop_release/ ls -la src/mcp_feedback_enhanced/desktop_release/
- name: Build desktop applications locally (fallback) - name: Validate desktop binaries
if: ${{ github.event.inputs.include_desktop == 'true' }} if: ${{ github.event.inputs.include_desktop == 'true' }}
run: | run: |
# 如果沒有預構建的桌面應用,嘗試本地構建 echo "🔍 驗證桌面應用二進制文件..."
if [ ! -d "src/mcp_feedback_enhanced/desktop_release" ] || [ -z "$(ls -A src/mcp_feedback_enhanced/desktop_release 2>/dev/null)" ]; then
echo "🔧 沒有找到預構建的桌面應用,嘗試本地構建..."
echo "⚠️ 注意:本地構建可能只支援當前平台"
# 安裝 Rust如果還沒安裝 if [ ! -d "src/mcp_feedback_enhanced/desktop_release" ]; then
if ! command -v cargo &> /dev/null; then echo "❌ 桌面應用目錄不存在"
echo "📦 安裝 Rust..." exit 1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y fi
source ~/.cargo/env
# 檢查各平台文件
PLATFORMS=(
"mcp-feedback-enhanced-desktop.exe:Windows"
"mcp-feedback-enhanced-desktop-macos-intel:macOS Intel"
"mcp-feedback-enhanced-desktop-macos-arm64:macOS ARM64"
"mcp-feedback-enhanced-desktop-linux:Linux"
)
VALID_COUNT=0
for platform_info in "${PLATFORMS[@]}"; do
IFS=':' read -r filename description <<< "$platform_info"
filepath="src/mcp_feedback_enhanced/desktop_release/$filename"
if [ -f "$filepath" ]; then
filesize=$(stat -f%z "$filepath" 2>/dev/null || stat -c%s "$filepath" 2>/dev/null || echo "0")
if [ "$filesize" -gt 1000000 ]; then # 至少 1MB
echo "✅ $description: $filename (${filesize} bytes)"
VALID_COUNT=$((VALID_COUNT + 1))
else
echo "⚠️ $description: $filename 文件太小 (${filesize} bytes)"
fi
else
echo "❌ $description: $filename 不存在"
fi fi
done
# 運行本地構建腳本 echo ""
python scripts/build_desktop.py --release echo "📊 驗證結果: $VALID_COUNT/4 個平台有效"
echo "✅ 本地桌面應用構建完成" if [ $VALID_COUNT -eq 0 ]; then
else echo "❌ 沒有有效的桌面應用二進制文件"
echo "✅ 使用預構建的桌面應用" echo "💡 建議:"
echo " 1. 檢查 'Build Desktop Applications' 工作流程是否成功"
echo " 2. 確認指定的 Run ID 是否正確"
echo " 3. 或者設置 include_desktop 為 false"
exit 1
fi fi
- name: Skip desktop applications - name: Skip desktop applications
@ -426,10 +503,37 @@ jobs:
if [ -d "src/mcp_feedback_enhanced/desktop_release" ] && [ -n "$(ls -A src/mcp_feedback_enhanced/desktop_release 2>/dev/null)" ]; then if [ -d "src/mcp_feedback_enhanced/desktop_release" ] && [ -n "$(ls -A src/mcp_feedback_enhanced/desktop_release 2>/dev/null)" ]; then
echo " ✅ 桌面應用已包含在發佈中" echo " ✅ 桌面應用已包含在發佈中"
echo " 📱 支援的平台:" echo " 📱 支援的平台:"
[ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop.exe" ] && echo " - Windows x64"
[ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel" ] && echo " - macOS Intel" # 檢查各平台並顯示文件大小
[ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-arm64" ] && echo " - macOS Apple Silicon" if [ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop.exe" ]; then
[ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux" ] && echo " - Linux x64" size=$(stat -f%z "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop.exe" 2>/dev/null || stat -c%s "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop.exe" 2>/dev/null || echo "unknown")
echo " - ✅ Windows x64 (${size} bytes)"
else
echo " - ❌ Windows x64 (缺失)"
fi
if [ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel" ]; then
size=$(stat -f%z "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel" 2>/dev/null || stat -c%s "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel" 2>/dev/null || echo "unknown")
echo " - ✅ macOS Intel (${size} bytes)"
else
echo " - ❌ macOS Intel (缺失)"
fi
if [ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-arm64" ]; then
size=$(stat -f%z "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-arm64" 2>/dev/null || stat -c%s "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-arm64" 2>/dev/null || echo "unknown")
echo " - ✅ macOS Apple Silicon (${size} bytes)"
else
echo " - ❌ macOS Apple Silicon (缺失)"
fi
if [ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux" ]; then
size=$(stat -f%z "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux" 2>/dev/null || stat -c%s "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux" 2>/dev/null || echo "unknown")
echo " - ✅ Linux x64 (${size} bytes)"
else
echo " - ❌ Linux x64 (缺失)"
fi
echo " 🔗 構建來源: Run ID ${{ steps.check_desktop.outputs.run_id }}"
else else
echo " ⚠️ 桌面應用未包含(可能構建失敗)" echo " ⚠️ 桌面應用未包含(可能構建失敗)"
fi fi

View File

@ -86,15 +86,52 @@ ls -la src/mcp_feedback_enhanced/desktop_app/
- 測試安裝: `uvx mcp-feedback-enhanced@latest` - 測試安裝: `uvx mcp-feedback-enhanced@latest`
- 測試桌面模式: `uvx mcp-feedback-enhanced@latest test --desktop` - 測試桌面模式: `uvx mcp-feedback-enhanced@latest test --desktop`
## 🚀 一鍵構建和發佈
### Build Desktop & Release 工作流程
最簡單的方式是使用 **Build Desktop & Release** 工作流程,它會自動:
1. 構建所有平台的桌面應用
2. 等待構建完成
3. 自動觸發發佈流程
**使用方法**
1. 前往 [Build Desktop & Release](../../actions/workflows/build-and-release.yml)
2. 點擊 "Run workflow"
3. 選擇版本類型或輸入自定義版本
4. 選擇要構建的平台默認all
5. 如果只想構建不發佈,勾選 "只構建桌面應用,不進行發佈"
**優勢**
- ✅ 自動化整個流程
- ✅ 確保桌面應用構建成功後才發佈
- ✅ 統一的狀態報告
- ✅ 減少手動操作錯誤
## 🔧 故障排除 ## 🔧 故障排除
### 桌面應用構建失敗 ### 桌面應用構建失敗
1. **檢查構建日誌** - 查看 GitHub Actions 中的詳細錯誤信息 1. **檢查構建日誌** - 查看 GitHub Actions 中的詳細錯誤信息
2. **平台特定問題**: 2. **平台特定問題**:
- macOS: 可能缺少 Xcode 命令行工具 - **macOS**: 可能缺少 Xcode 命令行工具或系統依賴
- Linux: 可能缺少系統依賴 (GTK, Cairo 等) - **Linux**: 可能缺少系統依賴 (GTK, WebKit, Cairo 等)
- Windows: 通常構建成功 - **Windows**: 通常構建成功,如失敗檢查 MSVC 工具鏈
### 發佈流程問題
1. **桌面應用缺失**:
- 確認 "Build Desktop Applications" 工作流程已成功運行
- 檢查指定的 Run ID 是否正確
- 驗證 Artifacts 是否已正確上傳
2. **版本衝突**:
- 檢查 PyPI 上是否已存在相同版本
- 確認版本號格式正確 (X.Y.Z)
3. **權限問題**:
- 確認 PYPI_API_TOKEN 密鑰已正確設置
- 檢查 GitHub Token 權限
3. **本地測試** - 在對應平台上運行本地構建腳本 3. **本地測試** - 在對應平台上運行本地構建腳本

View File

@ -1,13 +1,13 @@
[project] [project]
name = "mcp-feedback-enhanced" name = "mcp-feedback-enhanced"
version = "2.4.3" version = "2.4.3"
description = "Enhanced MCP server for interactive user feedback and command execution in AI-assisted development, featuring Web UI with intelligent environment detection." description = "Enhanced MCP server for interactive user feedback and command execution in AI-assisted development, featuring dual interface support (Web UI and Desktop Application) with intelligent environment detection and cross-platform compatibility."
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"
authors = [ authors = [
{ name = "Minidoracat", email = "minidora0702@gmail.com" } { name = "Minidoracat", email = "minidora0702@gmail.com" }
] ]
keywords = ["mcp", "ai", "feedback", "web-ui", "interactive", "development"] keywords = ["mcp", "ai", "feedback", "web-ui", "desktop-app", "interactive", "development", "cross-platform", "tauri", "dual-interface"]
classifiers = [ classifiers = [
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Intended Audience :: Developers", "Intended Audience :: Developers",
@ -17,6 +17,13 @@ classifiers = [
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: User Interfaces", "Topic :: Software Development :: User Interfaces",
"Topic :: Desktop Environment",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Operating System :: OS Independent",
"Environment :: Web Environment",
"Environment :: X11 Applications",
"Environment :: Win32 (MS Windows)",
"Environment :: MacOS X",
] ]
dependencies = [ dependencies = [
"fastmcp>=2.0.0", "fastmcp>=2.0.0",

View File

@ -0,0 +1,215 @@
#!/usr/bin/env python3
"""
GitHub Actions 工作流程驗證腳本
此腳本驗證 GitHub Actions 工作流程文件的語法和配置正確性
"""
import sys
from pathlib import Path
import yaml
def validate_yaml_syntax(file_path: Path) -> bool:
"""驗證 YAML 文件語法"""
try:
with open(file_path, encoding="utf-8") as f:
yaml.safe_load(f)
print(f"{file_path.name}: YAML 語法正確")
return True
except yaml.YAMLError as e:
print(f"{file_path.name}: YAML 語法錯誤 - {e}")
return False
except Exception as e:
print(f"{file_path.name}: 讀取文件失敗 - {e}")
return False
def validate_workflow_structure(file_path: Path) -> bool:
"""驗證工作流程結構"""
try:
with open(file_path, encoding="utf-8") as f:
workflow = yaml.safe_load(f)
# 檢查是否成功解析
if workflow is None:
print(f"{file_path.name}: 文件為空或解析失敗")
return False
# 檢查必需的頂級字段
# 注意YAML 會將 'on' 解析為 True所以我們需要特殊處理
required_fields = ["name", "jobs"]
for field in required_fields:
if field not in workflow:
print(f"{file_path.name}: 缺少必需字段 '{field}'")
print(f" 實際字段: {list(workflow.keys())}")
return False
# 檢查 'on' 字段(可能被解析為 True
if "on" not in workflow and True not in workflow:
print(f"{file_path.name}: 缺少觸發條件 'on'")
print(f" 實際字段: {list(workflow.keys())}")
return False
# 檢查 jobs 結構
if not isinstance(workflow["jobs"], dict):
print(f"{file_path.name}: 'jobs' 必須是字典")
return False
if not workflow["jobs"]:
print(f"{file_path.name}: 'jobs' 不能為空")
return False
print(f"{file_path.name}: 工作流程結構正確")
return True
except Exception as e:
print(f"{file_path.name}: 結構驗證失敗 - {e}")
return False
def validate_build_desktop_workflow(file_path: Path) -> bool:
"""驗證桌面構建工作流程的特定配置"""
try:
with open(file_path, encoding="utf-8") as f:
workflow = yaml.safe_load(f)
# 檢查 matrix 配置
build_job = workflow["jobs"].get("build-desktop", {})
strategy = build_job.get("strategy", {})
matrix = strategy.get("matrix", {})
if "include" not in matrix:
print(f"{file_path.name}: 缺少 matrix.include 配置")
return False
# 檢查平台配置
platforms = matrix["include"]
expected_platforms = {"windows", "macos-intel", "macos-arm64", "linux"}
actual_platforms = {item.get("name") for item in platforms}
if not expected_platforms.issubset(actual_platforms):
missing = expected_platforms - actual_platforms
print(f"{file_path.name}: 缺少平台配置: {missing}")
return False
print(f"{file_path.name}: 桌面構建配置正確")
return True
except Exception as e:
print(f"{file_path.name}: 桌面構建驗證失敗 - {e}")
return False
def validate_publish_workflow(file_path: Path) -> bool:
"""驗證發佈工作流程的特定配置"""
try:
with open(file_path, encoding="utf-8") as f:
workflow = yaml.safe_load(f)
# 檢查輸入參數 - 注意 'on' 可能被解析為 True
on_section = workflow.get("on") or workflow.get(True)
if not on_section:
print(f"{file_path.name}: 找不到觸發條件")
return False
workflow_dispatch = on_section.get("workflow_dispatch", {})
inputs = workflow_dispatch.get("inputs", {})
required_inputs = {"version_type", "include_desktop"}
actual_inputs = set(inputs.keys())
if not required_inputs.issubset(actual_inputs):
missing = required_inputs - actual_inputs
print(f"{file_path.name}: 缺少輸入參數: {missing}")
print(f" 實際輸入參數: {actual_inputs}")
return False
# 檢查是否有桌面應用處理步驟
release_job = workflow["jobs"].get("release", {})
steps = release_job.get("steps", [])
has_desktop_steps = any(
"desktop" in step.get("name", "").lower() for step in steps
)
if not has_desktop_steps:
print(f"{file_path.name}: 缺少桌面應用處理步驟")
return False
print(f"{file_path.name}: 發佈工作流程配置正確")
return True
except Exception as e:
print(f"{file_path.name}: 發佈工作流程驗證失敗 - {e}")
return False
def main():
"""主函數"""
print("🔍 驗證 GitHub Actions 工作流程...")
print()
# 獲取工作流程目錄
workflows_dir = Path(__file__).parent.parent / ".github" / "workflows"
if not workflows_dir.exists():
print(f"❌ 工作流程目錄不存在: {workflows_dir}")
sys.exit(1)
# 查找所有工作流程文件
workflow_files = list(workflows_dir.glob("*.yml")) + list(
workflows_dir.glob("*.yaml")
)
if not workflow_files:
print(f"❌ 在 {workflows_dir} 中沒有找到工作流程文件")
sys.exit(1)
print(f"📁 找到 {len(workflow_files)} 個工作流程文件")
print()
# 驗證每個文件
all_valid = True
for workflow_file in sorted(workflow_files):
print(f"🔍 驗證 {workflow_file.name}...")
# 基本語法驗證
if not validate_yaml_syntax(workflow_file):
all_valid = False
continue
# 結構驗證
if not validate_workflow_structure(workflow_file):
all_valid = False
continue
# 特定工作流程驗證
if workflow_file.name == "build-desktop.yml":
if not validate_build_desktop_workflow(workflow_file):
all_valid = False
elif workflow_file.name == "publish.yml":
if not validate_publish_workflow(workflow_file):
all_valid = False
print()
# 總結
if all_valid:
print("🎉 所有工作流程文件驗證通過!")
print()
print("📋 下一步:")
print(" 1. 提交並推送更改到 GitHub")
print(" 2. 測試 'Build Desktop Applications' 工作流程")
print(" 3. 測試 'Build Desktop & Release' 工作流程")
print(" 4. 驗證桌面應用是否正確包含在發佈中")
else:
print("❌ 部分工作流程文件驗證失敗")
print("請修復上述問題後重新運行驗證")
sys.exit(1)
if __name__ == "__main__":
main()