From 59bfa8d5649d7c783c8ae7f8770b4edb79aa0e6d Mon Sep 17 00:00:00 2001 From: lincube Date: Wed, 4 Mar 2026 17:02:12 +0800 Subject: [PATCH] 0.3.7 --- .github/PACKAGING_FIXES.md | 184 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 144 ++++++++++++++++++-------- 2 files changed, 287 insertions(+), 41 deletions(-) create mode 100644 .github/PACKAGING_FIXES.md diff --git a/.github/PACKAGING_FIXES.md b/.github/PACKAGING_FIXES.md new file mode 100644 index 0000000..3e9a415 --- /dev/null +++ b/.github/PACKAGING_FIXES.md @@ -0,0 +1,184 @@ +# CI/CD 打包工作流修复报告 + +修复日期:2026年3月4日 + +## 问题概述 + +GitHub Actions `release.yml` 工作流中的打包步骤存在多个bug,导致无法正常生成发布包。 + +## 🔴 已发现并修复的问题 + +### 1. **macOS Info.plist 变量展开问题** (关键) +📍 位置:`release.yml` - macOS Package as DMG 步骤 + +**问题**: +```bash +cat > "${app_name}.app/Contents/Info.plist" << 'EOF' + ... + ${version} # 此处无法展开变量 + ... +EOF +``` + +使用了 `'EOF'`(带引号),导致heredoc中的shell变量无法展开。 + +**修复**: +```bash +cat > "${app_name}.app/Contents/Info.plist" << EOF + ... + $version # 现在可以正确展开 + ... +EOF +``` + +### 2. **Linux DEB 控制文件缩进错误** +📍 位置:`release.yml` - Linux Package as DEB 步骤 + +**问题**: +```bash +cat > "build-deb/DEBIAN/control" << EOF + Package: $package_name # 错误的缩进导致无效的DEB control文件 + Version: $package_version +``` + +DEB control文件不允许在字段前有缩进。 + +**修复**: +```bash +cat > "build-deb/DEBIAN/control" << EOF +Package: $package_name # 移除所有缩进 +Version: $package_version +``` + +### 3. **Windows 打包路径和错误处理缺失** +📍 位置:`release.yml` - Windows Package 步骤 + +**问题**: +- 使用 `Copy-Item -Path "$source/*"` 可能无法正确处理通配符 +- 缺少目录存在性检查 +- 缺少打包内容验证 + +**修复**: +```powershell +# 1. 添加源目录验证 +if (-not (Test-Path -Path $source)) { + Write-Error "Source directory not found: $source" + exit 1 +} + +# 2. 改进复制(使用反斜杠) +Copy-Item -Path "$source\*" -Destination $package -Recurse -Force + +# 3. 验证打包内容 +$itemCount = @(Get-ChildItem $package -Recurse).Count +if ($itemCount -eq 0) { + Write-Error "Package directory is empty after copy" + exit 1 +} +``` + +### 4. **Linux DEB 打包缺少错误检查** +📍 位置:`release.yml` - Linux Package as DEB 步骤 + +**问题**: +- 未验证源目录是否存在 +- 未验证复制是否成功 +- `dpkg-deb` 命令缺少错误检查 + +**修复**: +```bash +# 1. 验证源目录 +if [ ! -d "$source" ]; then + echo "Error: Source directory not found: $source" + exit 1 +fi + +# 2. 验证复制成功 +item_count=$(find build-deb/usr/local/bin -type f 2>/dev/null | wc -l) +if [ "$item_count" -eq 0 ]; then + echo "Error: DEB package is empty after copy" + exit 1 +fi + +# 3. 验证dpkg-deb成功 +if dpkg-deb --build "build-deb" "${package_name}_${package_version}_${arch}.deb"; then + echo "Successfully created..." +else + echo "Error: Failed to build DEB package" + exit 1 +fi +``` + +### 5. **macOS DMG 打包缺少错误检查** +📍 位置:`release.yml` - macOS Package as DMG 步骤 + +**问题**: +- 未验证source目录是否存在 +- 未验证app bundle复制是否成功 +- `hdiutil` 命令缺少错误检查 + +**修复**: +```bash +# 1. 验证源目录 +if [ ! -d "$source" ]; then + echo "Error: Source directory not found: $source" + exit 1 +fi + +# 2. 验证复制成功 +item_count=$(find "${app_name}.app/Contents/MacOS" -type f | wc -l) +if [ "$item_count" -eq 0 ]; then + echo "Error: App bundle is empty after copy" + exit 1 +fi + +# 3. 验证hdiutil成功 +if hdiutil create -volname "${app_name}" -srcfolder dmg-temp -ov -format UDZO "${package_name}.dmg" 2>&1; then + echo "Successfully created: ${package_name}.dmg" +else + echo "Error: Failed to create DMG" + exit 1 +fi +``` + +## 📝 修改文件 + +- `.github/workflows/release.yml` + - Windows Package 步骤:完整重写,添加验证和错误处理 + - Linux Package as DEB 步骤:修复缩进,添加验证和错误处理 + - macOS Package as DMG 步骤:修复heredoc变量展开,添加验证和错误处理 + +## ✅ 测试建议 + +1. **本地测试** (可选): + ```bash + # 手动运行打包步骤以测试逻辑 + ``` + +2. **GitHub Actions 测试**: + - 推送一个测试标签:`git tag v1.0.0-test && git push origin v1.0.0-test` + - 查看Actions日志验证打包步骤是否成功 + - 检查发布页面是否包含所有平台的包 + +3. **包验证**: + - Windows: 检查 `.zip` 文件是否包含可执行文件 + - Linux: 检查 `.deb` 文件是否可安装 `dpkg` 验证 + - macOS: 检查 `.dmg` 文件是否包含应用和有效的Info.plist + +## 🔧 后续改进建议 + +1. **添加签名步骤**: + - Windows: Code签名 (需证书) + - macOS: 代码签名和公证 (需开发者账户) + +2. **添加完整性检查**: + - SHA256 校验和生成和验证 + - 添加版本信息验证 + +3. **优化包大小**: + - 使用 `--self-contained false` 依赖系统运行时 + - 剥离调试符号 (已使用 `-p:DebugType=none`) + +4. **改进发布说明**: + - 添加更详细的更新日志 + - 链接到提交日志和问题跟踪 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 13c2097..c8f16ca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -97,14 +97,35 @@ jobs: run: | $version = "${{ needs.prepare.outputs.version }}" $arch = "${{ matrix.arch }}" - $source = "publish/windows-$arch" + $source = "publish\windows-$arch" $package = "LanMountainDesktop-$version-win-$arch" - New-Item -ItemType Directory -Path "$package" -Force | Out-Null - Copy-Item -Path "$source/*" -Destination "$package" -Recurse -Force - Compress-Archive -Path "$package" -DestinationPath "$package.zip" -Force + # Verify source directory exists + if (-not (Test-Path -Path $source)) { + Write-Error "Source directory not found: $source" + Write-Host "Available directories:" + Get-ChildItem -Path "publish" -Directory -ErrorAction SilentlyContinue | Select-Object Name + exit 1 + } - Write-Host "Created: $package.zip" + # Create package directory and copy files + New-Item -ItemType Directory -Path $package -Force | Out-Null + Copy-Item -Path "$source\*" -Destination $package -Recurse -Force + + # Verify package has content + $itemCount = @(Get-ChildItem $package -Recurse -ErrorAction SilentlyContinue).Count + Write-Host "Package contains $itemCount items" + + if ($itemCount -eq 0) { + Write-Error "Package directory is empty after copy" + exit 1 + } + + # Create archive + Compress-Archive -Path $package -DestinationPath "$package.zip" -Force -ErrorAction Stop + + Write-Host "Successfully created: $package.zip" + Write-Host "Archive size: $($(Get-Item "$package.zip").Length / 1MB) MB" shell: pwsh - name: Upload @@ -171,6 +192,13 @@ jobs: package_version="${version}" arch="amd64" + # Verify source directory exists + if [ ! -d "$source" ]; then + echo "Error: Source directory not found: $source" + ls -la publish/ || echo "publish directory not found" + exit 1 + fi + # Create DEB package structure mkdir -p "build-deb/DEBIAN" mkdir -p "build-deb/usr/local/bin" @@ -180,23 +208,36 @@ jobs: # Copy application files cp -r "$source"/* "build-deb/usr/local/bin/" - # Create control file + # Verify copy was successful + item_count=$(find build-deb/usr/local/bin -type f 2>/dev/null | wc -l) + echo "DEB package contains $item_count files" + + if [ "$item_count" -eq 0 ]; then + echo "Error: DEB package is empty after copy" + exit 1 + fi + + # Create control file (NOTE: No leading spaces in control file) cat > "build-deb/DEBIAN/control" << EOF - Package: $package_name - Version: $package_version - Architecture: $arch - Maintainer: LanMountain Team - Description: LanMountain Desktop Application - A desktop application for LanMountain. - EOF +Package: $package_name +Version: $package_version +Architecture: $arch +Maintainer: LanMountain Team +Description: LanMountain Desktop Application + A desktop application for LanMountain. +EOF # Set proper permissions - chmod 755 "build-deb/usr/local/bin/LanMountainDesktop" + chmod 755 "build-deb/usr/local/bin/LanMountainDesktop" || chmod 755 "build-deb/usr/local/bin"/* # Create DEB file - dpkg-deb --build "build-deb" "${package_name}_${package_version}_${arch}.deb" - - echo "Created: ${package_name}_${package_version}_${arch}.deb" + if dpkg-deb --build "build-deb" "${package_name}_${package_version}_${arch}.deb"; then + echo "Successfully created: ${package_name}_${package_version}_${arch}.deb" + ls -lh "${package_name}_${package_version}_${arch}.deb" + else + echo "Error: Failed to build DEB package" + exit 1 + fi - name: Upload uses: actions/upload-artifact@v4 @@ -256,6 +297,13 @@ jobs: app_name="LanMountainDesktop" package_name="${app_name}-${version}-macos-${arch}" + # Verify source directory exists + if [ ! -d "$source" ]; then + echo "Error: Source directory not found: $source" + ls -la publish/ || echo "publish directory not found" + exit 1 + fi + # Create app bundle structure mkdir -p "${app_name}.app/Contents/MacOS" mkdir -p "${app_name}.app/Contents/Resources" @@ -263,37 +311,51 @@ jobs: # Copy application files cp -r "$source"/* "${app_name}.app/Contents/MacOS/" - # Create minimal Info.plist - cat > "${app_name}.app/Contents/Info.plist" << 'EOF' - - - - - CFBundleExecutable - LanMountainDesktop - CFBundleName - LanMountain Desktop - CFBundleVersion - ${version} - CFBundleShortVersionString - ${version} - CFBundleIdentifier - com.lanmountain.desktop - CFBundlePackageType - APPL - - - EOF + # Verify copy was successful + item_count=$(find "${app_name}.app/Contents/MacOS" -type f | wc -l) + echo "App bundle contains $item_count files" + + if [ "$item_count" -eq 0 ]; then + echo "Error: App bundle is empty after copy" + exit 1 + fi + + # Create Info.plist - NOTE: Using unquoted EOF to allow variable expansion + cat > "${app_name}.app/Contents/Info.plist" << EOF + + + + + CFBundleExecutable + LanMountainDesktop + CFBundleName + LanMountain Desktop + CFBundleVersion + $version + CFBundleShortVersionString + $version + CFBundleIdentifier + com.lanmountain.desktop + CFBundlePackageType + APPL + + +EOF # Create DMG mkdir -p dmg-temp cp -r "${app_name}.app" dmg-temp/ - hdiutil create -volname "${app_name}" -srcfolder dmg-temp -ov -format UDZO "${package_name}.dmg" + + if hdiutil create -volname "${app_name}" -srcfolder dmg-temp -ov -format UDZO "${package_name}.dmg" 2>&1; then + echo "Successfully created: ${package_name}.dmg" + ls -lh "${package_name}.dmg" + else + echo "Error: Failed to create DMG" + exit 1 + fi # Cleanup rm -rf dmg-temp "${app_name}.app" - - echo "Created: ${package_name}.dmg" - name: Upload uses: actions/upload-artifact@v4