Подключение обновлений к программе
Инструкция к «Набору ТБП Обновления» 1.1.0 для программиста.
Этот набор нужен, чтобы программа сама находила новые версии на сервере «Техно без паники», спрашивала пользователя и обновлялась. Механизм обновления уже готов: его нужно только подключить.
Подключение занимает три шага:
- Положить два файла из набора рядом с главным файлом программы.
- Добавить одну строку в код, которая выполняется при запуске программы.
- Выпускать версии в админке или скриптом. Программа сама их найдёт.
Это общая инструкция. В админке на странице каждой программы есть кнопка «Набор для программиста». Скачанный набор уже заполнен настройками этой программы, и в его инструкции указаны её названия.
Подключаете с ИИ-помощником (Claude, Codex, Cursor, Copilot и другие)? Распакуйте набор в папку проекта и скажите помощнику: «Подключи обновления по набору из папки tbp-update-kit-…». Задание для него лежит в наборе в файле
AGENTS.md. В конце помощник напишет, какую папку набора взял и что осталось сделать вам.
Содержание
- Что в наборе
- Настройки программы
- Windows
- Linux
- Android
- Что увидит пользователь
- Проверка перед первым выпуском
- Выпуск версий
- Обязательные требования
- Что делает только человек
- Частые ошибки
- Своё окно обновления вместо стандартного
Что в наборе
| Папка или файл | Что это |
|---|---|
README.html, README.md |
эта инструкция |
AGENTS.md, CLAUDE.md |
задание для ИИ-помощника: то же самое коротко, по шагам |
windows/ |
всё для платформы «Windows»: tbp-updater.exe и tbp-update.json |
windows-portable/ |
всё для платформы «Windows (без установки)»: tbp-updater.exe и tbp-update.json |
android/ |
всё для платформы «Android»: библиотека tbp-updater.aar, tbp-update.json и store/tbp-update.json для сборок RuStore и Google Play |
linux/ |
всё для платформы «Linux»: tbp-updater (x64), tbp-updater-arm64 (ARM) и tbp-update.json |
examples/ |
готовые примеры подключения для разных языков |
publish/ |
скрипты автоматического выпуска версий: publish.ps1 для Windows, publish.sh для Linux |
Главное правило: файлы tbp-updater и tbp-update.json лежат в одной папке с главным файлом программы, а их имена не меняются.
Какую папку брать
Каждая папка набора — это одна платформа в админке, то есть отдельный поток обновлений. Берите папку той платформы, под которой эта сборка будет выпускаться в админке. Если взять не ту, программе будут приходить обновления, предназначенные для другой сборки.
| Как раздаётся программа | Папка набора |
|---|---|
| Windows, установщик (exe, msi) | windows/ |
| Windows (без установки): zip или один exe | windows-portable/ |
| Android: APK файлом, RuStore, Google Play | android/ |
| Linux: DEB, RPM, AppImage или архив | linux/ |
Если программа раздаётся в нескольких видах, например установщиком и zip-архивом, в каждую сборку кладётся свой tbp-update.json из своей папки. Какие платформы есть и как они называются, видно в админке: «Платформы».
Настройки программы
Файл tbp-update.json уже заполнен. Вписывать в него ничего не нужно.
{
"kit": "1.1.0",
"server": "https://updates.technobezpaniki.ru",
"app": "kod-programmy",
"name": "Ваша программа",
"platform": "windows",
"channel": "stable",
"public_key": "+QpN0ZeOt6U5tBsxABczTrxjnXnQ3axflzcjdpkP6EQ=",
"page": "https://technobezpaniki.ru/programs/kod-programmy/"
}
| Поле | Значение |
|---|---|
server |
адрес сервера обновлений |
app |
код программы на сервере |
name |
название программы в окнах обновления |
platform |
код платформы. В каждой папке набора он свой, поэтому файлы из папок не смешивают |
channel |
stable — обычные версии, beta — ещё и бета-версии. Это единственное поле, которое можно менять: например, для тестовых сборок |
public_key |
открытый ключ подписи. По нему проверяется, что файл обновления выпущен вами и не подменён |
page |
страница программы на сайте |
Код программы и коды платформ появляются в адресах обновлений. После выпуска программы менять их нельзя.
Windows
Куда положить файлы
Скопируйте оба файла из папки набора, которая подходит этой сборке (см. Какую папку брать): windows/ — «Windows», windows-portable/ — «Windows (без установки)». Файлы кладутся в папку программы:
C:\Program Files\Ваша программа\ ← папка программы (любая)
├─ program.exe ← ваша программа
├─ tbp-updater.exe ← из набора
└─ tbp-update.json ← из набора
Эти два файла должны входить в каждую версию: в установщик или в архив, как обычные файлы программы. Отдельно их никто не ставит.
Одна строка при запуске программы
Запустите tbp-updater.exe из папки программы и передайте номер текущей версии. Ждать его завершения не нужно: он сразу уходит в фон и не задерживает запуск.
C# (Program.cs, до Application.Run или в App.OnStartup):
System.Diagnostics.Process.Start(
System.IO.Path.Combine(AppContext.BaseDirectory, "tbp-updater.exe"), "--version 1.4.2");
C++ (WinAPI):
ShellExecuteW(nullptr, L"open", L"tbp-updater.exe", L"--version 1.4.2", exeFolder, SW_HIDE);
Python (в том числе собранный PyInstaller):
import os, subprocess, sys
folder = os.path.dirname(sys.executable if getattr(sys, "frozen", False) else os.path.abspath(__file__))
subprocess.Popen([os.path.join(folder, "tbp-updater.exe"), "--version", "1.4.2"])
Готовые примеры для C#, C++, Qt, Delphi, Python, Electron и Java лежат в папке examples/.
Номер версии на Windows можно не передавать. Тогда tbp-updater прочитает его из свойств exe-файла программы (поле «Версия продукта»). Но надёжнее передавать явно и брать из того же места, откуда берётся номер для сборки.
Ещё три правила запуска:
- Запускайте
tbp-updaterпрямо из программы, а не черезcmd /c, bat-файл или отдельный запускатель. По процессу, который его запустил,tbp-updaterузнаёт, какую программу закрыть перед установкой и запустить после. Если по-другому нельзя, передайте номер процесса программы:--pid 1234. Программа на Python, запущенная скриптом, передаёт--pidвсегда (так сделано вexamples/python/). - Путь к
tbp-updaterберите от папки программы, а не от текущей папки: программу могут запустить из любой папки. - Если
tbp-updaterне нашёлся или не запустился, программа работает дальше как обычно. Ошибку достаточно записать в журнал, пользователю её не показывают.
Номер версии в файлах, которые вы выпускаете
Сервер сам читает номер версии из загружаемого файла. Он должен совпадать с номером, который программа передаёт в --version.
| Что выпускаете | Откуда сервер берёт номер |
|---|---|
Установщик .exe |
«Версия продукта» в свойствах файла. Inno Setup: AppVersion и VersionInfoVersion; NSIS: VIProductVersion и VIAddVersionKey ProductVersion |
.msi |
из имени файла: program-1.4.2.msi |
Архив .zip |
из имени файла: program-1.4.2-windows.zip |
Номер можно и вписать вручную при выпуске.
Как ставится обновление
Способ выбирается по типу файла. При необходимости его можно поменять в админке: при выпуске версии раздел «Установка у пользователя».
- Установщик (exe, msi). Программа закрывается, установщик запускается как при обычной установке. Если нужны права администратора, Windows спросит. После установки программа запускается снова, если установщик не сделал этого сам. Установщик должен ставиться поверх прежней версии в ту же папку, без удаления старой. В Inno Setup для этого нужен тот же
AppIdиCloseApplications=yes. Чтобы установщик прошёл без вопросов, укажите в админке «Параметры установщика»: Inno Setup —/SILENTили/VERYSILENT /SUPPRESSMSGBOXES, NSIS —/S, MSI —/passive. - Без установки (zip). Программа закрывается, архив распаковывается поверх папки программы, и программа запускается снова. Файлы в архиве лежат в корне или в одной папке, как в папке программы. Старые файлы, которых нет в архиве, не удаляются. При сбое всё возвращается как было. Если папка программы в
Program Files, Windows спросит права администратора. - Один exe-файл без архива. Выберите в админке способ «Заменить файл программы».
- Архив со своим установщиком (например, в архиве исходники и
Install.ps1, который собирает и ставит программу). Выберите способ «Архив со своим установщиком» и в «Параметрах установщика» укажите имя файла в архиве и его параметры, напримерInstall.ps1 -Update -Quiet.tbp-updaterраспакует архив, запустит установщик без окна консоли и дождётся его. Установщик должен сам закрыть работающую программу, поставить новую версию и запустить её, а при ошибке — вернуть код выхода не 0. Годятся.ps1,.cmd,.bat,.exe(на Linux —.sh). Скриптом выпуска:-Install script -InstallArgs "Install.ps1 -Update -Quiet".
Пример скрипта Inno Setup: examples/windows/inno-setup/setup.iss.
Linux
Куда положить файлы
/opt/program/
├─ program ← ваша программа
├─ tbp-updater ← из папки linux/ набора (для ARM — tbp-updater-arm64, переименуйте в tbp-updater)
└─ tbp-update.json ← из папки linux/ набора
У tbp-updater должен быть признак исполняемого файла: chmod 755 tbp-updater.
Одна строка при запуске программы
На Linux номер версии обязателен:
subprocess.Popen(["/opt/program/tbp-updater", "--version", "1.4.2"])
Лучше брать путь к папке от самой программы, а не писать его жёстко. Примеры есть в examples/python/ и examples/qt/. Правила запуска те же, что на Windows: запускать прямо из программы, не ждать завершения, а если tbp-updater не запустился — работать дальше как обычно.
Форматы выпуска
| Формат | Откуда номер версии | Как ставится обновление |
|---|---|---|
| DEB (рекомендуется) | поле Version: в DEBIAN/control |
через apt-get; система спросит пароль администратора (pkexec) |
| RPM | из имени файла | через dnf или zypper, тоже с паролем |
| AppImage | из имени файла: program-1.4.2-x86_64.AppImage |
заменяется сам файл .AppImage; положите tbp-updater и tbp-update.json внутрь, рядом с программой (usr/bin/) |
Архив .tar.gz / .tar.xz |
из имени файла | распаковывается поверх папки программы |
Архив со своим install.sh |
из имени файла | распаковывается во временную папку, запускается install.sh (способ «Архив со своим установщиком», см. раздел Windows) |
Для DEB-пакета добавьте в control строку Recommends: zenity | kdialog, pkexec. Тогда у обновления будут нормальные окна. Пример: examples/linux/deb/.
Окна показываются через zenity (GNOME, Cinnamon, MATE, XFCE) или kdialog (KDE). Если их нет, вопрос задаётся в терминале, если программа запущена из него, а иначе показывается только уведомление о новой версии.
Android
Подключение
- Скопируйте
android/tbp-updater.aarв папкуapp/libs/проекта. - В
app/build.gradle.ktsдобавьте зависимость:kotlin dependencies { implementation(files("libs/tbp-updater.aar")) } - Скопируйте
android/tbp-update.jsonвapp/src/main/assets/tbp-update.json. - Добавьте одну строку в
onCreateглавной Activity:kotlin TbpUpdater.check(this) // Kotlinjava TbpUpdater.check(this); // JavaИмпорт:ru.technobezpaniki.updater.TbpUpdater.
Номер версии библиотека берёт сама из versionName в build.gradle.kts. Он должен совпадать с номером, под которым APK выпускается на сервере: сервер читает его из APK. versionCode должен расти с каждой версией.
Разрешения INTERNET и REQUEST_INSTALL_PACKAGES библиотека добавляет сама. При первом обновлении Android спросит пользователя, можно ли этому приложению устанавливать программы. Это нормально, так спрашивает сама система.
Минимальная версия Android — 5.0 (minSdk 21).
APK всегда подписывайте одним и тем же ключом. Если ключ подписи сменится, Android откажется ставить обновление поверх старой версии. Ключ (
.jks) храните в надёжном месте и не теряйте.
RuStore и Google Play
Google Play запрещает приложениям обновлять себя в обход магазина. Поэтому для магазинов делается отдельная сборка (flavor), в которой библиотека с нашего сервера не обновляется, а обновлением занимается магазин.
- В
build.gradle.ktsзаведите варианты сборкиdirect(файлом с сайта),rustoreиgoogleplay(пример:examples/android/build.gradle.kts). - Для
rustoreиgoogleplayположите файлandroid/store/tbp-update.jsonиз набора вapp/src/rustore/assets/иapp/src/googleplay/assets/. Он отличается одним полем:"mode": "store". - Для них же уберите разрешение на установку. Файл
app/src/rustore/AndroidManifest.xmlесть вexamples/android/store/.
Код приложения при этом одинаковый: строка TbpUpdater.check(this) остаётся, а в сборке для магазина она ничего не делает.
Пока приложения нет в магазинах, раздаётся только вариант direct. Варианты для магазинов можно завести сразу или позже, когда приложение туда выйдет.
Что увидит пользователь
При запуске программы, а если она открыта долго — раз в сутки, tbp-updater спрашивает сервер о новой версии. Если она есть, появляется окно:
Вышла новая версия Установлена версия 1.4.2, новая — 1.4.3. Что нового: … [Обновить] [Позже] [Пропустить эту версию]
- Обновить. Файл скачивается с полосой прогресса, затем проверяются контрольная сумма и цифровая подпись. Программа закрывается, как будто пользователь нажал «крестик», поэтому она успевает сохранить данные. Ставится новая версия, и программа запускается снова.
- Позже. Программа спросит при следующем запуске или через сутки.
- Пропустить эту версию. Про эту версию программа больше не спрашивает, а про следующие спросит.
Если в админке у версии стоит галочка «Обязательное обновление», у окна только две кнопки: «Обновить» и «Закрыть программу». Пока открыто это окно, программой на Windows пользоваться нельзя. Если интернета нет, проверка просто не выполняется, и программа работает как обычно.
Текст «Что нового» берётся из поля «Что нового» у версии в админке.
Проверка перед первым выпуском
- Соберите программу с версией
1.0.0, установите её и запустите. Окна быть не должно. - В админке выпустите версию
1.0.1для той же платформы: загрузите файл и нажмите «Сохранить». Для проверки удобно выпустить её в канал «Бета» и в тестовой сборке указать"channel": "beta": тогда обычные пользователи её не увидят. - Запустите установленную
1.0.0. Должно появиться окно «Вышла новая версия». Нажмите «Обновить». - Программа должна закрыться, обновиться и запуститься уже версией
1.0.1. Окно больше не появляется.
Проверить без окна из командной строки (Windows — PowerShell в папке программы):
.\tbp-updater.exe check --version 1.0.0 | Out-String
./tbp-updater check --version 1.0.0
Ответ — JSON, например "update_available": true. Команда tbp-updater about показывает настройки и путь к журналу.
Журнал всех проверок и установок:
- Windows: %LOCALAPPDATA%\TBP\Updater\<код программы>\updater.log
- Linux: ~/.local/state/tbp-updater/<код программы>/updater.log
- Android: adb logcat -s TbpUpdater
Выпуск версий
Вручную: админка → «Версии» → «Выпустить версию». Выберите программу и платформу, прикрепите файл и нажмите «Сохранить».
Автоматически из сборки: скрипты в папке publish/. Нужен ключ API: админка → «Ключи API (автоматизация)» → «Создать ключ». Ключ показывается один раз. Передайте его скрипту через переменную окружения TBP_API_TOKEN, в код ключ не записывайте.
$env:TBP_API_TOKEN = "tbp_…"
.\publish\publish.ps1 -File dist\setup.exe -Platform windows -Notes "- Исправлены ошибки"
export TBP_API_TOKEN=tbp_…
./publish/publish.sh --file dist/program_1.4.3_amd64.deb --platform linux --notes-file CHANGES.md
-Platform обязателен: это имя папки набора, из которой взят tbp-update.json этой сборки. Если программа раздаётся в нескольких видах, каждый файл выпускается со своим -Platform.
Полезные параметры (в publish.sh они пишутся так же, но строчными через дефис: --channel beta):
- -Channel beta — бета-версия;
- -Mandatory — обязательное обновление;
- -Draft — загрузить, но не публиковать: опубликуете галочкой в админке после проверки;
- -InstallArgs "/SILENT" — параметры установщика; следующие версии получат их сами;
- -Version 1.4.3 — номер версии, если его не удаётся прочитать из файла.
Обязательные требования
- Данные пользователя хранятся не в папке программы: на Windows в
%APPDATA%или%LOCALAPPDATA%, на Linux в~/.configили~/.local/share. При обновлении файлы в папке программы заменяются. - Номер версии в программе совпадает с номером выпущенного файла. Иначе программа после обновления будет считать себя старой.
- Каждая новая версия получает больший номер:
1.4.2→1.4.3. Сравниваются числа, поэтому1.10новее1.9. Бета-версии обозначаются1.5.0-beta.1. - Программа нормально закрывается по «крестику» (на Linux — по сигналу SIGTERM). Именно так её закрывает
tbp-updaterперед установкой. - Установщик ставится поверх старой версии, в ту же папку.
- Android: APK подписывается всегда одним ключом, а
versionCodeрастёт. tbp-update.jsonиtbp-updaterне переименовываются, а настройки в файле не правятся (кромеchannel).- Своя проверка обновлений не пишется. Проверку, скачивание, проверку подписи и установку делает
tbp-updaterили библиотека Android.
Что делает только человек
Это не делают ни программист в коде, ни ИИ-помощник:
- Решает, как раздаётся программа (установщик, zip, DEB, APK, магазины). От этого зависит папка набора.
- Создаёт ключ API в админке для скриптов выпуска и передаёт его через переменную окружения
TBP_API_TOKENили секрет сборочного сервера. В код и в репозиторий ключ не попадает. - Выпускает версии в админке или запускает скрипт выпуска. Решает, какая версия бета, какая обязательная.
- Android: создаёт и хранит ключ подписи APK (
.jks) и пароли к нему. Ключ не теряется и не меняется. - Проверяет обновление по-настоящему перед первым выпуском: см. Проверка перед первым выпуском.
Частые ошибки
| Что происходит | Почему | Что сделать |
|---|---|---|
| Окно обновления не появляется | нет файла tbp-update.json рядом с tbp-updater, или на сервере нет версии новее |
tbp-updater about и tbp-updater check --version …, журнал |
| После обновления снова предлагает то же обновление | программа передаёт старый номер версии | исправить номер в программе (требование 2) |
| Уже скачанная раньше версия не обновляется | в ней ещё не было tbp-updater |
такие пользователи один раз скачивают новую версию с сайта, дальше она обновляется сама. Первую версию с обновлениями выпускайте с новым номером |
| Пришло обновление от другой сборки (например, установщик вместо zip) | tbp-update.json взят не из той папки набора или версия выпущена не на ту платформу |
см. Какую папку брать, в скрипте выпуска — свой -Platform |
| «Подпись не сходится» | tbp-update.json взят из набора другого сервера или другой программы |
взять файл из набора этой программы |
| «Программа не закрывается» | программа не реагирует на «крестик» | обработать закрытие окна / SIGTERM |
| Android: «Приложение не установлено» | APK подписан другим ключом | подписывать тем же ключом, что и первую версию |
| Windows: «Неизвестный издатель» | у программ нет цифровой подписи кода | со временем купить сертификат подписи кода и подписывать exe |
Своё окно обновления вместо стандартного
Если программа хочет показывать своё окно, используйте команды:
tbp-updater check --version 1.4.2
Выводит JSON, ничего не показывая: update_available, mandatory, version, notes. Код выхода: 0 — обновлений нет, 10 — есть, 11 — есть обязательное, 1 — ошибка.
tbp-updater install --version 1.4.2
Сразу скачивает и ставит новую версию без вопроса: полоса прогресса, закрытие программы, установка, запуск.
tbp-updater --version 1.4.2 --once
Одна проверка со стандартным окном «Обновить / Позже / Пропустить», без повторов раз в сутки. Удобно, если программа сама решает, когда проверять (например, по своему таймеру и с выключателем в настройках).
Все три команды запускаются из процесса программы без ожидания, кроме check: его вывод программа читает. В ответе check есть и skipped — пользователь уже нажал «Пропустить эту версию». Если программа сама запускает проверки, не запускайте ещё и обычный фоновый tbp-updater --version …: он держит проверку за собой, пока программа открыта, и install тогда ничего не сделает.
Как устроен обмен с сервером (адреса, формат ответа, проверка подписи), описано на странице https://technobezpaniki.ru/developers/.