Skip to content

tauri-build-windows-official #7

tauri-build-windows-official

tauri-build-windows-official #7

name: tauri-build-windows-official
on:
workflow_dispatch:
inputs:
env_name:
description: "Frontend build mode (development/production/test)"
required: false
default: "production"
jobs:
build:
# Windows 专用构建 Job:
# - 固定运行在 GitHub-hosted Windows Server 2025 Runner 上
# - 不适用于 macOS / Linux 等其他平台
# 如需支持多平台,请为不同平台创建独立的 workflow 或 job
runs-on: windows-2025
permissions:
contents: write
env:
# 前端构建参数
# build.cjs reads ENV_NAME; default production
ENV_NAME: ${{ inputs.env_name || 'production' }}
# App config values
APP_SERVER_BASE_URL: ${{ secrets.APP_SERVER_BASE_URL }}
APP_SERVER_VERSION: ${{ secrets.APP_SERVER_VERSION }}
APP_SERVER_SECRET_KEY: ${{ secrets.APP_SERVER_SECRET_KEY }}
APP_UPDATER_CHECK_URL: ${{ secrets.APP_UPDATER_CHECK_URL }}
APP_UPDATER_LATEST_JSON_URL: ${{ secrets.APP_UPDATER_LATEST_JSON_URL }}
APP_RUNTIME_LATEST_JSON_URL: ${{ secrets.APP_RUNTIME_LATEST_JSON_URL }}
APP_UPDATER_TEMP_DIR: ${{ secrets.APP_UPDATER_TEMP_DIR }}
APP_WEBVIEW_DOWNLOAD_URL: ${{ secrets.APP_WEBVIEW_DOWNLOAD_URL }}
# Release 相关上下文
# - tag push 时 github.ref_name 即为 vX.Y.Z
# - workflow_dispatch 时不会创建 release,仅用于手动构建
RELEASE_TAG: ${{ github.ref_name }}
# R2 相关配置(若未配置对应 Secret,则相关功能会被跳过或报错)
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
R2_BUCKET: ${{ secrets.R2_BUCKET }}
R2_PUBLIC_BASE_URL: ${{ secrets.R2_PUBLIC_BASE_URL }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Ensure AWS CLI
shell: powershell
run: |
$ErrorActionPreference = "Stop"
if (Get-Command aws -ErrorAction SilentlyContinue) {
aws --version
exit 0
}
$msiPath = Join-Path $env:RUNNER_TEMP "AWSCLIV2.msi"
Invoke-WebRequest "https://awscli.amazonaws.com/AWSCLIV2.msi" -OutFile $msiPath
Start-Process msiexec.exe -Wait -ArgumentList "/i `"$msiPath`" /qn"
@(
"C:\Program Files\Amazon\AWSCLIV2",
"C:\Program Files\Amazon\AWSCLIV2\bin"
) | ForEach-Object {
if (Test-Path $_) {
Add-Content -Path $env:GITHUB_PATH -Value $_
}
}
$awsExe = Get-Command aws -ErrorAction SilentlyContinue
if (-not $awsExe) {
$awsInstalled = Get-ChildItem "C:\Program Files\Amazon" -Filter aws.exe -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $awsInstalled) {
Write-Error "AWS CLI installation completed, but aws.exe was not found."
}
& $awsInstalled.FullName --version
exit 0
}
aws --version
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Prepare app config
shell: powershell
run: |
Copy-Item "src-tauri/config.example.toml" "src-tauri/config.production.toml" -Force
$configPath = "src-tauri/config.production.toml"
$content = Get-Content $configPath -Raw
function Set-ConfigValue {
param(
[string]$Pattern,
[string]$Value
)
if ([string]::IsNullOrWhiteSpace($Value)) {
return
}
$escapedValue = $Value.Replace('\', '\\').Replace('"', '\"')
$script:content = [regex]::Replace(
$script:content,
$Pattern,
('$1"{0}"' -f $escapedValue),
[System.Text.RegularExpressions.RegexOptions]::Multiline
)
}
Set-ConfigValue '^(base_url\s*=\s*)".*"$' "${{ env.APP_SERVER_BASE_URL }}"
Set-ConfigValue '^(version\s*=\s*)".*"$' "${{ env.APP_SERVER_VERSION }}"
Set-ConfigValue '^(secret_key\s*=\s*)".*"$' "${{ env.APP_SERVER_SECRET_KEY }}"
Set-ConfigValue '^(check_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_CHECK_URL }}"
Set-ConfigValue '^(latest_json_url\s*=\s*)".*"$' "${{ env.APP_UPDATER_LATEST_JSON_URL }}"
Set-ConfigValue '^(runtime_latest_json_url\s*=\s*)".*"$' "${{ env.APP_RUNTIME_LATEST_JSON_URL }}"
Set-ConfigValue '^(updater_temp_dir\s*=\s*)".*"$' "${{ env.APP_UPDATER_TEMP_DIR }}"
Set-ConfigValue '^(downlaod_url\s*=\s*)".*"$' "${{ env.APP_WEBVIEW_DOWNLOAD_URL }}"
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
$resolvedConfigPath = (Resolve-Path $configPath).Path
[System.IO.File]::WriteAllText($resolvedConfigPath, $content, $utf8NoBom)
# 在 CI 构建期间使用 fixed 版本的 Tauri 配置
# 先将 src-tauri/tauri.conf.fixed.json 覆盖为 src-tauri/tauri.conf.json,
# 然后再由 prepare-version.mjs 统一写入最终版本号,确保参与打包的配置版本正确。
- name: Use fixed Tauri config
shell: powershell
run: |
Copy-Item "src-tauri/tauri.conf.fixed.json" "src-tauri/tauri.conf.json" -Force
- name: Prepare version from tag
# For release events, GITHUB_REF_NAME is usually "vX.Y.Z" as well.
run: node deploy/prepare-version.mjs
# Build and bundle the Tauri app.
# It will run `beforeBuildCommand` from `src-tauri/tauri.conf.json` (node build.cjs -> pnpm build:<env>)
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
# 优先使用 GT_TOKEN;未配置时回退到 GitHub 自动注入的 token
GITHUB_TOKEN: ${{ secrets.GT_TOKEN || github.token }}
# Optional: enable updater signing / release signing if you configure them later
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
with:
projectPath: .
# 与本地一致,使用 production feature 进行构建
args: --features production
- name: Generate latest.json
run: node deploy/generate-latest-json.mjs
- name: Publish GitHub release assets
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ secrets.GT_TOKEN || github.token }}
GH_REPO: ${{ github.repository }}
run: node deploy/publish-github-release.mjs
- name: Upload installer to R2 storage
# tag push 时上传到 R2
if: startsWith(github.ref, 'refs/tags/')
shell: powershell
run: |
$ErrorActionPreference = "Stop"
$TAG = "${{ env.RELEASE_TAG }}"
# 去掉前缀 v,得到纯版本号,如 0.1.0
$VERSION = $TAG.TrimStart('v')
# 找到 NSIS 安装包
$installer = Get-ChildItem "src-tauri/target/release/bundle/nsis" -Filter *.exe | Select-Object -First 1
if (-not $installer) {
Write-Error "NSIS installer not found under src-tauri/target/release/bundle/nsis"
}
# 使用 AWS CLI 上传到 R2(唯一方式)
if (-not (Get-Command aws -ErrorAction SilentlyContinue)) {
Write-Error "aws CLI not found. Please install AWS CLI v2 and ensure 'aws' is in PATH."
}
$accountId = "${{ env.R2_ACCOUNT_ID }}"
$bucket = "${{ env.R2_BUCKET }}"
$endpoint = "https://${accountId}.r2.cloudflarestorage.com"
$dest = "s3://${bucket}/${VERSION}/simprint_setup.exe"
$env:AWS_ACCESS_KEY_ID = "${{ env.R2_ACCESS_KEY_ID }}"
$env:AWS_SECRET_ACCESS_KEY = "${{ env.R2_SECRET_ACCESS_KEY }}"
$env:AWS_EC2_METADATA_DISABLED = "true"
Write-Host "Uploading $($installer.FullName) to R2: $dest"
aws s3 cp $installer.FullName $dest --endpoint-url $endpoint --region auto
- name: Upload latest.json to R2 root
# tag push 时上传到 R2
if: startsWith(github.ref, 'refs/tags/')
shell: powershell
run: |
$ErrorActionPreference = "Stop"
if (-not (Get-Command aws -ErrorAction SilentlyContinue)) {
Write-Error "aws CLI not found. Please install AWS CLI v2 and ensure 'aws' is in PATH."
}
$accountId = "${{ env.R2_ACCOUNT_ID }}"
$bucket = "${{ env.R2_BUCKET }}"
$endpoint = "https://${accountId}.r2.cloudflarestorage.com"
$dest = "s3://${bucket}/latest.json"
$env:AWS_ACCESS_KEY_ID = "${{ env.R2_ACCESS_KEY_ID }}"
$env:AWS_SECRET_ACCESS_KEY = "${{ env.R2_SECRET_ACCESS_KEY }}"
$env:AWS_EC2_METADATA_DISABLED = "true"
Write-Host "Uploading latest.json to R2 root: $dest"
aws s3 cp "latest.json" $dest --endpoint-url $endpoint --region auto
- name: Upload latest.json artifact (manual runs)
if: github.event_name == 'workflow_dispatch' && hashFiles('latest.json') != ''
uses: actions/upload-artifact@v4
with:
name: latest-json
path: latest.json
- name: Publish version metadata
if: startsWith(github.ref, 'refs/tags/')
env:
VERSION_API_URL: ${{ secrets.VERSION_API_URL }}
VERSION_API_KEY: ${{ secrets.VERSION_API_KEY }}
RELEASE_TAG: ${{ env.RELEASE_TAG }}
run: node deploy/publish-version.mjs