mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 02:22:26 +08:00
🎨 調整發布流程
This commit is contained in:
parent
ff5a6c317d
commit
94aa415648
148
.github/workflows/build-and-release.yml
vendored
Normal file
148
.github/workflows/build-and-release.yml
vendored
Normal 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
|
102
.github/workflows/build-desktop.yml
vendored
102
.github/workflows/build-desktop.yml
vendored
@ -97,18 +97,47 @@ jobs:
|
||||
${{ runner.os }}-cargo-${{ matrix.target }}-
|
||||
${{ 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 }}
|
||||
run: |
|
||||
cd src-tauri
|
||||
echo "🔨 開始構建 ${{ matrix.name }} (${{ matrix.target }})..."
|
||||
cargo build --release --target ${{ matrix.target }} --bin mcp-feedback-enhanced-desktop
|
||||
echo "✅ 構建完成"
|
||||
|
||||
- name: Verify build output
|
||||
run: |
|
||||
echo "🔍 檢查構建產物..."
|
||||
if [ "${{ matrix.os }}" = "windows-latest" ]; then
|
||||
ls -la "src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}" || echo "❌ Windows 二進制文件不存在"
|
||||
BINARY_PATH="src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}"
|
||||
|
||||
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
|
||||
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
|
||||
shell: bash
|
||||
|
||||
@ -120,14 +149,38 @@ jobs:
|
||||
path: src-tauri/target/${{ matrix.target }}/release/${{ matrix.binary }}
|
||||
retention-days: 30 # 保留 30 天
|
||||
compression-level: 6
|
||||
if-no-files-found: error # 如果沒有找到文件則失敗
|
||||
|
||||
# 構建摘要
|
||||
# 構建摘要和驗證
|
||||
build-summary:
|
||||
needs: build-desktop
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
outputs:
|
||||
build_success: ${{ steps.check_results.outputs.success }}
|
||||
platforms_built: ${{ steps.check_results.outputs.platforms }}
|
||||
|
||||
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
|
||||
run: |
|
||||
echo "## 🖥️ 桌面應用構建摘要" >> $GITHUB_STEP_SUMMARY
|
||||
@ -137,16 +190,43 @@ jobs:
|
||||
|
||||
# 檢查各平台構建狀態
|
||||
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
|
||||
echo "❌ 部分平台構建失敗" >> $GITHUB_STEP_SUMMARY
|
||||
echo "❌ **部分平台構建失敗**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "請檢查各平台的構建日誌以了解失敗原因。" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "⚠️ 構建狀態: ${{ needs.build-desktop.result }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "⚠️ **構建狀態**: ${{ needs.build-desktop.result }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 下一步" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### 📦 產物信息" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 構建產物已上傳到 GitHub Artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 可以在發佈流程中使用這些二進制文件" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- 如需重新構建,請手動觸發此工作流程" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **保留期限**: 30 天" >> $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
|
||||
|
||||
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
|
||||
|
218
.github/workflows/publish.yml
vendored
218
.github/workflows/publish.yml
vendored
@ -287,93 +287,170 @@ jobs:
|
||||
- Auto-generated release from workflow"
|
||||
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' }}
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build-desktop.yml
|
||||
run_id: ${{ github.event.inputs.desktop_build_run_id }}
|
||||
run_id: ${{ steps.check_desktop.outputs.run_id }}
|
||||
path: desktop-artifacts
|
||||
if_no_artifact_found: warn
|
||||
if_no_artifact_found: error
|
||||
|
||||
- name: Prepare multi-platform desktop binaries
|
||||
if: ${{ github.event.inputs.include_desktop == 'true' }}
|
||||
run: |
|
||||
# 檢查是否有桌面應用構建產物
|
||||
if [ ! -d "desktop-artifacts" ] || [ -z "$(ls -A desktop-artifacts 2>/dev/null)" ]; then
|
||||
echo "⚠️ 警告:沒有找到桌面應用構建產物"
|
||||
echo "💡 提示:請先運行 'Build Desktop Applications' 工作流程"
|
||||
echo "🔧 或者設置 include_desktop 為 false 來跳過桌面應用"
|
||||
echo "📦 準備多平台桌面應用二進制文件..."
|
||||
|
||||
# 檢查下載的產物
|
||||
echo "🔍 檢查下載的桌面應用產物..."
|
||||
if [ ! -d "desktop-artifacts" ]; then
|
||||
echo "❌ 桌面產物目錄不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "📁 產物目錄內容:"
|
||||
find desktop-artifacts -type f -name "*" | head -20
|
||||
|
||||
# 創建桌面應用目錄
|
||||
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
|
||||
cp desktop-artifacts/desktop-windows/mcp-feedback-enhanced-desktop.exe src/mcp_feedback_enhanced/desktop_release/
|
||||
echo "✅ Windows 二進制文件已複製"
|
||||
else
|
||||
echo "⚠️ Windows 二進制文件不存在"
|
||||
fi
|
||||
# 複製並重命名二進制文件
|
||||
COPIED_COUNT=0
|
||||
TOTAL_PLATFORMS=4
|
||||
|
||||
if [ -f "desktop-artifacts/desktop-macos-intel/mcp-feedback-enhanced-desktop" ]; then
|
||||
cp desktop-artifacts/desktop-macos-intel/mcp-feedback-enhanced-desktop src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-macos-intel
|
||||
echo "✅ macOS Intel 二進制文件已複製"
|
||||
else
|
||||
echo "⚠️ macOS Intel 二進制文件不存在"
|
||||
fi
|
||||
for platform_dir in desktop-windows desktop-macos-intel desktop-macos-arm64 desktop-linux; do
|
||||
echo "🔍 處理平台: $platform_dir"
|
||||
|
||||
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
|
||||
echo "✅ macOS ARM64 二進制文件已複製"
|
||||
else
|
||||
echo "⚠️ macOS ARM64 二進制文件不存在"
|
||||
fi
|
||||
# 查找該平台的二進制文件
|
||||
BINARY_FILE=""
|
||||
if [ -d "desktop-artifacts/$platform_dir" ]; then
|
||||
# 查找二進制文件(可能是 .exe 或無擴展名)
|
||||
BINARY_FILE=$(find "desktop-artifacts/$platform_dir" -name "mcp-feedback-enhanced-desktop*" -type f | head -1)
|
||||
fi
|
||||
|
||||
if [ -f "desktop-artifacts/desktop-linux/mcp-feedback-enhanced-desktop" ]; then
|
||||
cp desktop-artifacts/desktop-linux/mcp-feedback-enhanced-desktop src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux
|
||||
echo "✅ Linux 二進制文件已複製"
|
||||
else
|
||||
echo "⚠️ Linux 二進制文件不存在"
|
||||
fi
|
||||
if [ -n "$BINARY_FILE" ] && [ -f "$BINARY_FILE" ]; then
|
||||
TARGET_NAME="${PLATFORM_MAP[$platform_dir]}"
|
||||
cp "$BINARY_FILE" "src/mcp_feedback_enhanced/desktop_release/$TARGET_NAME"
|
||||
|
||||
# 設置執行權限
|
||||
chmod +x src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-* 2>/dev/null || true
|
||||
# 設置執行權限(非 Windows)
|
||||
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
|
||||
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 "📦 最終的桌面應用二進制文件:"
|
||||
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' }}
|
||||
run: |
|
||||
# 如果沒有預構建的桌面應用,嘗試本地構建
|
||||
if [ ! -d "src/mcp_feedback_enhanced/desktop_release" ] || [ -z "$(ls -A src/mcp_feedback_enhanced/desktop_release 2>/dev/null)" ]; then
|
||||
echo "🔧 沒有找到預構建的桌面應用,嘗試本地構建..."
|
||||
echo "⚠️ 注意:本地構建可能只支援當前平台"
|
||||
echo "🔍 驗證桌面應用二進制文件..."
|
||||
|
||||
# 安裝 Rust(如果還沒安裝)
|
||||
if ! command -v cargo &> /dev/null; then
|
||||
echo "📦 安裝 Rust..."
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
source ~/.cargo/env
|
||||
if [ ! -d "src/mcp_feedback_enhanced/desktop_release" ]; then
|
||||
echo "❌ 桌面應用目錄不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 檢查各平台文件
|
||||
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
|
||||
done
|
||||
|
||||
# 運行本地構建腳本
|
||||
python scripts/build_desktop.py --release
|
||||
echo ""
|
||||
echo "📊 驗證結果: $VALID_COUNT/4 個平台有效"
|
||||
|
||||
echo "✅ 本地桌面應用構建完成"
|
||||
else
|
||||
echo "✅ 使用預構建的桌面應用"
|
||||
if [ $VALID_COUNT -eq 0 ]; then
|
||||
echo "❌ 沒有有效的桌面應用二進制文件"
|
||||
echo "💡 建議:"
|
||||
echo " 1. 檢查 'Build Desktop Applications' 工作流程是否成功"
|
||||
echo " 2. 確認指定的 Run ID 是否正確"
|
||||
echo " 3. 或者設置 include_desktop 為 false"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- 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
|
||||
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"
|
||||
[ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop-linux" ] && echo " - Linux x64"
|
||||
|
||||
# 檢查各平台並顯示文件大小
|
||||
if [ -f "src/mcp_feedback_enhanced/desktop_release/mcp-feedback-enhanced-desktop.exe" ]; then
|
||||
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
|
||||
echo " ⚠️ 桌面應用未包含(可能構建失敗)"
|
||||
fi
|
||||
|
@ -86,15 +86,52 @@ ls -la src/mcp_feedback_enhanced/desktop_app/
|
||||
- 測試安裝: `uvx mcp-feedback-enhanced@latest`
|
||||
- 測試桌面模式: `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 中的詳細錯誤信息
|
||||
2. **平台特定問題**:
|
||||
- macOS: 可能缺少 Xcode 命令行工具
|
||||
- Linux: 可能缺少系統依賴 (GTK, Cairo 等)
|
||||
- Windows: 通常構建成功
|
||||
- **macOS**: 可能缺少 Xcode 命令行工具或系統依賴
|
||||
- **Linux**: 可能缺少系統依賴 (GTK, WebKit, Cairo 等)
|
||||
- **Windows**: 通常構建成功,如失敗檢查 MSVC 工具鏈
|
||||
|
||||
### 發佈流程問題
|
||||
|
||||
1. **桌面應用缺失**:
|
||||
- 確認 "Build Desktop Applications" 工作流程已成功運行
|
||||
- 檢查指定的 Run ID 是否正確
|
||||
- 驗證 Artifacts 是否已正確上傳
|
||||
|
||||
2. **版本衝突**:
|
||||
- 檢查 PyPI 上是否已存在相同版本
|
||||
- 確認版本號格式正確 (X.Y.Z)
|
||||
|
||||
3. **權限問題**:
|
||||
- 確認 PYPI_API_TOKEN 密鑰已正確設置
|
||||
- 檢查 GitHub Token 權限
|
||||
|
||||
3. **本地測試** - 在對應平台上運行本地構建腳本
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
[project]
|
||||
name = "mcp-feedback-enhanced"
|
||||
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"
|
||||
requires-python = ">=3.11"
|
||||
authors = [
|
||||
{ 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 = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
@ -17,6 +17,13 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"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 = [
|
||||
"fastmcp>=2.0.0",
|
||||
|
215
scripts/validate_workflows.py
Normal file
215
scripts/validate_workflows.py
Normal 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()
|
Loading…
x
Reference in New Issue
Block a user