Upload script: - Retry curl on transient network failures (504, schannel TLS abrupt close): up to 4 retries with 15s/45s/2m/5m backoff. Before each retry, list the release assets server-side — Gitea sometimes commits the body but times out the response, so the file may already be there at the expected size (skip retry). If present at wrong size (partial), delete before re-uploading. ASCII-only (PS5.1 reads files in CP1251 without BOM). Docs: - README: bump release/test badges to v0.5.1 / 51 tests; mention silent retry in the auto-update feature line. - RELEASING: rewrite around the new update-channel architecture, bridge tags, and dropped Gitea Actions workflows. Co-Authored-By: Claude Opus 4.7 <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://xn--90adajar8af4h.xn--p1ai/git/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`
|
||
сам выбирает только необходимое.
|