168 lines
7.1 KiB
PowerShell
168 lines
7.1 KiB
PowerShell
# ============================================================
|
||
# Thing 构建发布脚本(目标:自建 Gitea release)
|
||
#
|
||
# 用法:
|
||
# .\scripts\release.ps1 -Version 0.2.0 # 同步版本号 + 构建 + 发布
|
||
# .\scripts\release.ps1 -Version 0.2.0 -SkipBuild # 复用现有构建产物,直接发布
|
||
# .\scripts\release.ps1 -Version 0.2.0 -SkipPush # 只构建+整理产物,不上传
|
||
#
|
||
# 发布产物(上传到 https://gitea.atie.fun/LFeng/Thing 的 v{Version} release):
|
||
# thing_{v}_x64.exe 便携免安装版(无内核)
|
||
# thing_{v}_x64.msi 安装版 MSI(去掉 tauri 默认的 _en-US 后缀)
|
||
# thing_{v}_x64-setup.exe 安装版 NSIS
|
||
# thing-hk_{v}.zip ThingHK 硬件监控内核(mihomo 继续走代理模块内置的 GitHub 下载)
|
||
#
|
||
# 前提:
|
||
# - Gitea token 已配置为环境变量 GITEA_TOKEN(-SkipPush 时不需要)
|
||
# - 可选 -NotesPath 指定 release notes 文件(Markdown 文本),
|
||
# 缺省时使用 scripts/release-notes.md(若存在),否则用简单占位文本
|
||
# ============================================================
|
||
|
||
param(
|
||
[string]$Version = '',
|
||
[switch]$SkipBuild,
|
||
[switch]$SkipPush,
|
||
[string]$NotesPath = ''
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
$Root = Split-Path -Parent $PSScriptRoot
|
||
$TargetDir = Join-Path $Root 'src-tauri\target\release'
|
||
$BundleDir = Join-Path $TargetDir 'bundle'
|
||
$RepoOwner = 'LFeng'
|
||
$RepoName = 'Thing'
|
||
$ApiBase = 'https://gitea.atie.fun/api/v1'
|
||
$Product = 'thing'
|
||
|
||
function Write-Step([string]$msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
|
||
|
||
# ---------- 0. 版本号 ----------
|
||
if ([string]::IsNullOrWhiteSpace($Version)) {
|
||
$conf = Get-Content (Join-Path $Root 'src-tauri\tauri.conf.json') -Raw | ConvertFrom-Json
|
||
$Version = $conf.version
|
||
Write-Step "未指定 -Version,沿用现有版本 $Version"
|
||
}
|
||
# 校验 X.Y.Z 格式
|
||
if ($Version -notmatch '^\d+\.\d+\.\d+$') {
|
||
throw "版本号格式错误(应为 X.Y.Z):$Version"
|
||
}
|
||
Write-Step "发布版本:v$Version"
|
||
|
||
# ---------- 1. 同步版本号到三处 ----------
|
||
$tauriConf = Join-Path $Root 'src-tauri\tauri.conf.json'
|
||
$cargoToml = Join-Path $Root 'src-tauri\Cargo.toml'
|
||
$pkgJson = Join-Path $Root 'package.json'
|
||
|
||
# UTF-8 安全读写:`Get-Content` 默认按系统 ANSI(如 GBK) 解码,会把本就含中文/乱码的文件二次编码损坏(曾导致
|
||
# Cargo.toml 的 keyring 依赖行被弄丢)。这里统一用显式 UTF-8 无 BOM 读写,保证逐字节稳定往返。
|
||
function Set-Utf8Version([string]$Path, [string]$Pattern, [string]$NewVersion) {
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||
$content = [System.IO.File]::ReadAllText($Path, $utf8NoBom)
|
||
$content = $content -replace $Pattern, "`${1}$NewVersion`${2}"
|
||
[System.IO.File]::WriteAllText($Path, $content, $utf8NoBom)
|
||
}
|
||
|
||
Set-Utf8Version -Path $tauriConf -Pattern '("version"\s*:\s*")[^"]*(")' -NewVersion $Version
|
||
Set-Utf8Version -Path $cargoToml -Pattern '(?m)^(version\s*=\s*")[^"]*(")' -NewVersion $Version
|
||
Set-Utf8Version -Path $pkgJson -Pattern '("version"\s*:\s*")[^"]*(")' -NewVersion $Version
|
||
Write-Step "版本号已同步:tauri.conf.json / Cargo.toml / package.json"
|
||
|
||
# ---------- 2. 构建 ----------
|
||
if (-not $SkipBuild) {
|
||
Write-Step '开始构建(bun run tauri build)...'
|
||
Push-Location $Root
|
||
try { bun run tauri build }
|
||
finally { Pop-Location }
|
||
if ($LASTEXITCODE -ne 0) { throw 'tauri build 失败' }
|
||
} else {
|
||
Write-Step '跳过构建,复用现有产物'
|
||
}
|
||
|
||
# ---------- 3. 整理产物 ----------
|
||
# 版本号此时已解析,再确定暂存目录
|
||
$StageDir = Join-Path $Root "release_stage\$Version"
|
||
New-Item -ItemType Directory -Force -Path $StageDir | Out-Null
|
||
|
||
$exeSrc = Join-Path $TargetDir "$Product.exe"
|
||
$msiSrc = Join-Path $BundleDir "msi\${Product}_${Version}_x64_en-US.msi"
|
||
$nsisSrc = Join-Path $BundleDir "nsis\${Product}_${Version}_x64-setup.exe"
|
||
$hkSrc = Join-Path $Root 'src-tauri\binaries\ThingHK.exe'
|
||
|
||
$exeOut = Join-Path $StageDir "${Product}_${Version}_x64.exe"
|
||
$msiOut = Join-Path $StageDir "${Product}_${Version}_x64.msi"
|
||
$nsisOut = Join-Path $StageDir "${Product}_${Version}_x64-setup.exe"
|
||
$hkZip = Join-Path $StageDir "thing-hk_${Version}.zip"
|
||
|
||
if (Test-Path $exeSrc) { Copy-Item $exeSrc $exeOut } else { Write-Warning "缺少便携版:$exeSrc" }
|
||
if (Test-Path $msiSrc) { Copy-Item $msiSrc $msiOut } else { Write-Warning "缺少 MSI(已跳过重命名):$msiSrc" }
|
||
if (Test-Path $nsisSrc) { Copy-Item $nsisSrc $nsisOut } else { Write-Warning "缺少 NSIS:$nsisSrc" }
|
||
|
||
if (Test-Path $hkSrc) {
|
||
$tmp = Join-Path $env:TEMP "thinghk_$([guid]::NewGuid().ToString('N'))"
|
||
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
|
||
Copy-Item $hkSrc (Join-Path $tmp 'ThingHK.exe')
|
||
Compress-Archive -Path (Join-Path $tmp 'ThingHK.exe') -DestinationPath $hkZip -Force
|
||
Remove-Item -Recurse -Force $tmp
|
||
Write-Step "ThingHK 内核包:$hkZip"
|
||
} else {
|
||
Write-Warning "缺少 ThingHK.exe:$hkSrc"
|
||
}
|
||
|
||
Write-Step "产物已整理到:$StageDir"
|
||
Get-ChildItem $StageDir | Select-Object Name, @{n='Size(MB)';e={[math]::Round($_.Length/1MB,1)}} | Format-Table -AutoSize
|
||
|
||
# ---------- 4. 上传到 Gitea ----------
|
||
if ($SkipPush) {
|
||
Write-Step '已跳过上传(-SkipPush)'
|
||
exit 0
|
||
}
|
||
|
||
$token = $env:GITEA_TOKEN
|
||
if ([string]::IsNullOrWhiteSpace($token)) {
|
||
throw '未设置环境变量 GITEA_TOKEN,无法发布到 Gitea(或使用 -SkipPush 跳过上传)'
|
||
}
|
||
$auth = @{ Authorization = "token $token" }
|
||
|
||
# 4.1 release notes
|
||
if (-not [string]::IsNullOrWhiteSpace($NotesPath)) {
|
||
$body = Get-Content $NotesPath -Raw
|
||
} elseif (Test-Path (Join-Path $PSScriptRoot 'release-notes.md')) {
|
||
$body = Get-Content (Join-Path $PSScriptRoot 'release-notes.md') -Raw
|
||
} else {
|
||
$body = "Thing v$Version"
|
||
}
|
||
|
||
# 4.2 创建 release(已存在同名 tag 则复用)
|
||
Write-Step "创建 release v$Version ..."
|
||
$releaseUrl = "$ApiBase/repos/$RepoOwner/$RepoName/releases"
|
||
$releasePayload = @{
|
||
tag_name = "v$Version"
|
||
name = "Thing v$Version"
|
||
body = $body
|
||
draft = $false
|
||
prerelease = $false
|
||
} | ConvertTo-Json
|
||
|
||
try {
|
||
$release = Invoke-RestMethod -Method Post -Uri $releaseUrl -Headers $auth -ContentType 'application/json' -Body $releasePayload
|
||
} catch {
|
||
# tag 已存在:尝试用该 tag 查找现有 release,后续资产上传会追加
|
||
Write-Warning "创建 release 失败,尝试复用已有 release:$_"
|
||
$release = Invoke-RestMethod -Method Get -Uri "$releaseUrl/tags/v$Version" -Headers $auth
|
||
}
|
||
$releaseId = $release.id
|
||
Write-Step "release id=$releaseId"
|
||
|
||
# 4.3 逐个上传资产
|
||
$assets = @($exeOut, $msiOut, $nsisOut, $hkZip) | Where-Object { Test-Path $_ }
|
||
foreach ($file in $assets) {
|
||
$name = Split-Path $file -Leaf
|
||
Write-Step "上传 $name ..."
|
||
$assetUrl = "$releaseUrl/$releaseId/assets?name=$([uri]::EscapeDataString($name))"
|
||
$resp = Invoke-RestMethod -Method Post -Uri $assetUrl -Headers $auth -ContentType 'application/octet-stream' -InFile $file
|
||
Write-Host " -> $($resp.browser_download_url)" -ForegroundColor Green
|
||
}
|
||
|
||
Write-Step "发布完成:https://gitea.atie.fun/$RepoOwner/$RepoName/releases/tag/v$Version"
|