mirror of
https://github.com/dream-pep/koring-launcher.git
synced 2026-09-12 05:45:18 +08:00
209 lines
10 KiB
YAML
209 lines
10 KiB
YAML
# Koring Launcher 构建 & 发布流水线(手动触发):构建 → SignPath 签名 → 发布 GitHub Release
|
||
#
|
||
# 手动触发(Actions 页面 -> Run workflow):
|
||
# mode 构建模式:beta(测试)或 run(正式)
|
||
# ref 构建来源分支/tag/commit(留空 = 默认分支)
|
||
# sign 是否使用 SignPath 签名
|
||
# 无 version 输入:base 自动读 package.json(版本单一事实源,消除本地/CI 版本双轨)。
|
||
# BUILD ID = GitHub Run Number(严格递增,无分钟级冲突),
|
||
# 最终版本号 = {base}-{buildId}(如 1.2.0-12),tag = v{base}-{buildId}。
|
||
#
|
||
# 发布行为:
|
||
# - beta:创建 GitHub prerelease(不占用 "Latest" 位)
|
||
# - run :创建正式 release
|
||
# - Release 标题命名(仅展示名,tag/真实版本号不变):run → "{base}"(如 1.2.1),beta → "BETA {base}"(如 BETA 1.2.1)
|
||
# - Release 正文为中文:版本信息(当前版本 / 编译状态 / 构建来源 commit)+ 提交记录(默认折叠)
|
||
# - 上传产物:koring-launcher-{base}-{buildId}-setup.exe + latest.yml(electron-updater 更新清单)
|
||
# - 构建元数据(commit / buildId)写入 src/lib/buildInfo.ts,打包进渲染层供 UI 显示
|
||
#
|
||
# Secrets:
|
||
# SIGNPATH_API_TOKEN SignPath API Token(必填;放在 Environment "BUILDER" 的环境 Secrets 中)
|
||
# SIGNPATH_ARTIFACT_CONFIG_SLUG 产物配置 slug(项目只有一个配置时可留空;仓库级 Secret)
|
||
#
|
||
# 组织 ID / slug 非密钥,直接写在下方 env(SignPath 后台确认值):
|
||
# OrganizationId 31ecd033-d59e-492b-a70b-b00a54bbc7c2
|
||
# ProjectSlug Koring_Launcher
|
||
# SigningPolicySlug Koring_Launcher_Dev_builder
|
||
#
|
||
# ⚠️ 签名策略说明:
|
||
# - 审批流程:SignPath 后台已关闭人工审批(自动批准),CI 可全自动。
|
||
# - 证书:当前策略为测试证书,用户机器默认不信任(SmartScreen / 杀软警告),
|
||
# 正式对外发布需生产证书(OV/EV)+ 对应生产签名策略,届时只换 SIGNPATH_SIGNING_POLICY_SLUG。
|
||
#
|
||
# ⚠️ 版本号注意(electron-updater 语义):
|
||
# - {base}-{buildId} 属于 semver prerelease;electron-updater 默认 allowPrerelease=false 会跳过带
|
||
# prerelease 后缀的新版本,客户端必须在 electron/updater.ts 设置 autoUpdater.allowPrerelease=true
|
||
# (已落地),否则如 v1.2.1-4 永远检测不到 v1.2.1-5。
|
||
# - 开启后:已安装同格式版本的用户可正常收到更高 buildId 的更新(buildId 数值比较)。
|
||
# - 若未来发布不带 buildId 的稳定版本(如 1.2.0),稳定版用户不会自动升级到带 buildId 的构建。
|
||
# - 切换 BUILD ID 方案(时间 ID → Run Number)时,旧格式数值更大(2608271921 > 12),
|
||
# 老用户不会自动升级 —— 切换时应同时提升 base(如 1.3.0-12 > 1.2.0-2608271921)。
|
||
|
||
name: Koring Launcher Builder
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
mode:
|
||
description: '构建模式:beta(测试)/ run(正式)'
|
||
required: true
|
||
type: choice
|
||
options:
|
||
- beta
|
||
- run
|
||
ref:
|
||
description: '构建来源分支 / tag / commit(留空 = 默认分支)'
|
||
required: false
|
||
default: ''
|
||
sign:
|
||
description: '是否使用 SignPath 签名(配额不足时自动跳过)'
|
||
required: true
|
||
type: boolean
|
||
default: true
|
||
|
||
permissions:
|
||
contents: write
|
||
|
||
jobs:
|
||
build-sign-publish:
|
||
runs-on: windows-latest
|
||
# 声明使用 Environment "BUILDER",才能读取其中的环境 Secret SIGNPATH_API_TOKEN
|
||
environment: BUILDER
|
||
env:
|
||
# 勾选 sign 才注入 token 走 SignPath 签名;不勾选则 token 为空,模块自动跳过签名
|
||
SIGNPATH_API_TOKEN: ${{ inputs.sign && secrets.SIGNPATH_API_TOKEN || '' }}
|
||
SIGNPATH_ORG_ID: 31ecd033-d59e-492b-a70b-b00a54bbc7c2
|
||
SIGNPATH_PROJECT_SLUG: Koring_Launcher
|
||
SIGNPATH_SIGNING_POLICY_SLUG: Koring_Launcher_Dev_builder
|
||
SIGNPATH_ARTIFACT_CONFIG_SLUG: ${{ secrets.SIGNPATH_ARTIFACT_CONFIG_SLUG }}
|
||
# 内部测试阶段:SignPath 年度配额(约 500MB)耗尽时跳过签名、照常发布(产物未签名)。
|
||
# ⚠️ 正式发布请删除此行并升级 SignPath 套餐(同时建议 SIGNPATH_ONLY_INSTALLER=false 全量签名)。
|
||
SIGNPATH_SKIP_ON_QUOTA: 'true'
|
||
# Electron 二进制 / electron-builder 辅助工具下载源:
|
||
# GitHub release-assets.githubusercontent.com 偶发 TLS 断连(本次 CI 即失败于此),
|
||
# 统一走 npmmirror 镜像更稳(对 pnpm install 的 electron postinstall 同样生效)。
|
||
ELECTRON_MIRROR: https://npmmirror.com/mirrors/electron/
|
||
ELECTRON_BUILDER_BINARIES_MIRROR: https://npmmirror.com/mirrors/electron-builder-binaries/
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
# 需要完整历史:生成中文提交记录(自上个 release tag 以来)
|
||
fetch-depth: 0
|
||
# 构建来源:默认默认分支,可指定分支/tag/commit
|
||
ref: ${{ inputs.ref || '' }}
|
||
|
||
- uses: pnpm/action-setup@v4
|
||
with:
|
||
version: 11.7.0
|
||
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: 22
|
||
cache: pnpm
|
||
|
||
- name: Install dependencies
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
# BUILD ID = GitHub Run Number(严格递增,无分钟级冲突)
|
||
# base 自动读 package.json(版本单一事实源)
|
||
# 版本格式(数字标识在 allowPrerelease 的通道逻辑中会被当"自定义频道",但正式版用户
|
||
# allowPrerelease=false,走 /releases/latest(按 GitHub 的 prerelease 标记而非 semver):
|
||
# 只要发布时不加 --prerelease,{base}-{buildId} 就是最新正式版,可正常识别):
|
||
# beta → {base}-beta.{buildId}(如 1.2.1-beta.13,频道 beta)
|
||
# run → {base}-{buildId}(如 1.2.1-13,带构建尾号)
|
||
- name: Generate BUILD ID & set version
|
||
id: version
|
||
shell: pwsh
|
||
run: |
|
||
$buildId = "$env:GITHUB_RUN_NUMBER"
|
||
$base = node scripts/version.js get
|
||
if ("${{ inputs.mode }}" -eq "beta") {
|
||
$full = node scripts/version.js build ci "beta.$buildId"
|
||
} else {
|
||
$full = node scripts/version.js build ci "$buildId"
|
||
}
|
||
"build_id=$buildId" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
||
"base=$base" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
||
"full=$full" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
||
Write-Host "BUILD ID: $buildId -> version: $full (base: $base)"
|
||
|
||
# 生成构建元数据(commit / 编译号)→ 打包进渲染层,UI 显示构建来源
|
||
- name: Generate build info
|
||
shell: pwsh
|
||
run: node scripts/gen-build-info.js ${{ inputs.mode }}
|
||
env:
|
||
BUILD_ID: ${{ steps.version.outputs.build_id }}
|
||
|
||
- name: Build renderer + main (${{ inputs.mode }})
|
||
shell: pwsh
|
||
run: |
|
||
if ("${{ inputs.mode }}" -eq "beta") {
|
||
pnpm build:beta
|
||
pnpm icon:beta
|
||
} else {
|
||
pnpm build:run
|
||
pnpm icon:run
|
||
}
|
||
|
||
# 关键步骤:win.sign 自定义签名(SignPath)在打包过程中逐个签名内部 exe 与 setup.exe
|
||
# 失败重试 1 次:Electron 二进制下载偶发 TLS 断连,重试只补下载缺失部分(已成功的 zip 会进缓存)
|
||
- name: Package & sign (SignPath)
|
||
shell: pwsh
|
||
run: |
|
||
for ($attempt = 1; $attempt -le 2; $attempt++) {
|
||
pnpm exec electron-builder --win --publish never
|
||
if ($LASTEXITCODE -eq 0) { break }
|
||
Write-Host "electron-builder 打包失败(第 $attempt 次,exit=$LASTEXITCODE),5 秒后重试..."
|
||
if ($attempt -eq 2) { exit $LASTEXITCODE }
|
||
Start-Sleep -Seconds 5
|
||
}
|
||
|
||
- name: Generate Chinese release notes
|
||
shell: pwsh
|
||
run: |
|
||
./scripts/release-notes.ps1 `
|
||
-BaseVersion "${{ steps.version.outputs.base }}" `
|
||
-FullVersion "${{ steps.version.outputs.full }}" `
|
||
-Mode "${{ inputs.mode }}" `
|
||
-SigningStatus "${{ inputs.sign && '已签名' || '未签名' }}" `
|
||
-Commit "${{ github.sha }}" `
|
||
-OutputPath release-notes.md
|
||
|
||
- name: Publish GitHub Release
|
||
shell: pwsh
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
$tag = "v${{ steps.version.outputs.full }}"
|
||
# Release 标题命名(仅展示名;tag / 真实版本号是 {base}-beta.{id} 或 {base}-{id}):
|
||
# 正式/预览版 → "1.2.5-13"(带构建尾号);测试版 → "BETA 1.2.5-beta.13"(带 Run Num)
|
||
$title = if ("${{ inputs.mode }}" -eq "beta") { "BETA ${{ steps.version.outputs.full }}" } else { "${{ steps.version.outputs.full }}" }
|
||
|
||
# 资产列表(beta 额外上传 latest-beta.yml:GitHub provider 频道取件(latest-beta)不再 404 回退)
|
||
$assets = @(
|
||
"dist-electron/koring-launcher-${{ steps.version.outputs.full }}-setup.exe",
|
||
"dist-electron/latest.yml",
|
||
"release-notes.md"
|
||
)
|
||
if ("${{ inputs.mode }}" -eq "beta") {
|
||
Copy-Item "dist-electron/latest.yml" "dist-electron/latest-beta.yml" -Force
|
||
$assets += "dist-electron/latest-beta.yml"
|
||
}
|
||
|
||
# 上传前校验资产存在(避免 gh 对缺失文件的模糊报错)
|
||
foreach ($a in $assets) {
|
||
if (-not (Test-Path -LiteralPath $a)) {
|
||
Write-Error "资产不存在: $a"
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
# 参数数组统一 splat:--prerelease 仅在 beta 追加;
|
||
# 不能传空串占位(gh 会把位置参数当资产 glob,空串 → "no matches found for" 报错)
|
||
$ghArgs = @($tag) + $assets
|
||
$ghArgs += @("--title", $title, "--notes-file", "release-notes.md")
|
||
if ("${{ inputs.mode }}" -eq "beta") {
|
||
$ghArgs += "--prerelease"
|
||
}
|
||
gh release create @ghArgs
|