prerelease.yml 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. name: Windows Prerelease
  2. # 推送到 prerelease 分支时,只打 Windows x64 内测安装包(NSIS + 便携版),
  3. # 发布为 GitHub prerelease(tag: prerelease)。
  4. # 不上传 latest.json,正式版自动更新通道不受影响。
  5. #
  6. # 首次启用(workflow 合入 main 之后):
  7. # git fetch origin
  8. # git push origin origin/main:prerelease
  9. # 之后把要内测的提交推进 prerelease 即可。
  10. on:
  11. push:
  12. branches:
  13. - prerelease
  14. workflow_dispatch:
  15. concurrency:
  16. group: windows-prerelease
  17. cancel-in-progress: true
  18. permissions:
  19. contents: write
  20. jobs:
  21. build-windows-prerelease:
  22. name: Build Windows x64 内测包
  23. runs-on: windows-latest
  24. steps:
  25. - name: Checkout
  26. uses: actions/checkout@v5
  27. - name: Install Rust stable
  28. uses: dtolnay/rust-toolchain@stable
  29. - name: Rust cache
  30. uses: Swatinem/rust-cache@v2
  31. with:
  32. workspaces: src-tauri
  33. shared-key: qmai-release
  34. add-job-id-key: false
  35. cache-on-failure: true
  36. - name: Install protoc (Windows)
  37. uses: arduino/setup-protoc@v3
  38. with:
  39. repo-token: ${{ secrets.GITHUB_TOKEN }}
  40. - name: Setup Node.js
  41. uses: actions/setup-node@v5
  42. with:
  43. node-version: 24
  44. cache: npm
  45. - name: Install frontend dependencies
  46. run: npm ci
  47. - name: Prepare release notes
  48. shell: bash
  49. run: |
  50. set -euo pipefail
  51. version="$(node -p "require('./package.json').version")"
  52. mkdir -p release-assets
  53. node scripts/release-notes.mjs "$version" --out release-assets/changelog.txt
  54. sha="$(echo "${GITHUB_SHA}" | cut -c1-7)"
  55. {
  56. echo "QMAI ${version} Windows 内测包"
  57. echo
  58. echo "- 平台:Windows x64(不含 macOS / Linux)"
  59. echo "- 提交:${GITHUB_SHA}"
  60. echo "- 短哈希:${sha}"
  61. echo "- 来源:\`${GITHUB_REF_NAME}\`"
  62. echo
  63. echo "本发布为内测,不会标记为 Latest,也不会写入正式版自动更新通道(latest.json)。"
  64. echo
  65. echo "## 更新说明"
  66. echo
  67. cat release-assets/changelog.txt
  68. } > release-assets/prerelease-notes.txt
  69. - name: Require Sentry sourcemap token
  70. env:
  71. SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
  72. shell: bash
  73. run: |
  74. if [ -z "${SENTRY_AUTH_TOKEN}" ]; then
  75. echo "SENTRY_AUTH_TOKEN is required to upload production sourcemaps." >&2
  76. echo "Create an org token (project:releases, org:read) at https://qmai-c5.sentry.io/settings/auth-tokens/" >&2
  77. echo "Then: gh secret set SENTRY_AUTH_TOKEN -R Mochocyang/QMAI" >&2
  78. exit 1
  79. fi
  80. - name: Build Tauri NSIS installer
  81. env:
  82. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  83. TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
  84. TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
  85. SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
  86. SENTRY_ORG: qmai-c5
  87. SENTRY_PROJECT: qmai
  88. run: npx tauri build --bundles nsis
  89. - name: Package Windows 内测 assets
  90. shell: pwsh
  91. run: |
  92. $ErrorActionPreference = "Stop"
  93. $version = node -p "require('./package.json').version"
  94. $sha = "${{ github.sha }}".Substring(0, 7)
  95. $assetDir = "release-assets"
  96. New-Item -ItemType Directory -Force -Path $assetDir | Out-Null
  97. $bundleDir = "src-tauri/target/release/bundle/nsis"
  98. $installer = Get-ChildItem $bundleDir -File -Filter "*.exe" |
  99. Sort-Object LastWriteTime -Descending |
  100. Select-Object -First 1
  101. if (-not $installer) {
  102. throw "未找到 Windows 安装包"
  103. }
  104. $installerName = "QMaiWrite_${version}_windows_X64_prerelease.exe"
  105. Copy-Item $installer.FullName (Join-Path $assetDir $installerName) -Force
  106. node scripts/build-portable.mjs
  107. $portableExe = "release-portable/QMaiWrite.exe"
  108. if (-not (Test-Path $portableExe)) {
  109. throw "便携版 EXE 未生成:$portableExe"
  110. }
  111. $portableName = "QMaiWrite_${version}_windows_X64_portable_prerelease.exe"
  112. Copy-Item $portableExe (Join-Path $assetDir $portableName) -Force
  113. Write-Host "sha=$sha"
  114. Get-ChildItem $assetDir | Format-Table Name, Length -AutoSize
  115. - name: Publish GitHub prerelease
  116. env:
  117. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  118. shell: bash
  119. run: |
  120. set -euo pipefail
  121. tag="prerelease"
  122. notes="release-assets/prerelease-notes.txt"
  123. version="$(node -p "require('./package.json').version")"
  124. sha="$(echo "${GITHUB_SHA}" | cut -c1-7)"
  125. title="QMAI ${version} 内测 (Windows ${sha})"
  126. if gh release view "$tag" >/dev/null 2>&1; then
  127. gh release delete "$tag" --yes --cleanup-tag
  128. fi
  129. shopt -s nullglob
  130. assets=(release-assets/QMaiWrite_*_prerelease.exe)
  131. if [ "${#assets[@]}" -eq 0 ]; then
  132. echo "未找到 Windows 内测安装包" >&2
  133. exit 1
  134. fi
  135. gh release create "$tag" \
  136. --title "$title" \
  137. --notes-file "$notes" \
  138. --prerelease \
  139. --latest=false \
  140. --target "${GITHUB_SHA}" \
  141. "${assets[@]}"
  142. - name: Upload workflow artifacts
  143. uses: actions/upload-artifact@v6
  144. with:
  145. name: qmai-windows-x64-prerelease
  146. path: |
  147. release-assets/QMaiWrite_*_prerelease.exe
  148. release-assets/prerelease-notes.txt
  149. if-no-files-found: error
  150. retention-days: 14