Skip to content

chore(release): bump version to 1.3.1-rc.1 #24

chore(release): bump version to 1.3.1-rc.1

chore(release): bump version to 1.3.1-rc.1 #24

Workflow file for this run

name: release
# 推送 v* tag 自动触发:构建三种形态 → 各自打包完整发行包 → 创建 GitHub Release 并上传。
# 也可在 Actions 页手动触发(仅产出构建工件,不发布 Release)。
#
# 三种构建版本(均自带 catalog/ configs/ assets/ 数据链):
# 1) with-runtime —— 集成 .NET 运行环境版:自包含、多文件,目标机免装 .NET。
# 2) framework —— 纯 App 版:依赖框架,体积最小,需目标机安装 .NET 10 桌面运行时。
# 3) singlefile —— 单文件版:自包含、单个 OwOWinDeployer.exe,目标机免装 .NET。
on:
push:
tags: ['v*']
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: windows-latest
env:
# 可选 Authenticode 代码签名:在仓库 Settings → Secrets 配置后自动启用(彻底解决 SmartScreen/Defender 拦截)。
SIGN_PFX_BASE64: ${{ secrets.SIGN_PFX_BASE64 }}
SIGN_PFX_PASSWORD: ${{ secrets.SIGN_PFX_PASSWORD }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'
- name: Publish all variants (集成运行环境 / 纯App / 单文件)
shell: pwsh
run: |
$variants = @(
@{ Key = 'with-runtime'; Sc = 'true'; Single = 'false' },
@{ Key = 'framework'; Sc = 'false'; Single = 'false' },
@{ Key = 'singlefile'; Sc = 'true'; Single = 'true' }
)
foreach ($v in $variants) {
$pubArgs = @('-c', 'Release', '-r', 'win-x64', '--self-contained', $v.Sc,
"-p:PublishSingleFile=$($v.Single)", '-p:DebugType=none', '--nologo')
if ($v.Single -eq 'true') { $pubArgs += '-p:IncludeNativeLibrariesForSelfExtract=true' }
Write-Host "== publish [$($v.Key)] GUI =="
dotnet publish src/OwOWinDeployer.App/OwOWinDeployer.App.csproj @pubArgs -o "dist/$($v.Key)/app"
if ($LASTEXITCODE -ne 0) { throw "GUI publish failed: $($v.Key)" }
Write-Host "== publish [$($v.Key)] CLI =="
dotnet publish src/OwOWinDeployer.Cli/OwOWinDeployer.Cli.csproj @pubArgs -o "dist/$($v.Key)/cli"
if ($LASTEXITCODE -ne 0) { throw "CLI publish failed: $($v.Key)" }
}
- name: Code sign binaries (only runs if a signing certificate secret is configured)
if: ${{ env.SIGN_PFX_BASE64 != '' }}
shell: pwsh
run: |
$pfx = Join-Path $env:RUNNER_TEMP 'sign.pfx'
[IO.File]::WriteAllBytes($pfx, [Convert]::FromBase64String($env:SIGN_PFX_BASE64))
$signtool = Get-ChildItem 'C:/Program Files (x86)/Windows Kits/10/bin' -Recurse -Filter signtool.exe -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -like '*x64*' } | Sort-Object FullName | Select-Object -Last 1
if (-not $signtool) { throw 'signtool.exe not found on runner' }
# Sign every variant's GUI + CLI executable before packaging.
$files = Get-ChildItem dist -Recurse -File |
Where-Object { $_.Name -in @('OwOWinDeployer.exe', 'owowindeployer.exe') } |
Select-Object -ExpandProperty FullName
& $signtool.FullName sign /f $pfx /p $env:SIGN_PFX_PASSWORD /fd SHA256 `
/tr http://timestamp.digicert.com /td SHA256 @files
Remove-Item $pfx -Force
- name: Assemble release packages (one ZIP per variant)
shell: pwsh
run: |
$tag = '${{ github.ref_name }}'
if ([string]::IsNullOrWhiteSpace($tag)) { $tag = 'dev' }
$variants = @(
@{ Key = 'with-runtime'; Single = $false },
@{ Key = 'framework'; Single = $false },
@{ Key = 'singlefile'; Single = $true }
)
foreach ($v in $variants) {
$appOut = "dist/$($v.Key)/app"
$cliOut = "dist/$($v.Key)/cli"
$name = "OwO-Win-Deployer-$tag-win-x64-$($v.Key)"
$stage = "dist/$name"
New-Item -ItemType Directory -Force -Path "$stage/assets" | Out-Null
if ($v.Single) {
# 单文件:仅一个 exe(运行库已并入)+ CLI 单文件
Copy-Item "$appOut/OwOWinDeployer.exe" "$stage/OwOWinDeployer.exe" -Force
Copy-Item "$cliOut/owowindeployer.exe" "$stage/owowindeployer-cli.exe" -Force
# CLI 别名:单文件自包含,副本可独立运行(保留已签名字节)。
Copy-Item "$cliOut/owowindeployer.exe" "$stage/owodeploy.exe" -Force
} else {
# 多文件:GUI 全量输出放根目录;CLI 放 cli/ 子目录(两者运行库 DLL 集不同,分目录避免冲突)
Copy-Item "$appOut/*" "$stage/" -Recurse -Force
New-Item -ItemType Directory -Force -Path "$stage/cli" | Out-Null
Copy-Item "$cliOut/*" "$stage/cli/" -Recurse -Force
# CLI 别名:apphost 副本,与 owowindeployer.dll 同目录即可运行。
Copy-Item "$stage/cli/owowindeployer.exe" "$stage/cli/owodeploy.exe" -Force
}
# 运行所需数据放在 exe 同级(程序向上查找 catalog/,再据此定位 repoRoot/assets)
Copy-Item catalog "$stage/catalog" -Recurse -Force
Copy-Item assets/icons "$stage/assets/icons" -Recurse -Force
Copy-Item configs "$stage/configs" -Recurse -Force
Copy-Item tools "$stage/tools" -Recurse -Force # bundled smartctl.exe (USB SMART)
Copy-Item LICENSE "$stage/LICENSE" -Force
Copy-Item README.md "$stage/README.md" -Force
Compress-Archive -Path "$stage" -DestinationPath "dist/$name.zip" -Force
Write-Host "packaged: dist/$name.zip"
}
# 供裸机引导 bootstrap.ps1 直链下载的单文件 GUI
Copy-Item "dist/singlefile/app/OwOWinDeployer.exe" "dist/OwOWinDeployer.exe" -Force
- name: Upload build artifacts
uses: actions/upload-artifact@v6
with:
name: OwO-Win-Deployer-win-x64
path: dist/*.zip
# Build the Release body from CHANGELOG.md's section for this tag (新增/调整/删除) + the static download
# table (.github/release-body.md). Falls back to the table alone if the tag has no changelog section.
- name: Compose release notes from CHANGELOG
if: startsWith(github.ref, 'refs/tags/')
shell: pwsh
run: |
$tag = '${{ github.ref_name }}'
$section = ''
if (Test-Path docs/CHANGELOG.md) {
$changelog = Get-Content docs/CHANGELOG.md -Raw
$pattern = "(?ms)^##\s+" + [regex]::Escape($tag) + "\b.*?(?=^##\s+|\z)"
$m = [regex]::Match($changelog, $pattern)
if ($m.Success) { $section = $m.Value.Trim() }
}
if (-not $section) { Write-Host "::warning::docs/CHANGELOG.md has no section for $tag — release notes will omit the changelog." }
$table = if (Test-Path .github/release-body.md) { (Get-Content .github/release-body.md -Raw).Trim() } else { '' }
$parts = @($section, $table) | Where-Object { $_ }
$notes = $parts -join "`n`n---`n`n"
Set-Content -Path release-notes.md -Value $notes -Encoding utf8
Write-Host "=== release-notes.md ==="; Get-Content release-notes.md
- name: Publish GitHub Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v3
with:
name: OwO! Win Deployer ${{ github.ref_name }}
generate_release_notes: true
body_path: release-notes.md
# SemVer convention: a hyphen in the tag marks a pre-release identifier (e.g. v1.3.1-rc.1) →
# publish as a GitHub Pre-release (not marked "Latest"); clean vX.Y.Z tags are full releases.
prerelease: ${{ contains(github.ref_name, '-') }}
files: |
dist/*.zip
dist/OwOWinDeployer.exe