Skip to content
345 changes: 345 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,345 @@
# GitHub Actions Release Workflow for iiCourseWPF
# 触发方式: 推送标签 v* 或手动触发
# 任务拆分: build → release → checksum

name: Release iiCourseWPF

on:
# 当推送版本标签时触发 (例如: v1.0.0)
push:
tags:
- 'v*'
# 允许手动触发
workflow_dispatch:
inputs:
version:
description: '版本号 (例如: 1.8.0)'
required: true
default: '1.8.0'
prerelease:
description: '是否为预发布版本'
type: boolean
required: false
default: false

env:
DOTNET_VERSION: '9.0.x'
SOLUTION_PATH: 'iiCourseWPF.sln'
MAIN_PROJECT: 'iiCourseWPF/iiCourseWPF.csproj'

jobs:
# ========== Job 1: 构建 ==========
build:
runs-on: windows-latest
outputs:
version: ${{ steps.version.outputs.version }}
assembly_version: ${{ steps.version.outputs.assembly_version }}

steps:
# 检出代码
- name: 检出代码
uses: actions/checkout@v4
with:
fetch-depth: 0

# 设置 .NET 9.0
- name: 设置 .NET ${{ env.DOTNET_VERSION }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

# 提取版本号
- name: 提取版本号
id: version
shell: pwsh
run: |
if ('${{ github.event_name }}' -eq 'workflow_dispatch') {
$version = '${{ github.event.inputs.version }}'
} else {
$tag = '${{ github.ref_name }}'
$version = $tag -replace '^v', ''
}
$assemblyVersion = "$version.0"
echo "version=$version" >> $env:GITHUB_OUTPUT
echo "assembly_version=$assemblyVersion" >> $env:GITHUB_OUTPUT
Write-Host "版本: $version"
Write-Host "程序集版本: $assemblyVersion"

# 还原 NuGet 包
- name: 还原 NuGet 包
run: dotnet restore ${{ env.SOLUTION_PATH }}

# 更新项目版本号
- name: 更新版本号
shell: pwsh
run: |
$version = '${{ steps.version.outputs.version }}'
$assemblyVersion = '${{ steps.version.outputs.assembly_version }}'

# 更新主项目
$mainProject = '${{ env.MAIN_PROJECT }}'
[xml]$xml = Get-Content $mainProject
$xml.Project.PropertyGroup.Version = $version
$xml.Project.PropertyGroup.AssemblyVersion = $assemblyVersion
$xml.Project.PropertyGroup.FileVersion = $assemblyVersion
$xml.Save($mainProject)

# 更新 Core 项目
$coreProject = 'iiCourse.Core/iiCourse.Core.csproj'
[xml]$xml = Get-Content $coreProject
$xml.Project.PropertyGroup.Version = $version
$xml.Project.PropertyGroup.AssemblyVersion = $assemblyVersion
$xml.Project.PropertyGroup.FileVersion = $assemblyVersion
$xml.Save($coreProject)

Write-Host "版本号已更新为: $version"

# 构建项目 (Release 配置)
- name: 构建项目
run: dotnet build ${{ env.SOLUTION_PATH }} --configuration Release --no-restore

# 运行测试 (如果有测试项目)
- name: 运行测试
run: dotnet test ${{ env.SOLUTION_PATH }} --configuration Release --no-build --verbosity normal
continue-on-error: true

# 发布自包含应用 (x64)
- name: 发布应用 (x64 自包含)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-x64 `
--self-contained true `
--output ./publish/x64 `
-p:PublishSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true

# 发布框架依赖应用 (x64)
- name: 发布应用 (x64 框架依赖)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-x64 `
--self-contained false `
--output ./publish/x64-framework `
-p:PublishSingleFile=true

# 发布自包含应用 (x86)
- name: 发布应用 (x86 自包含)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-x86 `
--self-contained true `
--output ./publish/x86 `
-p:PublishSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true

# 发布框架依赖应用 (x86)
- name: 发布应用 (x86 框架依赖)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-x86 `
--self-contained false `
--output ./publish/x86-framework `
-p:PublishSingleFile=true

# 发布自包含应用 (ARM64)
- name: 发布应用 (ARM64 自包含)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-arm64 `
--self-contained true `
--output ./publish/arm64 `
-p:PublishSingleFile=true `
-p:IncludeNativeLibrariesForSelfExtract=true

# 发布框架依赖应用 (ARM64)
- name: 发布应用 (ARM64 框架依赖)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--runtime win-arm64 `
--self-contained false `
--output ./publish/arm64-framework `
-p:PublishSingleFile=true

# 发布纯框架依赖应用
- name: 发布应用 (纯框架依赖)
run: |
dotnet publish ${{ env.MAIN_PROJECT }} `
--configuration Release `
--self-contained false `
--output ./publish/dotnet9-required

# 上传构建产物
- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: ./publish/
retention-days: 1

# ========== Job 2: 打包和发布 ==========
release:
needs: build
runs-on: windows-latest

steps:
# 下载构建产物
- name: 下载构建产物
uses: actions/download-artifact@v4
with:
name: build-artifacts
path: ./publish/

# 获取版本号
- name: 获取版本号
id: version
shell: pwsh
run: |
if ('${{ github.event_name }}' -eq 'workflow_dispatch') {
$version = '${{ github.event.inputs.version }}'
} else {
$tag = '${{ github.ref_name }}'
$version = $tag -replace '^v', ''
}
echo "version=$version" >> $env:GITHUB_OUTPUT
Write-Host "版本: $version"

# 打包所有版本
- name: 打包所有版本
shell: pwsh
run: |
$version = '${{ steps.version.outputs.version }}'
Compress-Archive -Path ./publish/x64/* -DestinationPath "./iiCourseWPF-v$version-win-x64-self-contained.zip" -Force
Compress-Archive -Path ./publish/x64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x64-framework.zip" -Force
Compress-Archive -Path ./publish/x86/* -DestinationPath "./iiCourseWPF-v$version-win-x86-self-contained.zip" -Force
Compress-Archive -Path ./publish/x86-framework/* -DestinationPath "./iiCourseWPF-v$version-win-x86-framework.zip" -Force
Compress-Archive -Path ./publish/arm64/* -DestinationPath "./iiCourseWPF-v$version-win-arm64-self-contained.zip" -Force
Compress-Archive -Path ./publish/arm64-framework/* -DestinationPath "./iiCourseWPF-v$version-win-arm64-framework.zip" -Force
Compress-Archive -Path ./publish/dotnet9-required/* -DestinationPath "./iiCourseWPF-v$version-dotnet9-required.zip" -Force
Write-Host "打包完成"

# 上传发布产物
- name: 上传发布产物
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: ./iiCourseWPF-v*.zip
retention-days: 30

# ========== Job 3: 创建 GitHub Release ==========
create-release:
needs: release
runs-on: ubuntu-latest
permissions:
contents: write

steps:
# 下载发布产物
- name: 下载发布产物
uses: actions/download-artifact@v4
with:
name: release-artifacts
path: ./artifacts

# 获取版本号
- name: 获取版本号
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
version=$(echo "${{ github.ref_name }}" | sed 's/^v//')
echo "version=$version" >> $GITHUB_OUTPUT
fi

# 创建 GitHub Release
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}
name: ${{ github.event_name == 'workflow_dispatch' && format('iiCourseWPF v{0}', github.event.inputs.version) || format('iiCourseWPF {0}', github.ref_name) }}
body: |
## iiCourseWPF ${{ steps.version.outputs.version }}

### 下载地址

**Windows (需要 Windows 10 1809+ 或 Windows 11)**

自包含版本(推荐,无需安装 .NET 9 运行时)
- [64位(常用)](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-self-contained.zip) | [32位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-self-contained.zip) | [ARM64](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-self-contained.zip)

框架依赖版本(体积较小,需先安装 [.NET 9 运行时](https://dotnet.microsoft.com/download/dotnet/9.0))
- [64位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x64-framework.zip) | [32位](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-x86-framework.zip) | [ARM64](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-win-arm64-framework.zip)

纯框架依赖版本(体积最小 ~200KB,需先安装 [.NET 9 运行时](https://dotnet.microsoft.com/download/dotnet/9.0))
- [下载](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/iiCourseWPF-v${{ steps.version.outputs.version }}-dotnet9-required.zip)

### 如何选择版本?

| 版本类型 | 文件大小 | 是否需要 .NET 9 | 适用场景 |
|---------|---------|----------------|---------|
| 自包含 64位 | ~50MB | ❌ 不需要 | **大多数用户推荐**,64位 Windows |
| 自包含 32位 | ~45MB | ❌ 不需要 | 32位 Windows 系统 |
| 自包含 ARM64 | ~45MB | ❌ 不需要 | Surface Pro X、Copilot+ PC 等 ARM 设备 |
| 框架依赖 64位 | ~5MB | ✅ 需要 | 已安装 .NET 9 的 64位系统 |
| 框架依赖 32位 | ~4MB | ✅ 需要 | 已安装 .NET 9 的 32位系统 |
| 框架依赖 ARM64 | ~4MB | ✅ 需要 | 已安装 .NET 9 的 ARM 设备 |
| 纯框架依赖 | ~200KB | ✅ 必须 | 开发者或磁盘空间极紧张 |

### 快速开始

1. **下载对应版本**(不确定就选「自包含 64位」)
2. **解压**到任意文件夹
3. **运行** `iiCourseWPF.exe`

### 校验

文件 SHA256 校验和可在发布页面查看,或下载 [checksums.txt](https://github.com/${{ github.repository }}/releases/download/${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}/checksums.txt)。

---
**完整更新日志**: 参见 [CHANGELOG.md](./docs/changelog.md)
files: ./artifacts/*.zip
prerelease: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.prerelease || false }}
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# ========== Job 4: 生成校验和 ==========
checksum:
needs: create-release
runs-on: ubuntu-latest
permissions:
contents: write

steps:
# 检出代码
- name: 检出代码
uses: actions/checkout@v4

# 下载发布产物
- name: 下载发布产物
uses: actions/download-artifact@v4
with:
name: release-artifacts
path: ./artifacts

# 生成校验和文件
- name: 生成 SHA256 校验和
run: |
cd ./artifacts
sha256sum *.zip > checksums.txt
cat checksums.txt

# 上传校验和到 Release
- name: 上传校验和
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}
files: ./artifacts/checksums.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Loading