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>
143 lines
7.2 KiB
Markdown
143 lines
7.2 KiB
Markdown
# Релиз и автообновления
|
||
|
||
Документ описывает, как выпускать новые версии и как устроена система
|
||
авто-обновлений.
|
||
|
||
## TL;DR
|
||
|
||
```pwsh
|
||
$env:GITEA_TOKEN = '<token из Gitea Settings → Applications>'
|
||
npm run release -- -Bump patch # 0.5.1 → 0.5.2
|
||
npm run release -- -Bump minor -BridgeTags v0.5.0 # 0.5.x → 0.6.0 + bridge
|
||
npm run release -- -Version 1.0.0
|
||
```
|
||
|
||
Скрипт делает всё сам: бамп версии, коммит, тег, push, тесты, сборка
|
||
инсталлятора, загрузка в Gitea releases.
|
||
|
||
## Архитектура auto-update
|
||
|
||
### Где лежат артефакты
|
||
|
||
Каждый выпуск публикует три файла:
|
||
|
||
```
|
||
Exercise-Reminder-Setup-X.Y.Z.exe # NSIS-инсталлятор (~80 MB)
|
||
Exercise-Reminder-Setup-X.Y.Z.exe.blockmap # для differential update (~90 KB)
|
||
latest.yml # манифест: версия + хеш + размер
|
||
```
|
||
|
||
И они одновременно публикуются в **три-четыре места** на Gitea:
|
||
|
||
| Release tag | Назначение |
|
||
| ----------------- | ------------------------------------------------------------ |
|
||
| `vX.Y.Z` | Архив + changelog для людей |
|
||
| `update-channel` | **Фиксированный URL для auto-updater** (никогда не меняется) |
|
||
| `vN.M.K` (bridge) | Мост: чтобы клиенты на старых версиях нашли обновление |
|
||
|
||
### Что приложение запекает в бинарник
|
||
|
||
В `package.json` → `build.publish.url`:
|
||
|
||
```
|
||
https://git.xn--90adajar8af4h.xn--p1ai/AnRil/laude/releases/download/update-channel
|
||
```
|
||
|
||
Этот URL **никогда не меняется**. Все версии (и сегодняшние, и будущие)
|
||
проверяют один и тот же `update-channel/latest.yml`.
|
||
|
||
### Цикл проверки
|
||
|
||
1. При запуске и каждый час `electron-updater` делает GET на
|
||
`…/update-channel/latest.yml`.
|
||
2. Если в манифесте версия выше текущей — Settings → Обновления показывает
|
||
«Доступно vX.Y.Z». По клику качается `.exe` (или differential по
|
||
`.blockmap`).
|
||
3. После скачивания — кнопка «Перезапустить». NSIS обновляет инсталляцию
|
||
поверх с сохранением `%APPDATA%\Exercise Reminder\app-state.json`.
|
||
|
||
### Bridge-теги (миграционный период)
|
||
|
||
До v0.5.1 publish.url был `…/releases/download/v${version}` — у каждой
|
||
версии свой адрес. Установленные ранее копии запекли старый URL.
|
||
Чтобы они нашли обновление, новые артефакты также заливаются в их
|
||
старые releases (флаг `-BridgeTags`).
|
||
|
||
После того как все клиенты получили v0.5.1 или выше, аргумент
|
||
`-BridgeTags` можно перестать использовать — все будущие версии берут
|
||
обновления через `update-channel`.
|
||
|
||
### Поведение при ошибках
|
||
|
||
- Hourly auto-check работает в **silent**-режиме: сетевые ошибки
|
||
логируются в консоль, но **не** показываются как красный баннер.
|
||
Следующая попытка через час.
|
||
- Boot-check ретраит 3 раза с backoff 30s/2m/5m перед тем как сдаться.
|
||
- Только ручной клик «Проверить обновления» показывает ошибку, если
|
||
она есть.
|
||
|
||
## Команды
|
||
|
||
```pwsh
|
||
# Один раз — токен из Gitea Settings -> Applications (write:repository).
|
||
[Environment]::SetEnvironmentVariable('GITEA_TOKEN', '<token>', 'User')
|
||
|
||
# Релиз
|
||
npm run release -- -Bump patch # patch (0.5.1 -> 0.5.2)
|
||
npm run release -- -Bump minor # minor (0.5.x -> 0.6.0)
|
||
npm run release -- -Bump major # major
|
||
npm run release -- -Version 1.2.3 # точная версия
|
||
npm run release -- -BridgeTags v0.4.0,v0.5.0 # дополнительные мосты
|
||
npm run release -- -DryRun # план без действий
|
||
```
|
||
|
||
Что делает `release.ps1`:
|
||
|
||
1. Проверяет чистоту дерева.
|
||
2. Бампит `package.json`, коммитит как `chore(release): vX.Y.Z`.
|
||
3. `npm run typecheck` + `npm run test:run`.
|
||
4. `npm run dist` → NSIS-инсталлятор + blockmap + latest.yml в `release/`.
|
||
5. `git tag vX.Y.Z` и push main + tag в origin.
|
||
6. Через `upload-release-assets.ps1` заливает артефакты в каждый тег
|
||
из списка: `vX.Y.Z`, `update-channel`, и все `-BridgeTags`.
|
||
7. Каждая заливка ретраит до 4 раз с backoff 15s/45s/2m/5m на 504.
|
||
|
||
## Тестирование auto-update
|
||
|
||
1. Установить какую-нибудь старую версию через `.exe` из её release.
|
||
2. Релизнуть свежую версию.
|
||
3. В установленной копии: Settings → Обновления → Проверить.
|
||
4. Должно показать «Доступна vX.Y.Z» с кнопкой «Скачать».
|
||
5. Скачать → Перезапустить → проверить версию.
|
||
|
||
Для `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. `git revert <bump-hash>` (бамп уже запушен).
|
||
4. Если артефакты успели уехать в `update-channel` — перезалить туда
|
||
предыдущую версию: `pwsh scripts/upload-release-assets.ps1 -Tag update-channel -AssetVersion <previous>`.
|
||
|
||
На практике лучше выпустить hotfix-патч `X.Y.Z+1`, чем откатывать.
|
||
|
||
## Gitea Actions
|
||
|
||
Раньше в `.gitea/workflows/` лежали `ci.yml` и `release.yml`. Они
|
||
требуют Gitea Actions runners (отдельная служба, у нас не настроена),
|
||
поэтому каждая push-операция оставляла зависший workflow run в Actions
|
||
tab. Workflows удалены, has_actions на репозитории выключен,
|
||
Actions tab возвращает 404. Если когда-нибудь захочется CI — добавить
|
||
обратно `.gitea/workflows/*.yml` + поднять runners.
|
||
|
||
## Что попадает в установщик
|
||
|
||
См. `build.files` в `package.json`:
|
||
|
||
- `out/**/*` — собранный код (main + preload + renderer)
|
||
- `resources/**/*` — иконки
|
||
|
||
Без `node_modules`, без исходников, без тестов — `electron-builder`
|
||
сам выбирает только необходимое.
|