Files
laude/RELEASING.md
AnRil 92e15e69a3
Some checks failed
CI / Typecheck + Tests (push) Has been cancelled
CI / Build (Windows) (push) Has been cancelled
feat: auto-update, тесты и CI/CD
Полная автоматизация релизного цикла.

== 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>
2026-05-16 20:32:59 +07:00

7.3 KiB
Raw Blame History

Релиз и автообновления

Документ описывает три способа выпустить новую версию. Все опираются на один и тот же артефакт — 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

  1. На каждом релизе вместе с .exe публикуется latest.yml — манифест с версией, размером, sha512 хешем.
  2. Приложение (через electron-updater) каждые 6 часов делает HTTP GET на <gitea>/AnRil/laude/releases/download/v<current>/latest.yml.
  3. Если версия в манифесте выше текущей — статус становится available, в Settings → Обновления появляется кнопка «Скачать».
  4. После скачивания — статус downloaded, кнопка «Перезапустить».
  5. При перезапуске 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         # посмотреть план без действий

Что делает скрипт:

  1. Проверяет что нет незакоммиченных изменений
  2. Бампит версию в package.json, коммитит
  3. Прогоняет npm run typecheck и npm run test:run
  4. Собирает npm run dist (NSIS + блокмап + latest.yml)
  5. Создаёт тег vX.Y.Z, пушит main и тег в origin
  6. Через Gitea API создаёт release с заметками из git log
  7. Загружает три файла как 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

Удобный способ проверить, что цикл работает:

  1. Релизнуть 0.x.0 через npm run release.
  2. Установить полученный .exe на машину.
  3. Релизнуть 0.x.1 (любой бамп).
  4. На установленной копии открыть Settings → Обновления → Проверить. Должно показать «Доступно обновление v0.x.1».
  5. Скачать → Перезапустить → проверить версию в окне «О программе» (или в Settings).

Для dev-режима (npm run dev) auto-updater отключён — статус сразу становится unsupported с пояснением.

Откат релиза

Если опубликовали плохой релиз:

  1. Удалить release в Gitea UI (или через API).
  2. Удалить тег: git push origin :refs/tags/vX.Y.Z и локально git tag -d vX.Y.Z.
  3. Откатить bump-коммит: git revert <hash> или git reset --hard HEAD~1 (если ещё не пушили дальше).
  4. Релизнуть тот же номер заново — auto-updater на клиентах увидит тот же манифест и не предложит обновление (если sha512 совпадёт). Если содержание поменялось — увидит и предложит обновиться. На практике лучше выпустить hotfix-патч X.Y.Z+1, чем переписывать существующий релиз.

Что попадает в установщик

См. build секцию package.json:

  • out/**/* — собранный код (main + preload + renderer)
  • resources/**/* — иконки

Никаких node_modules, исходников, тестов, README — electron-builder сам распаковывает и упаковывает только необходимое.