From ad8d8f94ffc014d3d9db7d215c68bd0e7915e575 Mon Sep 17 00:00:00 2001 From: doudou0720 <98651603+doudou0720@users.noreply.github.com> Date: Sat, 20 Dec 2025 23:46:37 +0800 Subject: [PATCH] Merge pull request #320 from doudou0720/beta-image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit !refactor(CI/CD):构建工作流重构 --- .github/workflows/dotnet-desktop.yml | 410 +++++++++++++- .github/workflows/prerelease.yml | 816 ++++++++++++++++++--------- build/InkCanvasForClass CE.iss | 63 +++ build/cliff.toml | 95 ++++ 4 files changed, 1083 insertions(+), 301 deletions(-) create mode 100644 build/InkCanvasForClass CE.iss create mode 100644 build/cliff.toml diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index e85a7288..98a8c6c5 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -1,35 +1,399 @@ -name: .NET Build +name: .NET Build & PR Check on: push: - branches: [ main,beta ] + branches: [ main, beta ] pull_request: + types: [opened, synchronize, reopened, ready_for_review] branches: [ main ] + paths-ignore: + - '**/*.md' + - 'docs/**' + - 'Images/**' + - 'Manual.md' + - 'README.md' + - 'UpdateLog.md' + - 'CODE_OF_CONDUCT.md' + - 'LICENSE' + - 'privacy.txt' + - 'icc.png' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-${{ github.head_ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: write jobs: - - build: - runs-on: windows-latest - + 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: - - uses: actions/checkout@v4.2.2 + - 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 }} - - name: Setup MSbuild - uses: microsoft/setup-msbuild@v2 - - - name: Setup NuGet - uses: NuGet/setup-nuget@v2.0.1 + 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: Restore NuGet Packages - run: nuget restore "Ink Canvas.sln" + - name: Post/Update Preview Comment + id: create-preview-comment + uses: peter-evans/create-or-update-comment@v4 + 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 - - name: Build the Solution - run: | - msbuild -t:restore /p:GitFlow="Github Action" - msbuild /p:platform="AnyCPU" /p:configuration="Debug" /p:GitFlow="Github Action" "Ink Canvas/InkCanvasForClass.csproj" + 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: Upload to artifact - uses: actions/upload-artifact@v4.5.0 - with: - name: InkCanvasForClass - path: "Ink Canvas/bin/Debug/net472" + - 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 + with: + path: | + # NuGet 全局包缓存(已下载的包) + ~/.nuget/packages + # NuGet 缓存目录(包索引) + ~\AppData\Local\NuGet\Cache + key: ${{ runner.os }}-nuget-v2-${{ hashFiles('**/*.csproj', '**/packages.config', '**/*.sln', '**/nuget.config') }} + restore-keys: | + ${{ runner.os }}-nuget-v2- + + - name: Cache obj/ folders + id: cache-obj + uses: actions/cache@v4 + with: + path: | + # MSBuild 生成的 obj/ 文件夹 + Ink Canvas/obj + key: ${{ runner.os }}-obj-v2-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-obj-v2- + + - name: "Cache debug: show cache hit status" + run: | + echo "NuGet cache hit: ${{ steps.cache-nuget.outputs.cache-hit }}" + echo "Obj cache hit: ${{ steps.cache-obj.outputs.cache-hit }}" + + # 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 + + - 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 + + - 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 + } + } + + - name: Create Package (if build succeeded) + id: create-archive + if: steps.check-exe.outputs.build_success == 'true' + env: + 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 + + - 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" + + 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 + run: | + # 从构建作业获取构建结果 + BUILD_SUCCESS="${{ needs.build-and-package.outputs.build_result }}" + ARTIFACT_URL="${{ needs.build-and-package.outputs.artifact_url }}" + + # 使用 PR 分支的实际提交哈希 + PR_HEAD_SHA="${{ github.event.pull_request.head.sha }}" + + # 确定构建状态 + if [ "$BUILD_SUCCESS" = "true" ]; then + STATUS_ICON="✅" + STATUS_TEXT="构建成功" + COLOR="#00d26a" + else + STATUS_ICON="❌" + STATUS_TEXT="构建失败" + COLOR="#f85149" + 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://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: Update Final Comment + uses: peter-evans/create-or-update-comment@v4 + 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://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 65b66db2..8743f1d7 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -1,6 +1,9 @@ name: Pre-release and Changelog on: + push: + tags: + - '*' workflow_dispatch: inputs: version_type: @@ -19,293 +22,550 @@ on: default: true type: boolean +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-${{ github.sha }} + cancel-in-progress: true + jobs: - prerelease: - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta' + prepare: runs-on: windows-latest - permissions: - contents: write + outputs: + tag_name: ${{ steps.get_tag.outputs.tag_name }} + version: ${{ steps.get_tag.outputs.version }} + is_prerelease: ${{ steps.release_type.outputs.is_prerelease }} + changelog: ${{ steps.read_changelog.outputs.changelog }} steps: - - name: Checkout code - uses: actions/checkout@v4.2.2 - with: - fetch-depth: 0 # 获取所有历史记录用于生成changelog - - - name: Setup MSbuild - uses: microsoft/setup-msbuild@v2 - - - name: Setup NuGet - uses: NuGet/setup-nuget@v2.0.1 - - - name: Restore NuGet Packages - run: nuget restore "Ink Canvas.sln" - - - name: Get current version from Git tag - id: get_version - run: | - # 获取最新的tag - $latestTag = git describe --tags --abbrev=0 2>$null - if ($latestTag) { - # 移除v前缀(如果有的话) - $version = $latestTag -replace "^v", "" - echo "Found latest tag: $latestTag" - } else { - # 如果没有tag,使用默认版本 - $version = "1.0.0.0" - echo "No tags found, using default version" - } - echo "current_version=$version" >> $env:GITHUB_OUTPUT - echo "Current version: $version" - - - name: Calculate new version - id: calc_version - run: | - $currentVersion = "${{ steps.get_version.outputs.current_version }}" - $versionParts = $currentVersion.Split('.') - - # 确保版本号格式正确(支持4部分) - if ($versionParts.Length -ge 3) { - $major = [int]$versionParts[0] - $minor = [int]$versionParts[1] - $patch = [int]$versionParts[2] - $build = [int]$versionParts[3] - } else { - # 如果版本号格式不正确,使用默认值 - $major = 1 - $minor = 0 - $patch = 0 - $build = 0 - } - - $versionType = "${{ github.event.inputs.version_type }}" - - switch ($versionType) { - "major" { - $major++ - $minor = 0 - $patch = 0 - $build = 0 + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + fetch-tags: true + + # ========== 获取当前版本 ========== + - name: Get current version from Git tag + id: get_version + run: | + # 获取最新的tag + $latestTag = git describe --tags --abbrev=0 2>$null + if ($latestTag) { + # 移除v/b前缀 + $version = $latestTag -replace "^[vb]", "" + echo "Found latest tag: $latestTag" + } else { + # 如果没有tag,使用默认值 + $version = "1.0.0.0" + echo "No tag found, using default version: $version" } - "minor" { - $minor++ - $patch = 0 - $build = 0 - } - "patch" { - $patch++ - $build = 0 - } - "build" { - $build++ - } - } - - # 生成新版本号(4位格式,如1.7.18.0) - $newVersion = "$major.$minor.$patch.$build" - echo "new_version=$newVersion" >> $env:GITHUB_OUTPUT - echo "New version: $newVersion" - - - name: Generate Changelog - id: changelog - run: | - # 获取上次tag到现在的所有commit - $lastTag = git describe --tags --abbrev=0 2>$null - if ($lastTag) { - $commits = git log --pretty=format:"%h|%s|%an|%ad" --date=short "$lastTag..HEAD" - } else { - $commits = git log --pretty=format:"%h|%s|%an|%ad" --date=short - } - - # 初始化分类数组 - $fixes = @() - $improvements = @() - $additions = @() - $deletions = @() - $versionChanges = @() - $others = @() - - # 解析每个commit - foreach ($commit in $commits) { - if ($commit -match "^([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)$") { - $hash = $matches[1] - $message = $matches[2] - $author = $matches[3] - $date = $matches[4] + echo "current_version=$version" >> $env:GITHUB_OUTPUT + echo "Current version: $version" + + # ========== 处理版本号和标签名 ========== + - name: Get tag name and version + id: get_tag + run: | + if ("${{ github.event_name }}" -eq "push") { + # 从 push tag 事件获取原始标签名 + $tagName = "${{ github.ref }}".Replace("refs/tags/", "") + # 移除 v/b 前缀获取纯版本号 + $cleanVersion = $tagName -replace "^[vb]", "" - $commitInfo = @{ - Hash = $hash - Message = $message - Author = $author - Date = $date - } + echo "tag_name=$tagName" >> $env:GITHUB_OUTPUT + echo "version=$cleanVersion" >> $env:GITHUB_OUTPUT + echo "Using pushed tag: $tagName, version: $cleanVersion" + } else { + # 从 workflow_dispatch 计算新版本(4位格式) + $currentVersion = "${{ steps.get_version.outputs.current_version }}" + $versionParts = $currentVersion.Split('.') - # 根据commit消息分类 - if ($message -match "^(fix|修复)") { - $fixes += $commitInfo - } elseif ($message -match "^(improve|改进|优化)") { - $improvements += $commitInfo - } elseif ($message -match "^(add|新增|添加)") { - $additions += $commitInfo - } elseif ($message -match "^(delete|删除|移除)") { - $deletions += $commitInfo - } elseif ($message -match "(版本|version|更新版本号)") { - $versionChanges += $commitInfo + # 确保版本号格式正确(至少4部分) + if ($versionParts.Length -ge 4) { + $major = [int]$versionParts[0] + $minor = [int]$versionParts[1] + $patch = [int]$versionParts[2] + $build = [int]$versionParts[3] } else { - $others += $commitInfo + # 如果版本号格式不正确,补充为4位 + if ($versionParts.Length -ge 3) { + $major = [int]$versionParts[0] + $minor = [int]$versionParts[1] + $patch = [int]$versionParts[2] + $build = 0 + } else { + # 如果版本号格式不正确,抛出错误 + echo "Error: Invalid version format. Expected format: x.y.z.w (e.g., 1.7.18.0)" + exit 1 + } } + + $versionType = "${{ github.event.inputs.version_type }}" + $isPrerelease = "${{ github.event.inputs.prerelease }}" -eq "true" + + switch ($versionType) { + "major" { + $major++ + $minor = 0 + $patch = 0 + $build = 0 + } + "minor" { + $minor++ + $patch = 0 + $build = 0 + } + "patch" { + $patch++ + $build = 0 + } + "build" { + $build++ + } + } + + # 生成新版本号(4位格式,如1.7.18.0) + $newVersion = "$major.$minor.$patch.$build" + + # 根据是否为预发布决定标签前缀 + if ($isPrerelease) { + $tagName = "b$newVersion" + } else { + $tagName = "v$newVersion" + } + + echo "tag_name=$tagName" >> $env:GITHUB_OUTPUT + echo "version=$newVersion" >> $env:GITHUB_OUTPUT + echo "New tag: $tagName, version: $newVersion" } - } - - # 生成changelog内容 - $version = "${{ steps.calc_version.outputs.new_version }}" - $changelog = "# ICC CE $version 更新日志`n`n## 修复 (Fixes)" - - if ($fixes.Count -gt 0) { - foreach ($fix in $fixes) { - $changelog += "`n- $($fix.Message) ($($fix.Author), $($fix.Date))" + + - name: Determine release type + id: release_type + run: | + if ("${{ github.event_name }}" -eq "push") { + # 根据 tag 名称前缀确定是否为预发布版本 + $tagName = "${{ steps.get_tag.outputs.tag_name }}" + if ($tagName -and $tagName.StartsWith("b")) { + echo "is_prerelease=true" >> $env:GITHUB_OUTPUT + echo "This is a pre-release (beta)" + } else { + echo "is_prerelease=false" >> $env:GITHUB_OUTPUT + echo "This is a release" + } + } else { + # workflow_dispatch 方式 + echo "is_prerelease=${{ github.event.inputs.prerelease }}" >> $env:GITHUB_OUTPUT } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n## 改进 (Improvements)" - - if ($improvements.Count -gt 0) { - foreach ($improvement in $improvements) { - $changelog += "`n- $($improvement.Message) ($($improvement.Author), $($improvement.Date))" - } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n## 新增功能 (New Features)" - - if ($additions.Count -gt 0) { - foreach ($addition in $additions) { - $changelog += "`n- $($addition.Message) ($($addition.Author), $($addition.Date))" - } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n## 删除功能 (Removed Features)" - - if ($deletions.Count -gt 0) { - foreach ($deletion in $deletions) { - $changelog += "`n- $($deletion.Message) ($($deletion.Author), $($deletion.Date))" - } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n## 版本更新 (Version Updates)" - - if ($versionChanges.Count -gt 0) { - foreach ($versionChange in $versionChanges) { - $changelog += "`n- $($versionChange.Message) ($($versionChange.Author), $($versionChange.Date))" - } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n## 其他更改 (Other Changes)" - - if ($others.Count -gt 0) { - foreach ($other in $others) { - $changelog += "`n- $($other.Message) ($($other.Author), $($other.Date))" - } - } else { - $changelog += "`n- 无" - } - - $changelog += "`n`n---`n*此更新日志由GitHub Actions自动生成*" - - # 保存changelog到文件 - $changelog | Out-File -FilePath "CHANGELOG_${{ steps.calc_version.outputs.new_version }}.md" -Encoding UTF8 - - # 输出changelog内容到步骤输出 - echo "changelog<> $env:GITHUB_OUTPUT - echo $changelog >> $env:GITHUB_OUTPUT - echo "EOF" >> $env:GITHUB_OUTPUT - - echo "Changelog generated successfully" - - - name: Display version info - run: | - echo "Current version: ${{ steps.get_version.outputs.current_version }}" - echo "New version: ${{ steps.calc_version.outputs.new_version }}" - echo "Note: Version will not be automatically updated in repository files" - - - name: Build the Solution - run: | - msbuild -t:restore /p:GitFlow="Github Action" - msbuild /p:platform="AnyCPU" /p:configuration="Release" /p:GitFlow="Github Action" "Ink Canvas/InkCanvasForClass.csproj" - - - name: Create Release Archive - run: | - $version = "${{ steps.calc_version.outputs.new_version }}" - $archiveName = "InkCanvasForClass.CE.$version.zip" - - # 创建发布目录 - New-Item -ItemType Directory -Path "release" -Force - - # 复制发布文件 - Copy-Item "Ink Canvas\bin\Release\net472\*" "release\" -Recurse -Force - - # 创建压缩包 - Compress-Archive -Path "release\*" -DestinationPath $archiveName -Force - - echo "archive_name=$archiveName" >> $env:GITHUB_OUTPUT - - - name: Upload Release Assets - uses: actions/upload-artifact@v4.5.0 - with: - name: release-files-${{ steps.calc_version.outputs.new_version }} - path: | - InkCanvasForClass.CE.${{ steps.calc_version.outputs.new_version }}.zip - CHANGELOG_${{ steps.calc_version.outputs.new_version }}.md + + # ========== 使用 git-cliff 生成变更日志 ========== + - name: Generate changelog with git-cliff (for pushed tag) + if: github.event_name == 'push' + id: git_cliff_tag + uses: orhun/git-cliff-action@v4 + with: + config: build/cliff.toml # 使用项目build目录的 cliff.toml 配置 + args: --latest --tag ${{ steps.get_tag.outputs.tag_name }} --output CHANGELOG.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate changelog with git-cliff (for workflow_dispatch) + if: github.event_name == 'workflow_dispatch' + id: git_cliff_unreleased + uses: orhun/git-cliff-action@v4 + with: + config: build/cliff.toml + args: --unreleased --tag ${{ steps.get_tag.outputs.tag_name }} --output CHANGELOG.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Read changelog content + id: read_changelog + run: | + $changelogContent = Get-Content -Path CHANGELOG.md -Raw + echo "changelog<> $env:GITHUB_OUTPUT + echo $changelogContent >> $env:GITHUB_OUTPUT + echo "EOF" >> $env:GITHUB_OUTPUT + + build: + needs: prepare + if: success() + runs-on: windows-latest + outputs: + archive_name: ${{ steps.create_archive.outputs.archive_name }} + zip_size: ${{ steps.calculate_size.outputs.zip_size }} + zip_hash: ${{ steps.calculate_size.outputs.zip_hash }} + installer_size: ${{ steps.calculate_installer_size.outputs.installer_size }} + installer_hash: ${{ steps.calculate_installer_size.outputs.installer_hash }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Setup NuGet + uses: NuGet/setup-nuget@v2.0.1 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Install Inno Setup Unofficial Language Files + run: | + # 创建临时目录用于下载文件 + New-Item -ItemType Directory -Path "temp_lang" -Force - - name: Prepare Release Info - run: | - $version = "${{ steps.calc_version.outputs.new_version }}" - echo "Preparing release for version: $version" - - - name: Create GitHub Release - uses: softprops/action-gh-release@v1 - with: - tag_name: ${{ steps.calc_version.outputs.new_version }} - name: ICC CE ${{ steps.calc_version.outputs.new_version }} - body: | - ${{ steps.changelog.outputs.changelog }} - draft: false - prerelease: ${{ github.event.inputs.prerelease }} - files: | - InkCanvasForClass.CE.${{ steps.calc_version.outputs.new_version }}.zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Generate UpdateLog preview - run: | - $version = "${{ steps.calc_version.outputs.new_version }}" - $changelogFile = "CHANGELOG_$version.md" - - # 读取生成的changelog - $changelogContent = Get-Content $changelogFile -Raw - - # 生成预览内容 - $previewContent = "ICC CE $version 更新日志`n" + $changelogContent - - echo "UpdateLog preview generated (not written to file):" - echo $previewContent - - - name: Display Summary - run: | - echo "=== Release Summary ===" - echo "Version: ${{ steps.calc_version.outputs.new_version }}" - echo "Pre-release: ${{ github.event.inputs.prerelease }}" - echo "Changelog: Generated and attached to release" - echo "Archive: ICC_CE_${{ steps.calc_version.outputs.new_version }}.zip" - echo "" - echo "Note: No repository files were modified" - echo "You can manually update version numbers and changelog as needed" + # 下载英语英国版语言文件 + 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" + + # 将文件移动到 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 + + # 清理临时目录 + 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 + run: | + $version = "${{ needs.prepare.outputs.version }}" + $archiveName = "InkCanvasForClass.CE.$version.zip" + + # 创建发布目录 + New-Item -ItemType Directory -Path "release" -Force + + # 复制发布文件 + Copy-Item "Ink Canvas\bin\Release\net472\*" "release\" -Recurse -Force + + # 创建压缩包 + Compress-Archive -Path "release\*" -DestinationPath $archiveName -Force + + echo "archive_name=$archiveName" >> $env:GITHUB_OUTPUT + + - name: Prepare Inno Setup script + run: | + $version = "${{ needs.prepare.outputs.version }}" + + # 更新 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 'OutputDir=.*', 'OutputDir=.' + + # 更新默认安装目录 + $issContent = $issContent -replace 'DefaultDirName=.*', 'DefaultDirName={autopf}\{#MyAppName}' + + # 更新许可证文件路径为相对路径(考虑到ISS文件在build目录下,需要返回上级目录) + $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 + uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 + with: + path: build\InkCanvasForClass CE.iss + options: /O. + + - name: Rename installer file + run: | + $version = "${{ needs.prepare.outputs.version }}" + $setupFile = "InkCanvasForClass CE Setup.exe" + $newSetupName = "InkCanvasForClass.CE.$version.Setup.exe" + + 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" + } + + - name: Calculate archive size and hash + id: calculate_size + run: | + $version = "${{ needs.prepare.outputs.version }}" + $archiveName = "InkCanvasForClass.CE.$version.zip" + + # 获取文件大小(字节) + $fileSize = (Get-Item $archiveName).Length + + # 计算SHA256哈希 + $hash = (Get-FileHash $archiveName -Algorithm SHA256).Hash + + echo "zip_size=$fileSize" >> $env:GITHUB_OUTPUT + echo "zip_hash=$hash" >> $env:GITHUB_OUTPUT + + echo "Archive size: $fileSize bytes" + echo "SHA256 hash: $hash" + + - name: Calculate installer size and hash + id: calculate_installer_size + run: | + $version = "${{ needs.prepare.outputs.version }}" + $installerName = "InkCanvasForClass.CE.$version.Setup.exe" + + if (Test-Path $installerName) { + # 获取文件大小(字节) + $fileSize = (Get-Item $installerName).Length + + # 计算SHA256哈希 + $hash = (Get-FileHash $installerName -Algorithm SHA256).Hash + + echo "installer_size=$fileSize" >> $env:GITHUB_OUTPUT + echo "installer_hash=$hash" >> $env:GITHUB_OUTPUT + + echo "Installer size: $fileSize bytes" + echo "SHA256 hash: $hash" + } else { + echo "Installer file not found: $installerName" + } + + - name: Upload Build Artifacts + uses: actions/upload-artifact@v4 + with: + name: build-files-${{ needs.prepare.outputs.version }} + path: | + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe + + sign: + needs: [prepare, build] + if: success() + runs-on: ubuntu-latest # 改为 Ubuntu 以使用 Python 签名工具 + outputs: + signatures_created: ${{ steps.sign_artifacts.outputs.signatures_created }} + zip_sigstore_file: "InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip.sigstore.json" + installer_sigstore_file: "InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe.sigstore.json" + zip_sigstore_hash: ${{ steps.calculate_zip_sig_hash.outputs.sigstore_hash }} + installer_sigstore_hash: ${{ steps.calculate_installer_sig_hash.outputs.sigstore_hash }} + permissions: + contents: write + id-token: write # 需要这个权限来验证签名 + steps: + - name: Download Build Artifacts + uses: actions/download-artifact@v4 + with: + name: build-files-${{ needs.prepare.outputs.version }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Sign release artifacts with sigstore-python + id: sign_artifacts + uses: sigstore/gh-action-sigstore-python@v3.2.0 + with: + inputs: | + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe + release-signing-artifacts: true + upload-signing-artifacts: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check generated signature files + run: | + version="${{ needs.prepare.outputs.version }}" + echo "Checking for generated signature files..." + ls -la *.sig* || true + echo "Current directory contents:" + pwd + ls -la + + - name: Calculate ZIP signature hash + id: calculate_zip_sig_hash + run: | + version="${{ needs.prepare.outputs.version }}" + sigstoreFile="InkCanvasForClass.CE.$version.zip.sigstore.json" + + if [ -f "$sigstoreFile" ]; then + # 计算SHA256哈希 + sigstoreHash=$(sha256sum "$sigstoreFile" | cut -d' ' -f1) + + echo "sigstore_hash=$sigstoreHash" >> $GITHUB_OUTPUT + echo "Sigstore JSON file hash: $sigstoreHash" + echo "Sigstore file size: $(stat -c%s "$sigstoreFile") bytes" + else + echo "Warning: Sigstore file not found: $sigstoreFile" + echo "sigstore_hash=" >> $GITHUB_OUTPUT + fi + + - name: Calculate Installer signature hash + id: calculate_installer_sig_hash + run: | + version="${{ needs.prepare.outputs.version }}" + sigstoreFile="InkCanvasForClass.CE.$version.Setup.exe.sigstore.json" + + if [ -f "$sigstoreFile" ]; then + # 计算SHA256哈希 + sigstoreHash=$(sha256sum "$sigstoreFile" | cut -d' ' -f1) + + echo "sigstore_hash=$sigstoreHash" >> $GITHUB_OUTPUT + echo "Sigstore JSON file hash: $sigstoreHash" + echo "Sigstore file size: $(stat -c%s "$sigstoreFile") bytes" + else + echo "Warning: Sigstore file not found: $sigstoreFile" + echo "sigstore_hash=" >> $GITHUB_OUTPUT + fi + + - name: Upload Signed Artifacts + if: steps.calculate_zip_sig_hash.outputs.sigstore_hash != '' || steps.calculate_installer_sig_hash.outputs.sigstore_hash != '' + uses: actions/upload-artifact@v4 + with: + name: signed-files-${{ needs.prepare.outputs.version }} + path: | + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip.sigstore.json + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe.sigstore.json + + release: + needs: [prepare, build, sign] + if: success() + runs-on: ubuntu-latest + + steps: + - name: Download Build Artifacts + uses: actions/download-artifact@v4 + with: + name: build-files-${{ needs.prepare.outputs.version }} + + - name: Download Signed Artifacts (if exists) + uses: actions/download-artifact@v4 + with: + name: signed-files-${{ needs.prepare.outputs.version }} + continue-on-error: true + + + - name: Create enhanced changelog with file table + id: enhanced_changelog + run: | + version="${{ needs.prepare.outputs.version }}" + + # 读取git-cliff生成的changelog内容 + originalChangelog="${{ needs.prepare.outputs.changelog }}" + + # 构建文件信息表格 + fileTable=$'\n## 文件信息 (File Information)\n' + fileTable+=$'| 文件名 | 大小 | SHA256 哈希 |\n' + fileTable+=$'|--------|------|-------------|\n' + + # ZIP 文件信息 + fileTable+=$'| InkCanvasForClass.CE.'"$version" + fileTable+=$'.zip | ${{ needs.build.outputs.zip_size }} bytes | ${{ needs.build.outputs.zip_hash }} |\n' + + # 安装包文件信息 + installerSize="${{ needs.build.outputs.installer_size }}" + installerHash="${{ needs.build.outputs.installer_hash }}" + if [ -n "$installerSize" ] && [ -n "$installerHash" ]; then + fileTable+=$'| InkCanvasForClass.CE.'"$version"'.Setup.exe | '"$installerSize"' bytes | '"$installerHash" + fileTable+=$' |\n' + fi + + # 检查是否有签名文件 + if [ -f "InkCanvasForClass.CE.$version.zip.sigstore.json" ]; then + sigstoreSize=$(stat -c%s "InkCanvasForClass.CE.$version.zip.sigstore.json") + sigstoreHash=$(sha256sum "InkCanvasForClass.CE.$version.zip.sigstore.json" | cut -d' ' -f1) + fileTable+=$'| InkCanvasForClass.CE.'"$version"'.zip.sigstore.json | '"$sigstoreSize"' bytes | '"$sigstoreHash" + fileTable+=$' |\n' + fi + + # 检查安装程序签名文件 + if [ -f "InkCanvasForClass.CE.$version.Setup.exe.sigstore.json" ]; then + sigstoreSize=$(stat -c%s "InkCanvasForClass.CE.$version.Setup.exe.sigstore.json") + sigstoreHash=$(sha256sum "InkCanvasForClass.CE.$version.Setup.exe.sigstore.json" | cut -d' ' -f1) + fileTable+=$'| InkCanvasForClass.CE.'"$version"'.Setup.exe.sigstore.json | '"$sigstoreSize"' bytes | '"$sigstoreHash" + fileTable+=$' |\n' + fi + + fileTable+=$'\n*文件哈希和大小信息由GitHub Actions自动生成*\n' + + # 将表格附加到原始changelog + enhancedChangelog="${originalChangelog}${fileTable}" + + # 输出增强版changelog内容 + echo "enhanced_changelog<> $GITHUB_OUTPUT + echo "$enhancedChangelog" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + echo "Enhanced changelog created with file information table" + + - name: Display Release Info + run: | + echo "=== Creating Release ===" + echo "Version: ${{ needs.prepare.outputs.version }}" + echo "Tag: ${{ needs.prepare.outputs.tag_name }}" + echo "Pre-release: ${{ needs.prepare.outputs.is_prerelease }}" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.prepare.outputs.tag_name }} + name: ICC CE ${{ needs.prepare.outputs.version }} + body: | + ${{ steps.enhanced_changelog.outputs.enhanced_changelog }} + draft: false + prerelease: ${{ needs.prepare.outputs.is_prerelease == 'true' }} + files: | + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.zip.sigstore.json + InkCanvasForClass.CE.${{ needs.prepare.outputs.version }}.Setup.exe.sigstore.json + fail_on_unmatched_files: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/build/InkCanvasForClass CE.iss b/build/InkCanvasForClass CE.iss new file mode 100644 index 00000000..576b9a34 --- /dev/null +++ b/build/InkCanvasForClass CE.iss @@ -0,0 +1,63 @@ +; 脚本由 Inno Setup 脚本向导生成。 +; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档! + +#define MyAppName "InkCanvasForClass CE" +#define MyAppVersion "1.7.18.1" +#define MyAppPublisher "CJK_mkp" +#define MyAppURL "https://inkcanvasforclass.github.io" +#define MyAppExeName "InkCanvasForClass.exe" +#define MyAppAssocName MyAppName + "" +#define MyAppAssocExt ".exe" +#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt + +[Setup] +; 注意:AppId 的值唯一标识此应用程序。不要在其他应用程序的安装程序中使用相同的 AppId 值。 +; (若要生成新的 GUID,请在 IDE 中单击 "工具|生成 GUID"。) +AppId={{CA801226-FD02-4C78-BCF8-753B38E70CB3}} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +UninstallDisplayIcon={app}\{#MyAppExeName} +ChangesAssociations=yes +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile=LICENSE +; 取消注释以下行以在非管理员安装模式下运行 (仅为当前用户安装)。 +;PrivilegesRequired=lowest +PrivilegesRequiredOverridesAllowed=dialog +OutputDir=. +OutputBaseFilename=InkCanvasForClass CE Setup +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "chinesesimp"; MessagesFile: "compiler:Languages\ChineseSimplified.isl" +Name: "english"; MessagesFile: "compiler:Languages\EnglishBritish.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "release\InkCanvasForClass.exe.config"; DestDir: "{app}"; Flags: ignoreversion +; 注意:不要在任何共享系统文件上使用 "Flags: ignoreversion" + +[Registry] +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0" +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1""" + +[Icons] +Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent \ No newline at end of file diff --git a/build/cliff.toml b/build/cliff.toml new file mode 100644 index 00000000..2eee46bb --- /dev/null +++ b/build/cliff.toml @@ -0,0 +1,95 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + + +[changelog] +# A Tera template to be rendered for each release in the changelog. +# See https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% 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}})\ + {% endfor %} +{% endfor %} +""" +# Remove leading and trailing whitespaces from the changelog's body. +trim = true +# Render body even when there are no releases to process. +render_always = true +# An array of regex based postprocessors to modify the changelog. +postprocessors = [ + # Replace the placeholder with a URL. + #{ pattern = '', replace = "https://github.com/orhun/git-cliff" }, +] +# render body even when there are no releases to process +# render_always = true +# output file path +# output = "test.md" + +[git] +# Parse commits according to the conventional commits specification. +# See https://www.conventionalcommits.org +conventional_commits = true +# Exclude commits that do not match the conventional commits specification. +filter_unconventional = true +# Require all commits to be conventional. +# Takes precedence over filter_unconventional. +require_conventional = false +# Split commits on newlines, treating each line as an individual commit. +split_commits = false +# An array of regex based parsers to modify commit messages prior to further processing. +commit_preprocessors = [ + # Replace issue numbers with link templates to be updated in `changelog.postprocessors`. + #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit message using https://github.com/crate-ci/typos. + # If the spelling is incorrect, it will be fixed automatically. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# Prevent commits that are breaking from being excluded by commit parsers. +protect_breaking_commits = false +# An array of regex based parsers for extracting data from the commit message. +# Assigns commits to groups. +# Optionally sets the commit's scope and can decide to exclude commits from further processing. + +commit_parsers = [ + { message = "^(add|新增|添加)", group = "🚀 新增功能" }, + { message = "^(fix|修复)", group = "🐛 修复" }, + { message = "^doc", group = "📚 文档更改" }, + { message = "^(improve|改进|优化)", group = "⚡ 体验优化" }, + { message = "^refactor", group = "🚜 重构" }, + { message = "^style", group = "🎨 格式化" }, + { message = "^(delete|删除|移除)", group = "❌ 删除功能" }, + { message = "^test", group = "🧪 测试" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "⚙️ 杂项" }, + { body = ".*security", group = "🛡️ 安全" }, + { message = "^revert", group = "◀️ 回退" }, + { message = "(版本|version|更新版本号)", group = "🎉 版本号更新" }, + { message = ".*", group = "💼 其他更改" }, +] +# Exclude commits that are not matched by any commit parser. +filter_commits = false +# An array of link parsers for extracting external references, and turning them into URLs, using regex. +link_parsers = [] +# Include only the tags that belong to the current branch. +use_branch_tags = false +# Order releases topologically instead of chronologically. +topo_order = false +# Order releases topologically instead of chronologically. +topo_order_commits = true +# Order of commits in each group/release within the changelog. +# Allowed values: newest, oldest +sort_commits = "oldest" +# Process submodules commits +recurse_submodules = false