Skip to content

修复action

修复action #51

Workflow file for this run

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