diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index 3afaef9a..853327a9 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -1,4 +1,4 @@ -name: .NET Build & PR Check +name: .NET Build & Package on: push: @@ -8,15 +8,6 @@ on: branches: [ main, beta ] paths-ignore: - '**/*.md' - - 'docs/**' - - 'Images/**' - - 'Manual.md' - - 'README.md' - - 'UpdateLog.md' - - 'CODE_OF_CONDUCT.md' - - 'LICENSE' - - 'privacy.txt' - - 'icc.png' workflow_dispatch: concurrency: @@ -25,191 +16,44 @@ concurrency: permissions: contents: read - pull-requests: write jobs: - find-or-create-pr-comment: - name: Find or Create PR Comment - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - permissions: - pull-requests: write - outputs: - comment_id: ${{ steps.find-comment.outputs.comment_id }} - steps: - - name: Find existing bot comment - id: find-comment - run: | - # 查找包含特定标记的现有评论 - COMMENTS=$(gh api \ - -H "Accept: application/vnd.github.v3+json" \ - "/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \ - --jq '.[] | select(.body | contains("")) | .id' | head -1) - - if [ -n "$COMMENTS" ]; then - echo "📝 找到现有评论 ID: $COMMENTS" - echo "comment_id=$COMMENTS" >> $GITHUB_OUTPUT - else - echo "📝 未找到现有评论,将创建新评论" - echo "comment_id=" >> $GITHUB_OUTPUT - fi - env: - GH_TOKEN: ${{ github.token }} - - pr-preview-comment: - name: PR Preview (Building) - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - needs: find-or-create-pr-comment - permissions: - pull-requests: write - outputs: - comment_id: ${{ steps.create-preview-comment.outputs.comment-id || '' }} - steps: - - name: Prepare Preview Comment - id: prepare-preview - env: - GH_REPO: ${{ github.repository }} - GH_RUN_ID: ${{ github.run_id }} - PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} - IS_READY_FOR_REVIEW: ${{ github.event.action == 'ready_for_review' }} - run: | - # 构建预览评论内容 - { - if [ "$IS_READY_FOR_REVIEW" = "true" ]; then - echo "# 🚀 PR 准备审查 - 构建预览" - echo "" - echo "**状态:** 🟡 正在构建(准备审查状态)..." - else - echo "# 🏗️ PR 构建预览" - echo "" - echo "**状态:** 🟡 正在构建..." - fi - - echo "**分支提交:** \`$PR_HEAD_SHA\`" - echo "**操作:** [查看运行详情](https://github.com/$GH_REPO/actions/runs/$GH_RUN_ID)" - echo "" - - if [ "$IS_READY_FOR_REVIEW" = "true" ]; then - echo "> 📋 此 PR 已标记为 **准备审查**,正在进行构建验证" - fi - - echo "---" - echo "" - echo "" - echo "" - echo "" - echo "" - echo "" - echo "🤖 构建完成后,状态将自动更新" - } > preview_comment.txt - - preview_content=$(cat preview_comment.txt) - echo "preview_body<> $GITHUB_OUTPUT - echo "$preview_content" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Post/Update Preview Comment - id: create-preview-comment - uses: peter-evans/create-or-update-comment@v5 - continue-on-error: true # 即使评论失败也继续执行 - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ needs.find-or-create-pr-comment.outputs.comment_id }} - body: ${{ steps.prepare-preview.outputs.preview_body }} - edit-mode: replace - build-and-package: name: Build & Package runs-on: windows-latest - outputs: - archive_name: ${{ steps.create-archive.outputs.archive_name }} - build_result: ${{ steps.check-exe.outputs.build_success }} - artifact_url: ${{ steps.upload-artifact.outputs.artifact-url }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 1 - - - name: Setup NuGet - uses: NuGet/setup-nuget@v2.0.1 - + - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 - - - name: Cache NuGet global packages - id: cache-nuget - uses: actions/cache@v4 + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 with: - path: | - ~/.nuget/packages - ~\AppData\Local\NuGet\Cache - key: ${{ runner.os }}-nuget-v2-${{ hashFiles('**/*.csproj', '**/packages.config', '**/*.sln', '**/nuget.config') }} - restore-keys: | - ${{ runner.os }}-nuget-v2- - - - - # Removed caching of obj/ folders to avoid cross-version incremental build issues - # NuGet packages will still be cached; always run restore to ensure packages are present - - name: Restore NuGet packages - run: | - Write-Host "📥 正在恢复 NuGet 包(始终运行以确保依赖可用)..." -ForegroundColor Yellow - - # 恢复解决方案级别的包 - nuget restore "Ink Canvas.sln" -Verbosity minimal - - # 恢复项目级别的包(兼容 packages.config) - msbuild -t:restore "Ink Canvas/InkCanvasForClass.csproj" /p:GitFlow="Github Action" /p:RestorePackagesConfig=true /verbosity:minimal - - Write-Host "✅ NuGet 包恢复完成" -ForegroundColor Green - + dotnet-version: '10.x' + cache: true + cache-dependency-path: '**/packages.lock.json' + + - name: Restore Package + run: dotnet restore "Ink Canvas.sln" --locked-mode + - name: Build the Solution - run: | - Write-Host "🔨 正在构建项目..." -ForegroundColor Cyan - - # 如果是 ready_for_review 事件,添加特殊标记 - if ("${{ github.event.action }}" -eq "ready_for_review") { - Write-Host "🚀 PR 准备审查状态构建 - 进行完整验证" -ForegroundColor Magenta - $GITFLOW = "Github Action - Ready For Review" - } else { - $GITFLOW = "Github Action" - } - - # 执行构建 - msbuild /p:platform="AnyCPU" /p:configuration="Debug" /p:GitFlow="$GITFLOW" "Ink Canvas/InkCanvasForClass.csproj" /m /p:UseMultiToolTask=true /p:EnforceProcessCountAcrossBuilds=true /verbosity:minimal - - Write-Host "🏗️ 构建命令执行完成" -ForegroundColor Cyan + run: msbuild /p:platform="AnyCPU" /p:configuration="Debug" /p:GitFlow="$GITFLOW" "Ink Canvas/InkCanvasForClass.csproj" /m /p:UseMultiToolTask=true /p:EnforceProcessCountAcrossBuilds=true /verbosity:minimal - name: Check if exe file is generated id: check-exe run: | - Write-Host "🔍 检查是否生成可执行文件..." -ForegroundColor Cyan - $exePath = "Ink Canvas\bin\Debug\net472\InkCanvasForClass.exe" if (Test-Path $exePath) { - Write-Host "✅ 找到可执行文件: $exePath" -ForegroundColor Green - $fileInfo = Get-Item $exePath - Write-Host " 文件大小: $($fileInfo.Length) 字节" -ForegroundColor Gray - Write-Host " 创建时间: $($fileInfo.CreationTime)" -ForegroundColor Gray echo "build_success=true" >> $env:GITHUB_OUTPUT } else { - Write-Host "❌ 未找到可执行文件: $exePath" -ForegroundColor Red - Write-Host " 检查目录内容:" -ForegroundColor Yellow - if (Test-Path "Ink Canvas\bin\Debug\net472\") { - Get-ChildItem "Ink Canvas\bin\Debug\net472\" -ErrorAction SilentlyContinue | ForEach-Object { - Write-Host " - $($_.Name)" -ForegroundColor Gray - } - } else { - Write-Host " bin\Debug\net472 目录不存在" -ForegroundColor Red - } echo "build_success=false" >> $env:GITHUB_OUTPUT - # 如果是直接触发,则抛出错误 if ("${{ github.event_name }}" -eq "workflow_dispatch") { - Write-Host "🚨 工作流手动触发 - 构建失败,抛出错误!" -ForegroundColor Red -BackgroundColor Black exit 1 } } @@ -221,179 +65,40 @@ jobs: GITHUB_SHA: ${{ github.sha }} GITHUB_RUN_NUMBER: ${{ github.run_number }} run: | - # 使用合并提交的短哈希(因为构建使用的是合并后的代码) $shortSha = $env:GITHUB_SHA.Substring(0, 7) $version = "debug-$shortSha-$env:GITHUB_RUN_NUMBER" - $archiveName = "InkCanvasForClass.CE.$version.zip" - Write-Host "📦 正在创建归档包: $archiveName" -ForegroundColor Cyan - Write-Host " 使用合并提交哈希: $env:GITHUB_SHA" -ForegroundColor Gray - Compress-Archive -Path "Ink Canvas\bin\Debug\net472\*" -DestinationPath $archiveName -Force - echo "archive_name=$archiveName" >> $env:GITHUB_OUTPUT - Write-Host "✅ 已创建归档包: $archiveName" -ForegroundColor Green + echo "archive_name=$version" >> $env:GITHUB_OUTPUT - name: Upload Artifact (if build succeeded) - id: upload-artifact if: steps.check-exe.outputs.build_success == 'true' uses: actions/upload-artifact@v4.5.0 with: - name: app-package - path: "*.zip" + name: InkCanvasForClass.CE.debug + path: "Ink Canvas/bin/Debug/net472/*" - pr-check-comment: - name: PR Check & Comment (Final) - needs: [build-and-package, pr-preview-comment] - if: always() && github.event_name == 'pull_request' - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: Prepare Final Comment Content - id: prepare-final-comment + - name: Create Summary + if: always() + shell: bash run: | - # 从构建作业获取构建结果 - BUILD_SUCCESS="${{ needs.build-and-package.outputs.build_result }}" - ARTIFACT_URL="${{ needs.build-and-package.outputs.artifact_url }}" + echo "# Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY - # 使用 PR 分支的实际提交哈希 - PR_HEAD_SHA="${{ github.event.pull_request.head.sha }}" - - # 确定构建状态 - if [ "$BUILD_SUCCESS" = "true" ]; then - STATUS_ICON="✅" - STATUS_TEXT="构建成功" - COLOR="#00d26a" + if [ "${{ steps.check-exe.outputs.build_success }}" = "true" ]; then + echo "## ✅ Build Successful" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Run:** #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ steps.create-archive.outputs.archive_name }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "[Download Artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "[Nightly.link Download](https://nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}/InkCanvasForClass.CE.debug.zip) \([GhProxy Fastly Mirror](https://cdn.gh-proxy.com/nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}/InkCanvasForClass.CE.debug.zip) / [GhProxy Mirror](https://gh-proxy.com/nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}/InkCanvasForClass.CE.debug.zip)\)" >> $GITHUB_STEP_SUMMARY else - STATUS_ICON="❌" - STATUS_TEXT="构建失败" - COLOR="#f85149" + echo "## ❌ Build Failed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Event:** ${{ github.event_name }} (${{ github.event.action || 'N/A' }})" >> $GITHUB_STEP_SUMMARY + echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Run:** #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Check build logs for details." >> $GITHUB_STEP_SUMMARY fi - - # 检查是否是 ready_for_review 事件 - READY_FOR_REVIEW="${{ github.event.action == 'ready_for_review' }}" - - # 构建最终评论内容 - { - if [ "$READY_FOR_REVIEW" = "true" ]; then - echo "# 🚀 PR 准备审查 - 构建结果" - echo "" - echo "> 📋 此 PR 已标记为 **准备审查**,构建验证完成" - echo "" - else - echo "# 📋 构建结果摘要" - echo "" - fi - - echo "## 本次构建状态" - echo "" - echo "| 项目 | 结果 |" - echo "|------|------|" - echo "| 状态 | $STATUS_ICON **$STATUS_TEXT** |" - echo "| 事件类型 | \`${{ github.event.action }}\` |" - echo "| 分支提交 | \`$PR_HEAD_SHA\` |" - echo "| 工作流 | [运行 #${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) |" - - # 如果有构建产物,显示下载链接 - if [ "$BUILD_SUCCESS" = "true" ]; then - NIGHTLY_LINK="https://hk.gh-proxy.com/https://nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}/app-package.zip" - echo "" - echo "## 构建产物" - if [ -n "$ARTIFACT_URL" ]; then - echo "- 📦 [下载构建产物]($ARTIFACT_URL)" - else - echo "- 📦 [下载构建产物](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" - fi - echo "- 🌙 [直链下载 (nightly.link)]($NIGHTLY_LINK)" - - if [ "$READY_FOR_REVIEW" = "true" ]; then - echo "" - echo "## 🎉 审查建议" - echo "- ✅ 构建验证通过,代码可以正常编译" - echo "- 🔍 请进行代码审查" - echo "- 🧪 建议测试构建产物功能" - fi - else - if [ "$READY_FOR_REVIEW" = "true" ]; then - echo "" - echo "## ⚠️ 审查阻塞" - echo "- ❌ 构建失败,需要修复后才能继续审查" - echo "- 🔧 请检查构建错误并修复" - echo "- 📝 修复后重新标记为准备审查" - fi - fi - - echo "" - echo "---" - echo "" - echo "" - echo "" - echo "" - echo "" - echo "" - echo "🤖 GitHub Actions 自动生成 • 最后更新: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" - } > final_comment.txt - - # 输出多行内容 - final_content=$(cat final_comment.txt) - echo "final_body<> $GITHUB_OUTPUT - echo "$final_content" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - echo "最终评论内容已生成" - - - name: Write Final Comment to GitHub Summary - run: | - echo "# 🚀 最终构建结果 (GitHub Actions Summary)" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "> ⚠️ 注意:由于权限限制,评论可能无法发布到 PR。这里是在 GitHub Actions 中的构建结果:" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - cat final_comment.txt >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "---" >> $GITHUB_STEP_SUMMARY - echo "**工作流信息:**" >> $GITHUB_STEP_SUMMARY - echo "- 事件类型: ${{ github.event_name }} (${{ github.event.action }})" >> $GITHUB_STEP_SUMMARY - echo "- 运行编号: #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY - echo "- 运行 ID: ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY - - - name: Update Final Comment - uses: peter-evans/create-or-update-comment@v5 - continue-on-error: true # 即使评论失败也继续执行 - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ needs.pr-preview-comment.outputs.comment_id }} - body: ${{ steps.prepare-final-comment.outputs.final_body }} - edit-mode: replace - - final-check: - name: Final Check (Manual Trigger) - if: always() && github.event_name == 'workflow_dispatch' - needs: [build-and-package] - runs-on: ubuntu-latest - steps: - - name: Check Build Result - id: check-build - run: | - BUILD_SUCCESS="${{ needs.build-and-package.outputs.build_result }}" - - if [ "$BUILD_SUCCESS" = "true" ]; then - echo "✅ 构建成功 - 工作流完成" - echo "status=success" >> $GITHUB_OUTPUT - else - echo "❌ 构建失败 - 抛出错误" - echo "status=failure" >> $GITHUB_OUTPUT - exit 1 - fi - - - name: Create Summary (if successful) - if: steps.check-build.outputs.status == 'success' - run: | - echo "# 🎉 手动构建完成" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**构建状态:** ✅ 成功" >> $GITHUB_STEP_SUMMARY - echo "**提交:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY - echo "**运行编号:** #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "[📦 下载构建产物](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "**直链下载 (nightly.link):**" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "[🌙 nightly.link 下载链接](https://hk.gh-proxy.com/https://nightly.link/${{ github.repository }}/actions/runs/${{ github.run_id }}/app-package.zip)" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 6ad56075..d47740e7 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -204,78 +204,59 @@ jobs: - name: Checkout code uses: actions/checkout@v6 with: - fetch-depth: 0 - fetch-tags: true - - - name: Setup NuGet - uses: NuGet/setup-nuget@v2.0.1 - + fetch-depth: 1 + - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 + + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10.x' + cache: true + cache-dependency-path: '**/packages.lock.json' + + - name: Restore Package + run: dotnet restore "Ink Canvas.sln" --locked-mode + + - name: Build the Solution (Release) + run: | + msbuild /p:platform="AnyCPU" /p:configuration="Release" /p:GitFlow="Github Action" "Ink Canvas/InkCanvasForClass.csproj" /m /p:UseMultiToolTask=true /p:EnforceProcessCountAcrossBuilds=true /verbosity:minimal + + - name: Check if exe file is generated + id: check-exe + run: | + $exePath = "Ink Canvas/bin/Release/net472/InkCanvasForClass.exe" + + if (Test-Path $exePath) { + echo "build_success=true" >> $env:GITHUB_OUTPUT + } else { + echo "build_success=false" >> $env:GITHUB_OUTPUT + exit 1 + } - name: Install Inno Setup Unofficial Language Files + if: steps.check-exe.outputs.build_success == 'true' run: | # 创建临时目录用于下载文件 New-Item -ItemType Directory -Path "temp_lang" -Force # 下载英语英国版语言文件 - Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/refs/heads/main/Files/Languages/Unofficial/EnglishBritish.isl" -OutFile "temp_lang\EnglishBritish.isl" + Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/refs/heads/main/Files/Languages/Unofficial/EnglishBritish.isl" -OutFile "temp_lang/EnglishBritish.isl" # 下载简体中文版语言文件 - Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/refs/heads/main/Files/Languages/Unofficial/ChineseSimplified.isl" -OutFile "temp_lang\ChineseSimplified.isl" + Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/refs/heads/main/Files/Languages/Unofficial/ChineseSimplified.isl" -OutFile "temp_lang/ChineseSimplified.isl" # 将文件移动到 Inno Setup 的语言目录 - Move-Item -Path "temp_lang\EnglishBritish.isl" -Destination "C:\Program Files (x86)\Inno Setup 6\Languages\EnglishBritish.isl" -Force - Move-Item -Path "temp_lang\ChineseSimplified.isl" -Destination "C:\Program Files (x86)\Inno Setup 6\Languages\ChineseSimplified.isl" -Force + Move-Item -Path "temp_lang/EnglishBritish.isl" -Destination "C:/Program Files (x86)/Inno Setup 6/Languages/EnglishBritish.isl" -Force + Move-Item -Path "temp_lang/ChineseSimplified.isl" -Destination "C:/Program Files (x86)/Inno Setup 6/Languages/ChineseSimplified.isl" -Force # 清理临时目录 Remove-Item -Path "temp_lang" -Recurse -Force - - Write-Host "✅ Inno Setup unofficial language files installed successfully" -ForegroundColor Green - - name: Cache NuGet packages and obj files - id: cache-nuget - uses: actions/cache@v4 - with: - path: | - # NuGet 全局包缓存(已下载的包) - ~/.nuget/packages - # NuGet 缓存目录(包索引) - ~\AppData\Local\NuGet\Cache - # 项目 obj 目录(包含 project.assets.json) - Ink Canvas/obj/ - key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/packages.config', '**/*.sln') }} - restore-keys: | - ${{ runner.os }}-nuget- - - - name: Restore NuGet packages (if cache missed) - if: steps.cache-nuget.outputs.cache-hit != 'true' - run: | - Write-Host "📥 缓存未命中,正在恢复 NuGet 包..." -ForegroundColor Yellow - - # 恢复解决方案级别的包 - nuget restore "Ink Canvas.sln" -Verbosity minimal - - # 恢复项目级别的包 - msbuild -t:restore "Ink Canvas/InkCanvasForClass.csproj" /p:GitFlow="Github Action" /p:RestorePackagesConfig=true /verbosity:minimal - - Write-Host "✅ NuGet 包恢复完成" -ForegroundColor Green - - - name: Display version info - run: | - echo "Building version: ${{ needs.prepare.outputs.version }}" - echo "Tag: ${{ needs.prepare.outputs.tag_name }}" - echo "Release type: ${{ needs.prepare.outputs.is_prerelease == 'true' && 'Pre-release' || 'Release' }}" - - - name: Build the Solution - run: | - Write-Host "🔨 正在构建项目..." -ForegroundColor Cyan - msbuild /p:platform="AnyCPU" /p:configuration="Release" /p:GitFlow="Github Action" "Ink Canvas/InkCanvasForClass.csproj" /m /p:UseMultiToolTask=true /p:EnforceProcessCountAcrossBuilds=true /verbosity:minimal - - Write-Host "🏗️ 构建命令执行完成" -ForegroundColor Cyan - - name: Create Release Archive id: create_archive + if: steps.check-exe.outputs.build_success == 'true' run: | $version = "${{ needs.prepare.outputs.version }}" $archiveName = "InkCanvasForClass.CE.$version.zip" @@ -284,51 +265,50 @@ jobs: New-Item -ItemType Directory -Path "release" -Force # 复制发布文件 - Copy-Item "Ink Canvas\bin\Release\net472\*" "release\" -Recurse -Force + Copy-Item "Ink Canvas/bin/Release/net472/*" "release/" -Recurse -Force # 创建压缩包 - Compress-Archive -Path "release\*" -DestinationPath $archiveName -Force + Compress-Archive -Path "release/*" -DestinationPath $archiveName -Force echo "archive_name=$archiveName" >> $env:GITHUB_OUTPUT - name: Prepare Inno Setup script + if: steps.check-exe.outputs.build_success == 'true' run: | $version = "${{ needs.prepare.outputs.version }}" # 更新 ISS 文件中的版本信息 - $issPath = "build\InkCanvasForClass CE.iss" + $issPath = "build/InkCanvasForClass CE.iss" $issContent = Get-Content -Path $issPath -Raw # 替换版本信息 $issContent = $issContent -replace '#define MyAppVersion ".*"', "#define MyAppVersion `"$version`"" # 替换源文件路径为相对路径(考虑到ISS文件在build目录下,需要返回上级目录) - $issContent = $issContent -replace 'Source: ".*\\{#MyAppExeName}";', 'Source: "..\release\{#MyAppExeName}";' - $issContent = $issContent -replace 'Source: ".*\\InkCanvasForClass.exe.config";', 'Source: "..\release\InkCanvasForClass.exe.config";' + $issContent = $issContent -replace 'Source: ".*\\{#MyAppExeName}";', 'Source: "../release/{#MyAppExeName}";' + $issContent = $issContent -replace 'Source: ".*\\InkCanvasForClass.exe.config";', 'Source: "../release/InkCanvasForClass.exe.config";' # 更新输出目录为当前目录 $issContent = $issContent -replace 'OutputDir=.*', 'OutputDir=.' # 更新默认安装目录 - $issContent = $issContent -replace 'DefaultDirName=.*', 'DefaultDirName={autopf}\{#MyAppName}' + $issContent = $issContent -replace 'DefaultDirName=.*', 'DefaultDirName={autopf}/{#MyAppName}' # 更新许可证文件路径为相对路径(考虑到ISS文件在build目录下,需要返回上级目录) - $issContent = $issContent -replace 'LicenseFile=.*', 'LicenseFile=..\LICENSE' + $issContent = $issContent -replace 'LicenseFile=.*', 'LicenseFile=../LICENSE' # 保存修改后的 ISS 文件 $issContent | Set-Content -Path $issPath -Encoding UTF8 - # 显示修改后的 ISS 文件内容 - Write-Host "Modified ISS file content:" - Write-Host $issContent - - name: Build MSI installer with Inno Setup + if: steps.check-exe.outputs.build_success == 'true' uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 with: - path: build\InkCanvasForClass CE.iss + path: build/InkCanvasForClass CE.iss options: /O. - name: Rename installer file + if: steps.check-exe.outputs.build_success == 'true' run: | $version = "${{ needs.prepare.outputs.version }}" $setupFile = "InkCanvasForClass CE Setup.exe" @@ -336,13 +316,13 @@ jobs: if (Test-Path $setupFile) { Rename-Item -Path $setupFile -NewName $newSetupName - Write-Host "Renamed setup file to: $newSetupName" } else { - Write-Host "Setup file not found: $setupFile" + Write-Error "Setup file not found: $setupFile" } - name: Calculate archive size id: calculate_size + if: steps.check-exe.outputs.build_success == 'true' run: | $version = "${{ needs.prepare.outputs.version }}" $archiveName = "InkCanvasForClass.CE.$version.zip" @@ -352,10 +332,9 @@ jobs: echo "zip_size=$fileSize" >> $env:GITHUB_OUTPUT - echo "Archive size: $fileSize bytes" - - name: Calculate installer size id: calculate_installer_size + if: steps.check-exe.outputs.build_success == 'true' run: | $version = "${{ needs.prepare.outputs.version }}" $installerName = "InkCanvasForClass.CE.$version.Setup.exe" @@ -365,13 +344,12 @@ jobs: $fileSize = (Get-Item $installerName).Length echo "installer_size=$fileSize" >> $env:GITHUB_OUTPUT - - echo "Installer size: $fileSize bytes" } else { - echo "Installer file not found: $installerName" + Write-Error "Installer file not found: $installerName" } - name: Upload Build Artifacts + if: steps.check-exe.outputs.build_success == 'true' uses: actions/upload-artifact@v4 with: name: build-files-${{ needs.prepare.outputs.version }} @@ -379,13 +357,50 @@ jobs: InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe + - name: Create Build Summary + if: always() + shell: bash + run: | + echo "# Release Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ "${{ steps.check-exe.outputs.build_success }}" = "true" ]; then + echo "## ✅ Release Build Successful" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.prepare.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Tag:** \`${{ needs.prepare.outputs.tag_name }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Release Type:** ${{ needs.prepare.outputs.is_prerelease == 'true' && 'Pre-release' || 'Release' }}" >> $GITHUB_STEP_SUMMARY + echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Run:** #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -n "${{ steps.calculate_size.outputs.zip_size }}" ]; then + echo "**Archive Size:** ${{ steps.calculate_size.outputs.zip_size }} bytes" >> $GITHUB_STEP_SUMMARY + fi + + if [ -n "${{ steps.calculate_installer_size.outputs.installer_size }}" ]; then + echo "**Installer Size:** ${{ steps.calculate_installer_size.outputs.installer_size }} bytes" >> $GITHUB_STEP_SUMMARY + fi + + else + echo "## ❌ Release Build Failed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.prepare.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Tag:** \`${{ needs.prepare.outputs.tag_name }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Event:** ${{ github.event_name }} (${{ github.event.action || 'N/A' }})" >> $GITHUB_STEP_SUMMARY + echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Run:** #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Check build logs for details." >> $GITHUB_STEP_SUMMARY + fi + sign: needs: [prepare, build] if: success() - runs-on: ubuntu-latest # 改为 Ubuntu 以使用 Python 签名工具 + runs-on: ubuntu-latest permissions: contents: write - id-token: write # 需要这个权限来验证签名 + id-token: write steps: - name: Download Build Artifacts uses: actions/download-artifact@v4 @@ -505,4 +520,4 @@ jobs: InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe.sigstore.json fail_on_unmatched_files: false env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/Ink Canvas/InkCanvasForClass.csproj b/Ink Canvas/InkCanvasForClass.csproj index 3cb49b7e..be368a2a 100644 --- a/Ink Canvas/InkCanvasForClass.csproj +++ b/Ink Canvas/InkCanvasForClass.csproj @@ -5,6 +5,7 @@ Ink_Canvas InkCanvasForClass net472 + true {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} true false diff --git a/Ink Canvas/packages.lock.json b/Ink Canvas/packages.lock.json new file mode 100644 index 00000000..73c824af --- /dev/null +++ b/Ink Canvas/packages.lock.json @@ -0,0 +1,178 @@ +{ + "version": 1, + "dependencies": { + ".NETFramework,Version=v4.7.2": { + "AForge.Video": { + "type": "Direct", + "requested": "[2.2.5, )", + "resolved": "2.2.5", + "contentHash": "XqzcOXtBUagEPRqg/00oayxlCPmxP4284SdM62mVotsNoD03fs19BrzdMBfhUOOYPyd0B/IXH7tEWnSDmc2gxA==", + "dependencies": { + "AForge": "2.2.5" + } + }, + "AForge.Video.DirectShow": { + "type": "Direct", + "requested": "[2.2.5, )", + "resolved": "2.2.5", + "contentHash": "pEch6felU/RGAbl0A7yjaQjsGxwiRFU9R+qBqR92wQo++XhzPLeQaZHnAPIBYaG7MfoqtjgCDkK4z3Tra4VQ3w==", + "dependencies": { + "AForge.Video": "2.2.5" + } + }, + "Costura.Fody": { + "type": "Direct", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "3Uriu9GJABMivG0wXMJs6NQ7FNE3pylir1gZEBAWDvpii3cnrmxXnOG44MMDuIVOIk/Xhef7WZFsaCNV+py9qA==", + "dependencies": { + "Fody": "6.8.2" + } + }, + "Hardcodet.NotifyIcon.Wpf": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "FFEkdRSidMrbMfQVwhCzq6KtSyR1qQojqtiUrkCyjnOOuMf7W3TNQkzFnBBxYxFe7uLk5mz7M38wFh1qdWyfvg==" + }, + "iNKORE.UI.WPF.Modern": { + "type": "Direct", + "requested": "[0.9.27, )", + "resolved": "0.9.27", + "contentHash": "Mt7KEDjYMdq7hOdPQ0accBN/X6Eb1bkgvyqs+qTGpfx9GKTVhtShbBslWplrqtKvvLsC9/6uU+bTa6rKBcO+kA==", + "dependencies": { + "System.ValueTuple": "4.5.0" + } + }, + "MdXaml": { + "type": "Direct", + "requested": "[1.27.0, )", + "resolved": "1.27.0", + "contentHash": "VWhqhCeKVkJe8vkPmXuGZlRX01WDrTugOLeUvJn18jH/8DrGGVBvtgIlJoELHD2f1DiEWqF3lxxjV55vnzE7Tg==", + "dependencies": { + "AvalonEdit": "6.3.0.90", + "MdXaml.Plugins": "1.27.0" + } + }, + "Microsoft.International.Converters.PinYinConverter": { + "type": "Direct", + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "hEs/VPwGFeVNLf2Wc6k2bMYF71zE6x+lW4MfebRAjkVbAbaa4DbEmdFRfSBymvGLtdsCUvXo2aa/yFKYSCYmEQ==" + }, + "Microsoft.Office.Interop.PowerPoint": { + "type": "Direct", + "requested": "[15.0.4420.1018, )", + "resolved": "15.0.4420.1018", + "contentHash": "3XkJAqbYq93MqqSOPusNE+6Tve5yBkbE92n9W8f+k8Z9AzXeoTMqMYqhZMrzVOp4saHhMMbOD78JkCjvk+qIzw==" + }, + "Microsoft.Toolkit.Uwp.Notifications": { + "type": "Direct", + "requested": "[7.1.3, )", + "resolved": "7.1.3", + "contentHash": "A1dglAzb24gjehmb7DwGd07mfyZ1gacAK7ObE0KwDlRc3mayH2QW7cSOy3TkkyELjLg19OQBuhPOj4SpXET9lg==", + "dependencies": { + "Microsoft.NETFramework.ReferenceAssemblies": "1.0.0", + "Microsoft.Windows.SDK.Contracts": "10.0.19041.1", + "System.ValueTuple": "4.5.0" + } + }, + "MicrosoftOfficeCore": { + "type": "Direct", + "requested": "[15.0.0, )", + "resolved": "15.0.0", + "contentHash": "/KgYw8uvv0Ut8FPvyEa1XJ/TrLSRgvTv3JgC2IT0/8NwoICzbEJWfmfwsE6Dwi8WH0jVkTEO7zRvGvaKqUOhqQ==" + }, + "Newtonsoft.Json": { + "type": "Direct", + "requested": "[13.0.3, )", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "NHotkey.Wpf": { + "type": "Direct", + "requested": "[3.0.0, )", + "resolved": "3.0.0", + "contentHash": "BIUKlhTG5KtFf9OQzWvkmVmktt5/FFj6AOEgag8Uf0R2YdZt5ajUzs3sVskcJcT2TztWlEHKQr1jFj3KQ0D9Nw==", + "dependencies": { + "NHotkey": "3.0.0" + } + }, + "OSVersionExt": { + "type": "Direct", + "requested": "[3.0.0, )", + "resolved": "3.0.0", + "contentHash": "G+3FGoEFhjSMx24UInvqRVb7dQ7K0coC8E+EiZWhnQGnDe8IJa14AZ0IDqz5YkwUFHOAcVUnoMWDqLH2RPR0wA==" + }, + "AForge": { + "type": "Transitive", + "resolved": "2.2.5", + "contentHash": "clkumhM9DggqIzEXAHgVLeWO4arG5YfoPr7J4jfjJx35AoeEIJSSm49J25bwp/9mXQYLwi7y1Wunc8qgYJsGxg==" + }, + "AvalonEdit": { + "type": "Transitive", + "resolved": "6.3.0.90", + "contentHash": "WVTb5MxwGqKdeasd3nG5udlV4t6OpvkFanziwI133K0/QJ5FvZmfzRQgpAjGTJhQfIA8GP7AzKQ3sTY9JOFk8Q==" + }, + "Fody": { + "type": "Transitive", + "resolved": "6.8.2", + "contentHash": "sjGHrtGS1+kcrv99WXCvujOFBTQp4zCH3ZC9wo2LAtVaJkuLpHghQx3y4k1Q8ZKuDAbEw+HE6ZjPUJQK3ejepQ==" + }, + "MdXaml.Plugins": { + "type": "Transitive", + "resolved": "1.27.0", + "contentHash": "We7LtBdoukRg9mqTfa1f5n8z/GQPMKBRj3URk9DiMuqzIHkW1lTgK5njVPSScxsRt4YzW22423tSnLWNm2MJKg==" + }, + "Microsoft.NETFramework.ReferenceAssemblies": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "7D2TMufjGiowmt0E941kVoTIS+GTNzaPopuzM1/1LSaJAdJdBrVP0SkZW7AgDd0a2U1DjsIeaKG1wxGVBNLDMw==", + "dependencies": { + "Microsoft.NETFramework.ReferenceAssemblies.net472": "1.0.0" + } + }, + "Microsoft.NETFramework.ReferenceAssemblies.net472": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "VI0f22cH/xOlXLUVY7t6vr2Gi7cg0vzwpspNGz5isRusyspZblF7jJMw49E8mF1m071JyeVmZVkIK9c5kbiyFA==" + }, + "Microsoft.Windows.SDK.Contracts": { + "type": "Transitive", + "resolved": "10.0.19041.1", + "contentHash": "sgDwuoyubbLFNJR/BINbvfSNRiglF91D+Q0uEAkU4ZTO5Hgbnu8+gA4TCc65S56e1kK7gvR1+H4kphkDTr+9bw==", + "dependencies": { + "System.Runtime.WindowsRuntime": "4.6.0", + "System.Runtime.WindowsRuntime.UI.Xaml": "4.6.0" + } + }, + "NHotkey": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "IEghs0QqWsQYH0uUmvIl0Ye6RaebWRh38eB6ToOkDnQucTYRGFOgtig0gSxlwCszTilYFz3n1ZuY762x+kDR3A==" + }, + "System.Runtime.WindowsRuntime": { + "type": "Transitive", + "resolved": "4.6.0", + "contentHash": "IWrs1TmbxP65ZZjIglNyvDkFNoV5q2Pofg5WO7I8RKQOpLdFprQSh3xesOoClBqR4JHr4nEB1Xk1MqLPW1jPuQ==" + }, + "System.Runtime.WindowsRuntime.UI.Xaml": { + "type": "Transitive", + "resolved": "4.6.0", + "contentHash": "r4tNw5v5kqRJ9HikWpcyNf3suGw7DjX93svj9iBjtdeLqL8jt9Z+7f+s4wrKZJr84u8IMsrIjt8K6jYvkRqMSg==", + "dependencies": { + "System.Runtime.WindowsRuntime": "4.6.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + } + }, + ".NETFramework,Version=v4.7.2/win": {}, + ".NETFramework,Version=v4.7.2/win-arm64": {}, + ".NETFramework,Version=v4.7.2/win-x64": {}, + ".NETFramework,Version=v4.7.2/win-x86": {} + } +} \ No newline at end of file diff --git a/build/cliff.toml b/build/cliff.toml index 2eee46bb..b11c9278 100644 --- a/build/cliff.toml +++ b/build/cliff.toml @@ -13,12 +13,23 @@ body = """ {% endif %}\ {% for group, commits in commits | group_by(attribute="group") %} ### {{ group | striptags | trim | upper_first }} - {% for commit in commits %} - - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ - {% if commit.breaking %}[**breaking**] {% endif %}\ - {{ commit.message | upper_first }} ({{commit.id}} by {{commit.author.name}})\ + {% for commit in commits | unique(attribute="message") %} + * {{ commit.message | split(pat="\n") | first | trim }}\ + {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif %}\ + {% if commit.remote.pr_number %} in #{{ commit.remote.pr_number }}{%- endif %} {% endfor %} {% endfor %} + +- 该版本有 {{ statistics.commit_count }} 次提交 +- 在提交中检测到 {{ statistics.links | length }} 个关联议题 +{%- if statistics.links | length > 0 %} + {%- for link in statistics.links %} + {{ " " }}- [{{ link.text }}]({{ link.href }}) (referenced {{ link.count }} time(s)) + {%- endfor %} +{%- endif %} + +感谢 {% for contributor in github.contributors %} @{{ contributor.username }} {%- endfor -%} 为本版本做出了贡献 + """ # Remove leading and trailing whitespaces from the changelog's body. trim = true