feat: auto-update, тесты и CI/CD
Some checks failed
CI / Typecheck + Tests (push) Has been cancelled
CI / Build (Windows) (push) Has been cancelled

Полная автоматизация релизного цикла.

== Auto-update (electron-updater) ==
- src/main/updater.ts — обёртка над autoUpdater с дискриминированным
  UpdaterStatus union и broadcast через IPC. autoDownload=false,
  пользователь сам жмёт «Скачать». allowDowngrade=false. Проверка
  каждые 6 часов, первая через 5с после старта.
- В dev-режиме (app.isPackaged=false) статус сразу становится
  'unsupported' с пояснением — никаких exceptions из updater'а.
- build.publish в package.json: provider=generic, url указывает на
  Gitea release assets конкретной версии.
- src/main/ipc.ts: 4 новых канала — status/check/download/install.
- src/preload: API window.api.updater* + onUpdaterStatus.
- src/renderer/src/components/UpdaterCard.tsx: HUD-карточка в Settings
  с состояниями idle/checking/available/downloading/downloaded/error,
  прогресс-бар с скоростью в МБ/с.

== Тесты (vitest) ==
- vitest.config.ts с алиасами @shared / @renderer
- 23 теста, все зелёные:
  * format.test.ts — formatCountdown, formatInterval (8 cases)
  * vdf.test.ts — parseVdf / stringifyVdf / round-trip (11 cases)
  * types.test.ts — DEFAULT_SETTINGS, SAMPLE_EXERCISES sanity (4)
- npm scripts: test (watch), test:run (CI)

== CI/CD (Gitea Actions) ==
- .gitea/workflows/ci.yml — на push/PR: typecheck + тесты + smoke-сборка
- .gitea/workflows/release.yml — на тег v*.*.*: сборка NSIS + Gitea release

== Локальный релизный скрипт ==
- scripts/release.ps1 — один скрипт от бампа версии до публикации
  через Gitea API (params: -Bump patch/minor/major, -Version, -DryRun)
- npm run release — обёртка
- RELEASING.md — полная инструкция

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
AnRil
2026-05-16 20:32:59 +07:00
parent 757352e447
commit 92e15e69a3
16 changed files with 1149 additions and 3 deletions

View File

@@ -0,0 +1,75 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
name: Build installer + publish release
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Verify version matches tag
shell: pwsh
run: |
$tag = "${{ gitea.ref_name }}"
$expected = $tag.TrimStart('v')
$actual = (Get-Content package.json | ConvertFrom-Json).version
if ($expected -ne $actual) {
Write-Error "Tag $tag does not match package.json version $actual"
exit 1
}
Write-Host "Version match: $actual"
- name: Typecheck
run: npm run typecheck
- name: Run unit tests
run: npm run test:run
- name: Build NSIS installer
run: npm run dist
env:
# electron-builder uses this when --publish flag is set; we publish
# to a Gitea release manually below to avoid hard-coupling.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Generate release notes from commits
id: notes
shell: pwsh
run: |
$tag = "${{ gitea.ref_name }}"
$prev = git describe --tags --abbrev=0 "$tag^" 2>$null
if ($prev) {
$log = git log --pretty=format:"- %s" "$prev..$tag"
} else {
$log = git log --pretty=format:"- %s" "$tag"
}
$notes = "### Изменения`n`n$log`n`n---`n`nУстановщик ниже — запустить и следовать мастеру. Если приложение уже стояло — обновится поверх с сохранением настроек."
$encoded = $notes -replace "`r?`n", "%0A"
"notes=$encoded" | Out-File -FilePath $env:GITEA_OUTPUT -Append
- name: Create Gitea release with artifacts
uses: akkuman/gitea-release-action@v1
with:
server_url: ${{ gitea.server_url }}
token: ${{ secrets.GITEA_TOKEN }}
name: 'Exercise Reminder ${{ gitea.ref_name }}'
body: ${{ steps.notes.outputs.notes }}
files: |
release/Exercise-Reminder-Setup-*.exe
release/Exercise-Reminder-Setup-*.exe.blockmap
release/latest.yml