Обновление билда на стендах через Яндекс.Диск

Новую версию приложения не обязательно возить на флешке. Вы кладёте в публичную папку Яндекс.Диска два файла — архив сборки и крошечный указатель manifest.json — а стенды забирают их сами, проверяют контрольную сумму и подменяют работающее приложение. Если новая версия окажется плохой, стенд откатится на предыдущую рабочую сам.

  • Папка на Яндекс.Диске
  • Стенды забирают сами
  • Апробация новой версии
  • Откат при сбое
Один zip и один manifest.json — и парк обновился

Что нужно: аккаунт Яндекс.Диска (хватит бесплатного) и одна опубликованная папка. Чего не нужно: своего сервера, базы данных, токена на стендах, открытых портов, белого IP, VPN и доменного имени. Стенд читает публичную папку анонимно — ни логина, ни токена в его настройках нет.

Про установку самого Watchdog — Установка и настройка. Про то, как он следит за приложением, — Когда Watchdog перезапускает приложение.

Как настроить обновления

Шаг 1. Создать и опубликовать папку на Яндекс.Диске

  1. Создайте папку — например museum-builds. Через сайт или десктоп-клиент, неважно.
  2. Опубликуйте папку целиком: правый клик → «Поделиться» → включить доступ по ссылке → скопировать ссылку вида https://disk.yandex.ru/d/AbC123XyZ. Эта ссылка целиком и есть то, что вставляется в Watchdog.
  3. Публикуется именно папка, а не отдельные файлы. Дальше каждое обновление сводится к тому, чтобы перезалить в неё zip и перезаписать manifest.json.

Аккаунт нужен только вам как публикатору: заливка и публикация — это запись. Стендам учётка не нужна.

Раскладка внутри папки плоская, подпапок нет:

museum-builds/            ← опубликована, её ссылка вставляется в Watchdog
  manifest.json           ← перезаписывается каждым релизом
  Chess-1.4.3.zip

Если приложений несколько — каждому нужна своя публичная папка: поля «Канал» и «Путь к манифесту» в интерфейсе сейчас скрыты, читается всегда manifest.json в корне.

Шаг 2. Собрать zip

Заархивируйте папку сборки. Годятся оба варианта — Watchdog нормализует распаковку сам:

# с обёрткой (корень zip = папка сборки) — обычное «Отправить → Сжатая папка»
Compress-Archive -Path .\Chess-1.4.3 -DestinationPath .\Chess-1.4.3.zip

# или плоско (в корне zip сразу exe и папка _Data)
Compress-Archive -Path .\Chess-1.4.3\* -DestinationPath .\Chess-1.4.3.zip

Правила:

  • в корне архива — после срезания одной обёрточной папки — должен лежать exe сборки;
  • имя обёрточной папки не важно;
  • служебный мусор __MACOSX/, .DS_Store, Thumbs.db игнорируется — актуально, если архив собирали на macOS;
  • путь к exe в манифесте указывается без обёртки: Chess.exe, а не Chess-1.4.3/Chess.exe.

Если в архиве по указанному пути exe не находится, это структурная ошибка: обновление не применяется, а версия уходит в карантин. Перекачка тут не поможет — нужно исправить архив или манифест.

Шаг 3. Сделать manifest.json

Манифест — это указатель на актуальную версию. Файл крошечный:

{
  "version": "1.4.3",
  "name": "Chess",
  "path": "Chess-1.4.3.zip",
  "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "sizeBytes": 734003200,
  "exeRelativePath": "Chess.exe",
  "rolloutAfter": ""
}

Три способа его получить — любой:

а) Генератор в браузере. Выбираете zip — инструмент считает контрольную сумму с прогресс-баром, берёт размер, читает список файлов из архива без распаковки и подставляет путь к exe, предзаполняет версию и имя из имени файла. Архив никуда не загружается и машину не покидает. Кнопки «Скачать manifest.json» и «Скопировать» становятся активны, только когда манифест проходит проверку.

б) Автоматически при сборке — см. Для разработчиков билдов.

в) Руками. Посчитайте контрольную сумму и размер в PowerShell и положите файл рядом с zip:

(Get-FileHash .\Chess-1.4.3.zip -Algorithm SHA256).Hash   # привести к нижнему регистру
(Get-Item .\Chess-1.4.3.zip).Length                       # размер в байтах

Поля манифеста:

ПолеОбязательноеЧто это
versionдаВерсия сборки. Уникальна для каждого релиза — именно по ней различаются версии
nameнетИмя продукта, идёт в имя папки на диске стенда. Пусто — выведется из имени exe
pathдаИмя zip рядом с манифестом, не ссылка
sha256даКонтрольная сумма архива: 64 шестнадцатеричных символа в нижнем регистре. Сверяется до любого действия с приложением
sizeBytesдаРазмер архива в байтах
exeRelativePathдаПуть к exe от корня сборки, без обёрточной папки
rolloutAfterнетМомент в формате 2026-07-01T03:00:00Z (UTC): применять не раньше. Пусто — сразу

Манифест проверяется до скачивания: контрольная сумма должна быть ровно 64 символа, размер — больше нуля, путь к exe — непустой и без ... Битый манифест не приводит к скачиванию: в журнал уходит «манифест невалиден: <причина>» не чаще раза в час, а цикл продолжает работать. Так одна опечатка не заставит парк качать многогигабайтный архив каждые 15 минут.

Шаг 4. Залить — сначала zip, манифест последним

ПОРЯДОК ЗАЛИВКИ:  1) zip   2) manifest.json — ПОСЛЕДНИМ

Манифест, указывающий на ещё не залитый архив, — это жёсткая ошибка скачивания на каждом стенде до конца заливки, а не тихий пропуск. Старые архивы можно удалять после того, как парк раскатился.

Шаг 5. Включить обновления в Watchdog

На стенде:

  1. Настройки → «Обновления» → поставить «Включить автообновление билдов». При необходимости поправить «Опрос, мин», «Тиков апробации», «Хранить версий» и окно раската.
  2. Настройки → «Приложение» (или «Приложения» и выбрать нужное) → блок «Источник обновлений»:
    • вставить публичную ссылку в поле «Публичная ссылка на папку Я.Диска»;
    • при необходимости изменить «Папку для билдов»;
    • проверить, что стоит «Обновления включены (для этого приложения)».
  3. Нажать «Проверить манифест». Ответ должен быть вида «Манифест найден: версия 1.4.3, 700 МБ, sha 9f86d081…, файл «Chess-1.4.3.zip».»
  4. «Сохранить». Настройки подхватываются на лету и будят опрос немедленно — ждать интервал не нужно.

Качать Watchdog начнёт, только если включены оба выключателя: общий «Включить автообновление билдов» и «Обновления включены» у этого приложения.

Если стенд настраивается с нуля, проще пройти мастер: источник «Скачать с Яндекс.Диска» → вставить ссылку → «Проверить» → «Начать». Мастер сам скачает архив, сверит контрольную сумму, распакует и настроит мониторинг. Галочка «Автоматически обновлять с этой папки» в мастере включена по умолчанию; если её снять, установка будет разовой, но ссылка всё равно сохранится — включить автообновление позже можно из настроек, не вводя её заново.

Если вкладок «Обновления» нет ни в главном окне, ни в настройках — это старый стенд: его настройки созданы до 8 июля 2026, когда показ вкладки стал поведением по умолчанию. Включается правкой config.json (update.featureVisible) при закрытом Watchdog.

Шаг 6. Что вы увидите

На вкладке «Обновления» главного окна строка версии пройдёт путь:

«В облаке» → «Качается 42 %» → «Подтверждается 1/3 … 3/3» → «Активная» с бейджем «текущая».

Вкладка «Обновления»: таблица версий со статусами
Версии на стенде: активная, на диске, в облаке

В журнале — вкладка «Логи watchdog» и файл logs\watchdog.log:

  • «Скачивание обновления 1.4.3 (700 МБ)»
  • «Обновление 1.4.3 применено, идёт апробация»
  • «Обновление 1.4.3 подтверждено (рабочая версия)»

На диске рядом с exe появится папка builds\…\Chess-1.4.3-9f86d0\, а во время закачки — .staging\.

Шаг 7. Выкатить следующую версию

  1. Поднимите version — она обязана быть новой и уникальной.
  2. Соберите и залейте новый zip.
  3. Обновите в манифесте version, path, sha256, sizeBytes и перезапишите manifest.json последним.

Следующий опрос накатит версию сам. Предыдущая останется на диске со статусом «На диске» — для отката, пока её не подрежет лимит «Хранить версий».

Если перезалить архив под той же версией с другим содержимым, стенд обновление не применит: в диагностический лог уйдёт предупреждение «поднимите версию, чтобы раскатать». Сравнение идёт только на равенство: понятий «новее» и «старее» у Watchdog нет.

Шаг 8. Откатить парк

Одну машину откатывают из интерфейса: вкладка «Обновления» → правый клик по нужной версии → «Откатиться на эту» в автоматическом режиме (отвергнутая версия уйдёт в карантин) или «Перейти на эту версию» в ручном (без карантина).

Весь парк — вернуть в manifest.json предыдущую версию: version, path, sha256 и sizeBytes от старого архива, сам архив должен лежать в папке. Поскольку сравнение идёт на равенство, стенды увидят «версия не совпадает с текущей» и перейдут на старую. Если она уже лежит у них на диске, установка пройдёт без повторной закачки.

Оговорка: версия, ранее провалившая апробацию, лежит в карантине по контрольной сумме — её сначала придётся разкарантинить вручную.

Что происходит после установки

Апробация — испытательный срок

Новая версия сразу становится текущей, но считается непроверенной, пока не отработает 3 здоровых тика подряд: процесс жив, окно отвечает, детектор зависания молчит.

ПараметрПо умолчанию
Здоровых тиков для подтверждения3
Длительность тикаравна интервалу опроса мониторинга, по умолчанию 10 секунд
Итого испытательный срококоло 30 секунд
Предельный срок апробации30 минут

Апробацию валят краш, перезапуск, зависание и срабатывание защиты от петли рестартов в это окно. Преднамеренная остановка — ручной стоп, плановый перезапуск — её не валит: счётчик тиков ставится на паузу и продолжается после запуска. Это закрывает случай «апробация не прошла, потому что стенд выключили на ночь».

Апробация не блокирует конвейер: манифест продолжает опрашиваться, и более новая версия, вышедшая тем временем, качается на диск — её установка просто ждёт исхода.

Откат

Цель отката — последняя версия, которая работала. Её папка уже на диске, поэтому откат мгновенный и без сети. В журнале: «Откат с 1.4.5 на 1.4.4: апробация не пройдена».

Откат спасает от плохого билда, а не от сломанной машины: если и предыдущая версия не стартует, работает штатный сценарий «пауза и сигнал человеку».

Карантин

Карантин блокирует содержимое: ключ — контрольная сумма, а не номер версии.

  • назначается автоматически при провале апробации и при структурной ошибке архива; вручную — правый клик → «В карантин»;
  • снимается автоматически, как только в манифесте появляется другая контрольная сумма (выложили фикс), или вручную — «Снять карантин»;
  • сбой до установки (сеть, не совпала контрольная сумма) карантином не считается — это временная неудача, повтор на следующем опросе. Карантин назначается за сбой после установки.

Стенд не встаёт колом: он просто пропускает плохую версию и спокойно накатит следующую.

Ручной режим (пин)

Хрупкий экспонат можно перевести в ручной режим: тумблер «Авто | Ручное» в шапке вкладки «Обновления».

КарантинРучной режим
На что действуетодна версиявсё приложение
Закачказаблокированаработает
Установказаблокированатолько вручную
Возврат в нормуавтоматически при новой версиитолько действием оператора

В ручном режиме новые версии всё равно скачиваются на диск и ждут команды «Перейти на эту версию». Мониторинг при этом не трогается: закреплённый билд упал — Watchdog перезапустит его как обычно. Состояние ручного режима переживает перезапуск Watchdog и отключение питания. При снятии пина стенд сверится с манифестом и перейдёт на ту версию, которая в нём сейчас; карантины при этом не сбрасываются.

Переключать режим безопасно в любой момент: пин во время закачки — архив докачается и останется на диске, пин во время апробации — апробация доиграет, блокируются только будущие установки.

Окно раската

Чтобы стенд не перезагружался при посетителях, установку можно ограничить по времени. Два независимых механизма:

  • окно раската в настройках стенда — интервал «с ЧЧ:мм по ЧЧ:мм», может пересекать полночь. По умолчанию выключено, обновление применяется сразу; при включении поля заполнены значениями 03:00 и 06:00;
  • rolloutAfter в манифесте — «не раньше такого-то момента», задаётся публикатором на конкретный релиз.

Окно гейтит только установку. Архив всё равно качается и ложится на диск, а встаёт при первом цикле после открытия окна — уже без повторной закачки.

Когда установка откладывается

Закачка и установка — независимые половины. Новая версия ложится на диск всегда: под пином, на паузе мониторинга, при закрытом окне раската и даже пока другая версия проходит апробацию. Ждать может только установка, и вот когда:

  • стоит пин;
  • идёт апробация другой версии;
  • окно раската закрыто;
  • мониторинг на паузе, а процесс приложения ещё жив — оператор приостановил Watchdog, оставив экспонат зрителям. Такой процесс не убивают: установка ждёт снятия паузы, а снятие паузы будит опрос немедленно.

Если процесс мёртв, а мониторинг на паузе (обычный ночной случай), версия ставится сразу, но своей паузы Watchdog не снимает: новый билд поднимется утром кнопкой ▶.

Указатель версии переключается атомарно и пишется последним, поэтому при отключении питания на диске всегда либо старая версия, либо новая — «половины» не бывает.

Действия со строкой версии

Правый клик по строке или кнопка «⋮» в конце строки:

ДействиеДля какого статусаЧто делает
Откатиться на эту«На диске», в автоматическом режимеПереключает указатель; отвергнутая версия уходит в карантин. Всегда спрашивает подтверждение
Перейти на эту версию«На диске», в ручном режимеНейтральный переход: без карантина и без апробации, закрепление переезжает на новую версию
Считать рабочей«Подтверждается»Засчитать апробацию вручную — например, если стенд держали выключенным
Скачать сейчас«В облаке»Обойти окно раската; в ручном режиме — скачать без установки
В карантин«Активная», «В облаке»Пометить версию плохой вручную
Снять карантин«В карантине»Разрешить новую попытку
Удалить с дискалюбая неактивнаяОсвободить место. Всегда спрашивает подтверждение
Открыть папкулюбая версия на дискеОткрывает папку билда в проводнике

Тексты подтверждений: «Откатиться на версию X? Текущая версия уйдёт в карантин, экспонат перезапустится.» · «Перейти на версию X? Текущая версия останется на диске (без карантина), экспонат перезапустится.» · «Удалить версию X с диска? Откатиться на неё будет нельзя.»

«Перейти на эту версию» спрашивает подтверждение только тогда, когда есть что перезапускать: если стенд стоит и процесса нет, версия переключается сразу. Отдельный случай, который спрашивает всегда, — мониторинг на паузе, но процесс жив.

Статусы версий

СтатусЗначит
В облакеМанифест указывает сюда, ещё не качали
Качается 42 %Идёт загрузка
Подтверждается 2/3Установлена как текущая, копит здоровые тики
АктивнаяТекущая рабочая версия — её запускает и наблюдает Watchdog
На дискеСкачана и лежит на диске: для мгновенного отката или ручного перехода
В карантинеПровалила апробацию, эта сборка заблокирована

Строка активной версии помечена трижды: подложкой, полоской слева и бейджем «текущая». В шапке таблицы справа — «Проверено: 16.09.2026 14:32» и кнопка, которая будит опрос немедленно.

Что настраивается и где

Общее на весь Watchdog — Настройки → «Обновления»:

НастройкаПо умолчаниюДиапазон
«Включить автообновление билдов»выключено
«Опрос, мин»151…1440
«Тиков апробации»31…60
«Хранить версий»2 (текущая + одна для отката)1…20
«Применять обновления только в окне»выключенополя 03:0006:00

Своё у каждого приложения — Настройки → «Приложения» → «Источник обновлений»: публичная ссылка на папку, папка для билдов (по умолчанию .\builds\<id>), тумблер «Обновления включены (для этого приложения)». Своими у приложения остаются также история версий, апробация и карантины: обновление одного экспоната не трогает соседний.

Хранится столько версий, сколько задано в «Хранить версий»; сломанные сюда не попадают — провалившая апробацию удаляется сразу, а текущая рабочая при чистке всегда защищена.

Типичные ошибки

СимптомПричинаЧто делать
«Скачивание обновления X не удалось (повтор позже): контрольная сумма не совпала»Архив перезалили, а sha256 и sizeBytes в манифесте забыли обновитьПересчитать сумму и размер, перезаписать манифест. После трёх провалов подряд по одной сумме закачка уходит в часовую паузу
«Файл … не найден на Я.Диске (манифест ссылается на отсутствующий zip)»Манифест залит раньше архива или архив перезалит под другим именемСоблюдать порядок: сначала zip, манифест последним. Проверить поле path
«структура архива: exe не найден», версия в карантинеПуть к exe в манифесте не совпадает с тем, что реально в архивеУказать имя exe от корня сборки, без обёрточной папки. Исправить манифест и поднять версию
«манифест невалиден: …»Манифест собран руками с ошибкойПересобрать генератором
Ничего не качаетсяПапка не опубликована; вставлена не та ссылка; выключен один из двух выключателей; в манифесте та же версия, что уже стоитПроверить по очереди
Апробация не проходит на заведомо рабочем билдеПриложению нужно прожить около 30 секунд и отвечать, то есть иметь окно. Консольный exe без окна может считаться «не отвечает»Проверить, что билд открывает окно
«недостаточно места: нужно ~1400 МБ, свободно 900 МБ»Нужно не меньше двух размеров архива: сам zip плюс распакованная копияОсвободить место или вынести папку для билдов на другой диск
SmartScreen или антивирус придерживает скачанный exeШтатное поведение WindowsДобавить папку builds\ в исключения

Для разработчиков билдов

Со стороны разработчика сборки от обновлений нужно немного: поднимать версию на каждый релиз и класть рядом с архивом корректный manifest.json.

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

  • версия сборки поднята и уникальна для этого релиза;
  • в корне архива (после срезания одной обёрточной папки) лежит exe;
  • путь к exe в манифесте — без обёрточной папки;
  • контрольная сумма и размер посчитаны по тому самому архиву, который заливаете;
  • manifest.json лежит рядом с zip;
  • в папку Яндекс.Диска сначала уходит zip, манифест — последним.

Это можно автоматизировать. Для Unity есть шаг сборочного конвейера, который после архивации сам кладёт рядом с архивом готовый manifest.json: считает контрольную сумму, берёт размер, версию и имя продукта из настроек проекта и путь к exe от корня сборки. Разработчику не нужно считать ничего руками — собрал билд и залил два файла. Шаг ставится после шага архивации, у архивации при этом должен быть выключен фоновый режим, иначе к моменту генерации манифеста архива ещё не существует. Единственный параметр шага — отложенное применение (rolloutAfter) в формате UTC.

Ограничения, о которых лучше знать заранее:

  • дельта-обновлений нет — каждый раз качается весь архив целиком;
  • цепочечных миграций между версиями нет — сборки считаются самодостаточными, прыгать через версии можно. Если билду нужна цепочка миграций сохранений, эта модель не подойдёт;
  • очереди версий нет — манифест это указатель, а не история. Если между опросами стендов вы перезаписали манифест дважды, промежуточную версию стенд никогда не увидит и «доигрывать» её не будет.

Обновление самого Watchdog

Watchdog обновляется тем же способом — из отдельной публичной папки релизов, не из той, где лежат билды экспоната.

  • Включено по умолчанию — свежий стенд обновляется из коробки, настраивать ничего не нужно.
  • Манифест папки релизов опрашивается каждые 5 минут, к интервалу добавляется разброс ±10 %, чтобы парк стендов не бил по одной папке синхронно после общего утреннего включения. Манифест тянется каждый опрос, архив — один раз на релиз на машину.
  • Режимы: Авто (скачал, проверил, подменил свой exe, перезапустился) и Вручную (скачает и остановится, установка — кнопкой «Установить» в окне «О программе»). Переключатель — Настройки → «Обновления» → «Обновление самого Watchdog» → «Режим установки»; применяется по кнопке «Сохранить».
  • Списка версий для самообновления нет — только «текущая» и «доступная».

Наблюдаемое приложение при обновлении не закрывается. Новый экземпляр Watchdog подхватывает уже работающий процесс на первом же тике: второй копии приложения не появляется, статуса «Конфликт цели» не возникает. Если стенд стоял на паузе, после обновления он на паузе и останется.

Обновление откладывается, пока открыт мастер первого запуска или пока любое из приложений качает или апробирует свою версию. Отложенное повторится на следующем опросе.

Что происходит по шагам: проверка свободного места (нужно не меньше четырёх размеров архива) → скачивание с прогрессом в окне «О программе» → сверка контрольной суммы → короткий самопроверочный запуск новой версии, невидимый для оператора → подмена файла exe → перезапуск. Подменяется только файл exe, путь не меняется, поэтому автозапуск, ярлыки, исключения антивируса и сохранённые пароли не ломаются. Новый экземпляр ждёт, пока освободится замок одиночного запуска, — до минуты, поэтому значок в трее может появиться не мгновенно.

Как откатиться руками. Прежний файл лежит рядом:

  1. Закрыть Watchdog: трей → «Выход».
  2. Удалить Watchdog.exe (на стендах, поставленных до 16 сентября 2026, — UnidayWatchdog.exe).
  3. Переименовать <имя>.exe.old в <имя>.exe.
  4. Запустить. Настройки, логи, автозапуск и привязка к приложению не пострадали.

Чтобы стенд не забрал релиз обратно на следующем опросе, верните манифест на старую версию или снимите галочку автообновления.

Если файл .old остался рядом надолго, а версия в подвале окна новая — просто не удалился хвост, обновление применилось.

Как отключить. Настройки → «Обновления» → снять «Включить автообновление Watchdog».

Честные ограничения

  • Транспорт только Яндекс.Диск. Другие облака, S3 и свой веб-сервер сейчас не поддерживаются.
  • Публичная папка = сборка доступна любому, у кого есть ссылка. Это цена отказа от сервера и токенов. Ссылку не индексируют, но защиты содержимого нет — для чувствительных сборок способ не годится.
  • Суточный лимит скачиваний. Яндекс включает его, когда файл качают много раз за сутки; точный порог не публикуется. При сборке в полтора гигабайта и парке стендов в него реально упереться — появится ошибка «превышен лимит на скачивание». Снимается тарифом Яндекс 360 на аккаунте-владельце, ступенчатым раскатом или переездом билдов в другое хранилище. Манифест крошечный, его лимит не трогает.
  • Ограничения публичной папки: до 50 ГБ и до 10 000 файлов.
  • Заливка на Яндекс.Диск — вручную. Автозагрузка архива и манифеста по токену владельца не сделана.
  • Каналы (подпапки на экспонат) сейчас выключены — одному приложению одна публичная папка.
  • Только Windows 10/11 x64.
  • Каждая копия Watchdog обновляется независимо: своя папка, своё состояние, свой резервный файл.

Дальше

© UNIDAY, 2014-2025

ООО «Юнидэй»
г. Саратов, ул. Бахметьевская 44/64, оф. 72
ИНН: 6454142737
КПП: 645401001
ОКВЭД: 62.01 Разработка компьютерного программного обеспечения.
Код вида деятельности: 22.01