修复action #51
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| permissions: | |
| contents: write | |
| on: | |
| push: | |
| tags: | |
| - 'v*' # 推送形如 v1.0.1 的 tag 时触发 | |
| jobs: | |
| build-and-release: | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9 | |
| - name: Install deps | |
| run: pnpm install --frozen-lockfile | |
| - name: Preflight check for signing secrets | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ -z "${TAURI_SIGNING_PRIVATE_KEY:-}" ]]; then | |
| echo "::error::Missing TAURI_SIGNING_PRIVATE_KEY secret"; | |
| exit 1; | |
| fi | |
| if [[ -z "${TAURI_SIGNING_PRIVATE_KEY_PASSWORD:-}" ]]; then | |
| echo "::warning::TAURI_SIGNING_PRIVATE_KEY_PASSWORD is empty (that's OK if your key has no password)."; | |
| fi | |
| env: | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| - name: Prepare updater endpoints (merge env & GitHub) | |
| run: node scripts/prepare-updater-endpoints.cjs | |
| env: | |
| # 用户自定义的端点列表(可包含多个,用逗号分隔),来自仓库 Secrets | |
| UPDATER_ENDPOINTS: ${{ secrets.UPDATER_ENDPOINTS != '' && format('{0},{1}', secrets.UPDATER_ENDPOINTS, env.CHANNEL_UPDATER_ENDPOINT) || env.CHANNEL_UPDATER_ENDPOINT }} | |
| # 根据是否为预发布决定通道端点:pre 通道使用固定 tag `pre`,稳定通道使用 `latest` | |
| CHANNEL_UPDATER_ENDPOINT: ${{ contains(github.ref_name, '-') && format('https://github.com/{0}/releases/download/pre/latest.json', github.repository) || format('https://github.com/{0}/releases/latest/download/latest.json', github.repository) }} | |
| - name: Tauri Build & Release | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| # 将端点注入到构建中(与上一步一致)。如果用户配置了 Secrets.UPDATER_ENDPOINTS,会与通道端点合并。 | |
| UPDATER_ENDPOINTS: ${{ secrets.UPDATER_ENDPOINTS != '' && format('{0},{1}', secrets.UPDATER_ENDPOINTS, env.CHANNEL_UPDATER_ENDPOINT) || env.CHANNEL_UPDATER_ENDPOINT }} | |
| CHANNEL_UPDATER_ENDPOINT: ${{ contains(github.ref_name, '-') && format('https://github.com/{0}/releases/download/pre/latest.json', github.repository) || format('https://github.com/{0}/releases/latest/download/latest.json', github.repository) }} | |
| # 注入前端通道变量:pre/stable | |
| VITE_RELEASE_CHANNEL: ${{ contains(github.ref_name, '-') && 'pre' || 'stable' }} | |
| with: | |
| # 使用触发的 tag,避免额外创建 v__VERSION__ 的 tag/release | |
| tagName: ${{ github.ref_name }} | |
| releaseName: 'BPM Sniffer ${{ github.ref_name }}' | |
| releaseDraft: false | |
| prerelease: ${{ contains(github.ref_name, '-') }} | |
| includeUpdaterJson: true | |
| distPath: src-tauri/dist | |
| args: --bundles nsis,updater | |
| # 该 Action 会在发布中附带 latest.json(v2 插件使用), | |
| # 如需显式开关,可按官方文档添加 includeUpdaterJson/updaterJson 选项。 | |
| # 预发布同步:按安装包进行自包含同步(而非 updater zip) | |
| - name: 等待 Release 资产刷新 | |
| if: contains(github.ref_name, '-') | |
| shell: bash | |
| run: | | |
| # GitHub Release 资产上传后存在短暂延迟,这里稍作等待避免下载步骤立即失败 | |
| sleep 20 | |
| - name: 检查资产是否已经可见 | |
| if: contains(github.ref_name, '-') | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const tag = context.ref_name; | |
| const patterns = [ | |
| /latest\.json$/, | |
| /_x64-setup\.exe$/, | |
| /_x64-setup\.exe\.sig$/ | |
| ]; | |
| for (let attempt = 1; attempt <= 10; attempt++) { | |
| const { data: release } = await github.rest.repos.getReleaseByTag({ owner, repo, tag }); | |
| const assets = release.assets || []; | |
| const allFound = patterns.every((pattern) => assets.some((asset) => pattern.test(asset.name))); | |
| if (allFound) { | |
| core.info(`Release assets ready on attempt ${attempt}`); | |
| return; | |
| } | |
| if (attempt === 10) { | |
| core.setFailed(`Assets not ready after ${attempt} attempts.`); | |
| return; | |
| } | |
| core.info(`Assets missing on attempt ${attempt}, waiting 10s...`); | |
| await new Promise((resolve) => setTimeout(resolve, 10000)); | |
| } | |
| # 预发布:从“本次 tag 的 Release”下载 latest.json 到工作区 | |
| - name: Download latest.json from current release | |
| if: contains(github.ref_name, '-') | |
| uses: robinraju/release-downloader@v1 | |
| with: | |
| repository: ${{ github.repository }} | |
| tag: ${{ github.ref_name }} | |
| fileName: latest.json | |
| out-file-path: . | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download NSIS installer from current release | |
| if: contains(github.ref_name, '-') | |
| uses: robinraju/release-downloader@v1 | |
| with: | |
| repository: ${{ github.repository }} | |
| tag: ${{ github.ref_name }} | |
| fileName: "*_x64-setup.exe*" | |
| out-file-path: pre-assets | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download NSIS installer signature from current release | |
| if: contains(github.ref_name, '-') | |
| uses: robinraju/release-downloader@v1 | |
| with: | |
| repository: ${{ github.repository }} | |
| tag: ${{ github.ref_name }} | |
| fileName: "*_x64-setup.exe.sig*" | |
| out-file-path: pre-assets | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Repoint latest.json URLs to `pre` | |
| if: contains(github.ref_name, '-') | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sed -E -i 's#/releases/download/[^/]+/#/releases/download/pre/#g' latest.json | |
| - name: Cleanup assets on pre release | |
| if: contains(github.ref_name, '-') | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const tag = 'pre'; | |
| try { | |
| const { data: release } = await github.rest.repos.getReleaseByTag({ owner, repo, tag }); | |
| if (release.assets && release.assets.length) { | |
| for (const asset of release.assets) { | |
| try { | |
| await github.rest.repos.deleteReleaseAsset({ owner, repo, asset_id: asset.id }); | |
| } catch (e) { | |
| core.warning(`delete asset failed: ${asset.name} -> ${e.message}`); | |
| } | |
| } | |
| } | |
| } catch (e) { | |
| core.warning(`pre release not found or cannot be fetched: ${e.message}`); | |
| } | |
| - name: Sync pre-channel assets to tag `pre` | |
| if: contains(github.ref_name, '-') | |
| uses: softprops/action-gh-release@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: pre | |
| prerelease: true | |
| files: | | |
| latest.json | |
| pre-assets/*_x64-setup.exe | |
| pre-assets/*_x64-setup.exe.sig |