Gitea переехал с path-prefix (xn--90adajar8af4h.xn--p1ai/git/) на выделенный сабдомен (git.xn--90adajar8af4h.xn--p1ai). Старый URL теперь отдаёт чужое приложение и для git мёртв. - package.json: publish.url (канал авто-апдейта) -> новый хост - scripts/release.ps1, upload-release-assets.ps1: $giteaHost (API + release URL) - README, CHANGELOG, RELEASING.md, CLAUDE.md: ссылки на репозиторий/релизы Прим.: уже установленные копии (<=0.5.8) запекли старый URL в бинарник — их авто-апдейт нужно мигрировать отдельно (bridge-теги), правкой конфига это ретроактивно не лечится. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
174 lines
6.1 KiB
PowerShell
174 lines
6.1 KiB
PowerShell
<#
|
||
.SYNOPSIS
|
||
Локальный релиз: бамп версии -> коммит -> тег -> push -> сборка -> upload в Gitea.
|
||
|
||
.DESCRIPTION
|
||
Single-command release flow.
|
||
|
||
Каждый релиз публикует артефакты в ТРИ места:
|
||
1. Тег vX.Y.Z (исторический архив + changelog)
|
||
2. Тег update-channel (фиксированный URL для auto-updater)
|
||
3. Bridge-теги, указанные в -BridgeTags (для миграции пользователей со
|
||
старых версий, у которых запечён старый publish.url).
|
||
|
||
После того как все пользователи получили версию с новым (фиксированным)
|
||
publish.url, аргумент -BridgeTags можно перестать указывать.
|
||
|
||
.PARAMETER Bump
|
||
Какую часть semver инкрементировать: patch (по умолчанию), minor, major.
|
||
|
||
.PARAMETER Version
|
||
Точная версия (напр. "0.5.1"). Если задана, -Bump игнорируется.
|
||
|
||
.PARAMETER SkipBuild
|
||
Пропустить сборку (если уже собрано вручную, .exe лежит в release/).
|
||
|
||
.PARAMETER BridgeTags
|
||
Список старых тегов, в которые нужно ТАКЖЕ перезалить новые артефакты,
|
||
чтобы пользователи на этих версиях нашли апдейт. Например: v0.4.0,v0.5.0.
|
||
|
||
.PARAMETER DryRun
|
||
Показать что произойдёт, ничего не делая.
|
||
|
||
.EXAMPLE
|
||
pwsh scripts/release.ps1 -Bump patch
|
||
pwsh scripts/release.ps1 -Version 0.5.1 -BridgeTags v0.4.0,v0.5.0
|
||
|
||
.NOTES
|
||
Требует GITEA_TOKEN с правом write:repository.
|
||
Канал 'update-channel' должен существовать на Gitea (создаётся однократно).
|
||
#>
|
||
param(
|
||
[ValidateSet('patch', 'minor', 'major')]
|
||
[string]$Bump = 'patch',
|
||
[string]$Version,
|
||
[switch]$SkipBuild,
|
||
[string[]]$BridgeTags = @(),
|
||
[switch]$DryRun
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
$repoOwner = 'AnRil'
|
||
$repoName = 'laude'
|
||
$giteaHost = 'git.xn--90adajar8af4h.xn--p1ai'
|
||
$channelTag = 'update-channel'
|
||
|
||
# --- Pre-flight ----------------------------------------------------------
|
||
$root = Resolve-Path (Join-Path $PSScriptRoot '..')
|
||
Set-Location $root
|
||
|
||
if (-not $env:GITEA_TOKEN -and -not $DryRun) {
|
||
Write-Error 'GITEA_TOKEN not set.'
|
||
exit 1
|
||
}
|
||
|
||
$status = git status --porcelain
|
||
if ($status) {
|
||
Write-Error "Uncommitted changes. Commit or stash first."
|
||
exit 1
|
||
}
|
||
|
||
$branch = git rev-parse --abbrev-ref HEAD
|
||
if ($branch -ne 'main') {
|
||
Write-Warning "Branch is $branch, not main. Press Enter to continue or Ctrl+C to cancel."
|
||
Read-Host
|
||
}
|
||
|
||
# --- Compute next version ------------------------------------------------
|
||
$pkg = Get-Content package.json | ConvertFrom-Json
|
||
$current = $pkg.version
|
||
|
||
if ($Version) {
|
||
$next = $Version
|
||
} else {
|
||
$parts = $current.Split('.')
|
||
$major = [int]$parts[0]; $minor = [int]$parts[1]; $patch = [int]$parts[2]
|
||
switch ($Bump) {
|
||
'major' { $major++; $minor = 0; $patch = 0 }
|
||
'minor' { $minor++; $patch = 0 }
|
||
'patch' { $patch++ }
|
||
}
|
||
$next = "$major.$minor.$patch"
|
||
}
|
||
|
||
$tag = "v$next"
|
||
Write-Host ""
|
||
Write-Host "Release plan" -ForegroundColor Cyan
|
||
Write-Host " current : v$current"
|
||
Write-Host " next : $tag"
|
||
Write-Host " publish into : $tag, $channelTag$(if ($BridgeTags) { ', ' + ($BridgeTags -join ', ') })"
|
||
Write-Host ""
|
||
|
||
if ($DryRun) {
|
||
Write-Host '(dry run - exiting)' -ForegroundColor Yellow
|
||
exit 0
|
||
}
|
||
|
||
# --- Bump package.json --------------------------------------------------
|
||
# IMPORTANT: read+write as UTF-8 WITHOUT BOM. PS5.1 defaults will (a) read the
|
||
# file as CP1251 and mangle non-ASCII chars like em-dash, and (b) write back
|
||
# with a BOM that breaks PostCSS / electron-builder reads of package.json.
|
||
Write-Host "Bumping package.json to $next..." -ForegroundColor Cyan
|
||
$pkgPath = Join-Path $root 'package.json'
|
||
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
||
$pkgJson = [System.IO.File]::ReadAllText($pkgPath, $utf8NoBom)
|
||
$pkgJson = $pkgJson -replace "`"version`":\s*`"$current`"", "`"version`": `"$next`""
|
||
[System.IO.File]::WriteAllText($pkgPath, $pkgJson, $utf8NoBom)
|
||
|
||
git add package.json
|
||
git commit -m "chore(release): $tag"
|
||
|
||
# --- Quality gates ------------------------------------------------------
|
||
if (-not $SkipBuild) {
|
||
Write-Host "Typecheck..." -ForegroundColor Cyan
|
||
npm run typecheck
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
Write-Host "Tests..." -ForegroundColor Cyan
|
||
npm run test:run
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
|
||
Write-Host "Building installer..." -ForegroundColor Cyan
|
||
npm run dist
|
||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||
}
|
||
|
||
# --- Verify artifacts ---------------------------------------------------
|
||
$installer = Join-Path 'release' "Exercise-Reminder-Setup-$next.exe"
|
||
$blockmap = "$installer.blockmap"
|
||
$manifest = Join-Path 'release' 'latest.yml'
|
||
foreach ($f in @($installer, $blockmap, $manifest)) {
|
||
if (-not (Test-Path $f)) {
|
||
Write-Error "Artifact missing: $f"
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
# --- Tag + push ---------------------------------------------------------
|
||
Write-Host "Tagging $tag and pushing..." -ForegroundColor Cyan
|
||
git tag -a $tag -m "Release $tag"
|
||
git push origin main
|
||
git push origin $tag
|
||
|
||
# --- Upload to all target releases --------------------------------------
|
||
$uploadScript = Join-Path $PSScriptRoot 'upload-release-assets.ps1'
|
||
|
||
$targets = @($tag, $channelTag) + $BridgeTags
|
||
foreach ($target in $targets) {
|
||
Write-Host ""
|
||
Write-Host "==> Uploading $next artifacts into release '$target'" -ForegroundColor Cyan
|
||
& powershell -ExecutionPolicy Bypass -File $uploadScript -Tag $target -AssetVersion $next
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Error "Upload to '$target' failed (exit $LASTEXITCODE)"
|
||
exit $LASTEXITCODE
|
||
}
|
||
}
|
||
|
||
$releaseUrl = "https://$giteaHost/$repoOwner/$repoName/releases/tag/$tag"
|
||
Write-Host ""
|
||
Write-Host "Release published" -ForegroundColor Green
|
||
Write-Host " $releaseUrl"
|
||
Write-Host ""
|
||
Write-Host "Auto-updater will pick up the new version within ~1 hour on all installed copies."
|