Полная автоматизация релизного цикла. == 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>
7.3 KiB
Релиз и автообновления
Документ описывает три способа выпустить новую версию. Все опираются на
один и тот же артефакт — NSIS-инсталлятор Exercise-Reminder-Setup-X.Y.Z.exe,
который сам решает: устанавливать заново или обновлять существующую копию.
TL;DR
$env:GITEA_TOKEN = '<token из Gitea Settings → Applications>'
npm run release -- -Bump patch # 0.2.0 → 0.2.1
# или
npm run release -- -Version 0.3.0
Скрипт сделает всё сам: бамп версии, коммит, тег, push, тесты, сборка инсталлятора, создание Gitea release с заметками из коммитов, загрузка артефактов.
После публикации релиза установленные у пользователей копии в течение
~6 часов проверят latest.yml на Gitea и предложат обновление через UI.
Как работает auto-update
- На каждом релизе вместе с
.exeпубликуетсяlatest.yml— манифест с версией, размером, sha512 хешем. - Приложение (через
electron-updater) каждые 6 часов делает HTTP GET на<gitea>/AnRil/laude/releases/download/v<current>/latest.yml. - Если версия в манифесте выше текущей — статус становится
available, в Settings → Обновления появляется кнопка «Скачать». - После скачивания — статус
downloaded, кнопка «Перезапустить». - При перезапуске NSIS установщик из дельты или полный накатывается
поверх существующей инсталляции. Данные в
%APPDATA%\Exercise Reminder\сохраняются.
Важно: репозиторий laude приватный. Чтобы auto-update работал на
машинах конечных пользователей, либо:
- сделать репозиторий публичным, либо
- сделать публичными только релизы (Gitea: Release Settings),
- либо подписывать запросы токеном (нужен код в
updater.ts, использующийautoUpdater.requestHeaders).
Способ 1 — скрипт релиза (рекомендованный сейчас)
Самый прямой путь, не зависит от Gitea Actions runners.
# Один раз — получить токен в Gitea (Settings → Applications)
# и сохранить в переменную окружения. Право — write:repository.
[Environment]::SetEnvironmentVariable('GITEA_TOKEN', '<token>', 'User')
# Релиз
npm run release -- -Bump patch # patch (0.2.0 → 0.2.1)
npm run release -- -Bump minor # minor (0.2.0 → 0.3.0)
npm run release -- -Bump major # major (0.2.0 → 1.0.0)
npm run release -- -Version 1.2.3 # точная версия
npm run release -- -DryRun # посмотреть план без действий
Что делает скрипт:
- Проверяет что нет незакоммиченных изменений
- Бампит версию в
package.json, коммитит - Прогоняет
npm run typecheckиnpm run test:run - Собирает
npm run dist(NSIS + блокмап + latest.yml) - Создаёт тег
vX.Y.Z, пушит main и тег в origin - Через Gitea API создаёт release с заметками из git log
- Загружает три файла как assets:
.exe,.exe.blockmap,latest.yml
Способ 2 — Gitea Actions (если есть runners)
Workflows лежат в .gitea/workflows/:
ci.yml— на push в main и на PR. Запускает typecheck + unit-тесты + smoke-сборку (без NSIS). Кладёт распакованную сборку как artifact на 7 дней.release.yml— на push тегаv*.*.*. Сверяет тег с версией вpackage.json, прогоняет тесты, собирает NSIS-инсталлятор, создаёт Gitea release с заметками, загружает артефакты.
Чтобы release workflow работал — в репозитории нужен secret
GITEA_TOKEN (Gitea Repo Settings → Secrets). Этот же токен может быть
переиспользован из Способа 1.
Для запуска release workflow:
git tag v0.3.0
git push origin v0.3.0
Способ 3 — руками
Если что-то сломалось в автоматизации:
npm run typecheck
npm run test:run
npm run dist
# В release/ появятся:
# Exercise-Reminder-Setup-X.Y.Z.exe
# Exercise-Reminder-Setup-X.Y.Z.exe.blockmap
# latest.yml
Затем в Gitea UI: Releases → Draft new release → загрузить три файла.
Тестирование auto-update
Удобный способ проверить, что цикл работает:
- Релизнуть
0.x.0черезnpm run release. - Установить полученный
.exeна машину. - Релизнуть
0.x.1(любой бамп). - На установленной копии открыть Settings → Обновления → Проверить. Должно показать «Доступно обновление v0.x.1».
- Скачать → Перезапустить → проверить версию в окне «О программе» (или в Settings).
Для dev-режима (npm run dev) auto-updater отключён — статус сразу
становится unsupported с пояснением.
Откат релиза
Если опубликовали плохой релиз:
- Удалить release в Gitea UI (или через API).
- Удалить тег:
git push origin :refs/tags/vX.Y.Zи локальноgit tag -d vX.Y.Z. - Откатить bump-коммит:
git revert <hash>илиgit reset --hard HEAD~1(если ещё не пушили дальше). - Релизнуть тот же номер заново — auto-updater на клиентах увидит
тот же манифест и не предложит обновление (если sha512 совпадёт).
Если содержание поменялось — увидит и предложит обновиться. На
практике лучше выпустить hotfix-патч
X.Y.Z+1, чем переписывать существующий релиз.
Что попадает в установщик
См. build секцию package.json:
out/**/*— собранный код (main + preload + renderer)resources/**/*— иконки
Никаких node_modules, исходников, тестов, README — electron-builder
сам распаковывает и упаковывает только необходимое.