Commit Graph
39 Commits
Author SHA1 Message Date
Dushnilin 8ecc3ee685 feat(updates): live operation log with page lock in progress modal
The progress modal faked its steps on a timer because the worker only wrote to syslog. Now every updates_log line is appended to <job>.log (UPDATES_JOB_LOG), the running state advertises log_path, the log survives job completion until the TTL sweep, and the new component_action_log CLI mode serves it from a byte offset. The UI polls it into a monospace panel with auto-scroll, exposes a Copy log button, and the modal cannot be closed while the job runs (only the disabled progress button is shown).
2026-08-14 13:20:33 +03:00
Dushnilin d527b86d4c Fix procd sing-box termination timeout, watchdog backup dir creation, and telegram retry log levels 2026-08-12 13:09:05 +03:00
Dushnilin 4d0eb2ea6a fix(action): use explicit else block in check_tachyon for outdated_same_release 2026-08-11 18:44:54 +03:00
Dushnilin c192eb5e5e fix(updater): inline tag normalization in release_metadata_tsv to prevent ucode order warning 2026-08-11 18:36:44 +03:00
Dushnilin 9b110b226d fix(core): исправить ложное застревание блокировок компонентных действий и отключить всплывающие ошибки при фоновой проверке
- Проверять /proc/<pid>/cmdline при валидации PID (исключает ложное определение dnsmasq/sing-box как владельца блокировки при рециркуляции PID в Linux)
- Добавить автоматическую очистку зависших блокировок старше 300 секунд (TTL)
- При фоновой автоматической проверке обновлений (action == check_update) пропускать занятые блокировки без записи [error] в syslog и появления всплывающих нотификаций
2026-08-10 19:43:30 +03:00
Dushnilin 6cf90e3e84 fix(updates): не выдавать успешное обновление за ошибку "Failed to execute"
Воркер компонентного действия перенаправлял stderr в тот же файл, что и
stdout (2>&1). Действие печатает результат в stdout одним JSON-объектом,
а stderr — предупреждения apk/opkg, вывод init-скрипта при рестарте —
попадал в тот же файл после JSON. Разбор всего файла падал, построчный
фолбэк не находил объекта, и finish_component_job писал синтетический
success: false с последней строкой лога в качестве сообщения.

Особенно надёжно это ломало самообновление Tachyon: install_tachyon
рестартует сервис, будучи предком воркера, поэтому вывод рестарта
гарантированно ложился поверх канала результата.

Теперь stderr пишется в отдельный <job>.out.stderr, он же используется
как источник сообщения, когда воркер действительно умер, не напечатав
результат. Файл убирается вместе с заданием и подметается orphan-очисткой.

Заодно валидация sing-box перестала судить о бинарнике по коду возврата:
popen().close() отдаёт сырой wait-статус, а command_output отбрасывал
stdout при любом ненулевом статусе. `sing-box version` печатает версию и
может завершиться ненулевым кодом или получить сигнал от остановки
сервиса перед установкой — валидация получала "", объявляла рабочий
пакет битым и откатывала установку с exit_code 129 (128+SIGHUP). Добавлен
command_output_lenient, он же чинит показ версии в дашборде.
2026-08-10 05:21:19 +03:00
Dushnilin af2d07b056 fix(updates): установка пересобранных релизов в рамках одного тега
opkg считает пакет уже установленным при равенстве версий, поэтому
пересборка под тем же тегом молча не применялась: задание завершалось
успехом, билд оставался старым. Добавлен --force-reinstall в
pkg_install_files_command (opkg) и в install.sh; apk не тронут, он
всегда пишет переданный файл.

Детект пересборки больше не зависит только от SHA, которого нет в
релизах старше f974e4a0: добавлен отпечаток билда по published_at и
метаданным ipk-ассета, решение вынесено в tachyon_build_differs с
префиксным сравнением SHA разной длины. Отпечаток установленного
билда пишется в state-файл и попадает в extra.

Telegram уведомляет о пересборках: check_notified_updates пропускает
outdated_same_release, дедуп идёт по версии и SHA, текст показывает
короткие SHA вместо пары одинаковых версий.

Кэш проверки обновлений сохраняет current_sha из результата действия
вместо безусловного latest, иначе неудачная установка выглядела как
"актуально".

Фронт пересобран из TS, ручная правка main.js снята. Добавлен
describeSameReleaseBuild с фолбэк-текстом, когда SHA недоступен.
2026-08-09 16:57:10 +03:00
Dushnilin f351164ebc fix(updates): retry apk add up to 10 times on database lock error (exit 227) before failing 2026-08-09 09:22:28 +03:00
Dushnilin 0e16860675 fix(updates): install all tachyon packages in a single apk call to avoid APK database lock (exit 227) 2026-08-09 09:10:05 +03:00
Dushnilin c850633b01 feat(updates): compare commit SHA for same-release build updates 2026-08-09 08:47:11 +03:00
Dushnilin 48e2492c0c fix(updates): clean stale lock directories with rm -rf to unblock update checks 2026-08-09 04:38:08 +03:00
Dushnilin e6e3853f05 fix(errors): перестать глотать сбои записи состояния в пустых catch
Пустых catch в кодовой базе около полусотни, и они не одинаковые. Большинство
выражает намерение: fs.unlink бросает на ENOENT, а вызывающий говорит «пусть
этого файла не будет», и отсутствующий файл это условие уже выполняет; разбор
json в цикле пропускает мусорную строку и берёт следующую. Такие места теперь
несут пояснение, почему пустое тело здесь и есть правильный ответ.

Семь мест к этому классу не относились: там сбой означал потерю состояния, а
дальше код шёл так, будто всё получилось.

Watchdog писал через пустой catch файл лока перезапуска прокси, шкалу
GOMEMLIMIT после OOM, бэкап конфига и метку keepalive. Не лёгший лок означает,
что следующий тик перезапустит прокси заново, а счётчик rate-limit об этом не
узнает; не записанная метка keepalive заставляет init.d считать watchdog мёртвым
и перезапускать его. Все четыре теперь идут через write_state_file, который
логирует отказ. Метка пишется на каждом тике uloop, поэтому безусловная строка
залила бы syslog именно при переполненной файловой системе — там, где лог нужнее
всего; вместо этого каждый путь сообщает о первом отказе и молчит до следующего
успеха, что заодно делает видимым восстановление.

Контроллер разбирал /etc/sing-box/config.json ради портов http и tproxy и при
неудаче молча брал 4534 и 4530. Watchdog после этого опрашивает не тот порт,
вечно считает прокси нерабочим и лечит его по кругу — при том, что в логе нет
ничего, что связало бы это с конфигом. Разбор вынесен в общую функцию, которая
сообщает о непарсящемся конфиге один раз на процесс.

Telegram молча терял карту callback-токенов: токен уже вшит в клавиатуру к
моменту записи, поэтому провал отдаёт пользователю кнопку, которая на нажатие
ответит «кнопка устарела». Обновление списков молча теряло маркер отложенного
применения nft — списки обновлены на диске и до nftables не доехали никогда,
а строкой выше в лог написано, что маркер сохраняется. urltest молча выкидывал
битое регулярное выражение из конфига пользователя, отчего группа тихо
подхватывала меньше outbound-ов, чем сказано в конфиге.

tests/heal_escalation.sh проверял порядок строк по литералу fs.writefile для
лока и обновлён под новый вызов.
2026-08-08 22:32:09 +03:00
Dushnilin f5fe6a7471 fix(updates): eliminate false same-release update warnings when current version matches latest release 2026-08-07 17:54:29 +03:00
Dushnilin 37c56a3652 fix(updates): validate hex format for remote_sha in same-release update check 2026-08-07 17:07:14 +03:00
Dushnilin 488bbfefd5 fix: комплексный аудит и исправление ucode кодовой базы
Критические исправления:
- safe_proxy_restart: удаление lock-файла после фонового перезапуска
  с защитой от stale lock (>300 сек)
- write_json_file: атомарная запись через tmp+mv вместо прямой
- write_reload_state: атомарная запись через tmp+mv
- state_add_list: отклонение значений с пробелами

Исправления безопасности:
- killall logread заменён на pkill -f 'logread -f'
- SIGTERM→SIGKILL для Telegram и sing-box при остановке
- Recover OOM scale: инкремент +0.05 каждые 10 минут
- nfqueue и byedpi: trap для корректного завершения дочерних процессов
- nfqueue: валидация стратегий и откат при ошибке запуска
- nfqueue: flush mangle_output перед добавлением правил
- Исправлен парсинг exit code в 14 файлах (status & 127)

Улучшения стабильности:
- init.d: trap для start_service/stop_service
- watchdog: signal traps для legacy fallback loop
- lifecycle: логирование ошибок при остановке компонентов
- singbox/priority: SIGTERM→SIGKILL при остановке
- telegram: exponential backoff (1x→300s) при ошибках API
- telegram: process_updates возвращает boolean для отслеживания успеха
- watchdog: кэш proxy port для уменьшения чтения конфига sing-box
- singbox/generator: упрощён atomic_write_json_file
- packages.uc: переупорядочивание apk_version (лёгкие запросы первыми)
- dns/apply: проверка PID sing-box перед настройкой dnsmasq
- server/service: cleanup_orphaned_server_certs перед вызовом
2026-08-06 00:03:51 +03:00
Dushnilin 7b8114bef1 fix: незаустановленные компоненты (zapret/byedpi/zapret2) не возвращают ошибку при check_update
- action.uc: для zapret, zapret2 и byedpi при check_update,
  если компонент не установлен, возвращаем success:true со статусом '' вместо action_fail,
  предотвращая красные toast-уведомления в LuCI
2026-08-04 21:12:01 +03:00
Dushnilin ff627cfb52 fix: FD-cascade при reinstall + SHA версии в UI + тип outdated_same_release
- action.uc: killall logread перед restart_tachyon_after_successful_change,
  предотвращает FD-каскад при reinstall/update (orphan logread pipe FD)
- action.uc: current_sha/latest_sha в ответе check_update для Tachyon
- updates.uc: SHA пробрасывается через кэш проверки обновлений
- fe/types.ts: outdated_same_release добавлен в union статусов,
  поля current_sha/latest_sha в ComponentActionResult,
  AI Watchdog поля в ConfigSection (pre-existing TS2339 fix)
- fe/store.service.ts: outdated_same_release и SHA в состоянии updatesChecks
- fe/initController.ts: рендер SHA hash-badge для outdated_same_release,
  setCheckResult принимает SHA, applyCachedCheckResults/handleCheckResult обновлены
- fe/styles.ts: .sha-info — monospace badge для отображения коммит-хешей
2026-08-04 16:03:07 +03:00
Dushnilin a3de505a9a chore: switch zapret2 repo to Dushnilin/zapret2-openwrt 2026-08-04 14:04:29 +03:00
Dushnilin 2c31a62e4d fix: same-release SHA prefix compare + sing-box generator error detail
- action.uc: compare release target_commitish (full 40-char SHA) with
  installed short SHA by prefix instead of exact match; fixes false
  'same release update found' when commit is actually the same
- runtime.uc: generator_failure_reason now returns the first error line
  instead of the ucode 'Near here ---^' position marker, and logs full
  generator output at debug level on failure for better diagnostics
2026-08-04 11:31:51 +03:00
Dushnilin 22a236e5d1 feat: commit-level version tracking for same-release updates
Backend:
- constants.uc: add TACHYON_COMMIT_SHA constant (placeholder __COMPILED_COMMIT_SHA__)
- build.sh: capture git rev-parse HEAD and sed-replace commit SHA placeholder
- Makefile: same commit SHA sed replacement for OpenWrt builds
- action.uc: modify check_tachyon() to compare installed commit SHA with
  target_commitish from GitHub release, new status 'outdated_same_release'
- action.uc: reuse release_json for both version and commit SHA extraction
- updater.uc: add release_commit_sha helper to extract target_commitish
- updates.uc: extend cacheable status to include outdated_same_release

Frontend:
- main.js: handle outdated_same_release status in renderComponentCard
- main.js: include outdated_same_release in shouldShowInstallAfterCheck
- main.js: include outdated_same_release in applyCachedCheckResults

i18n:
- Add 'Update is available for current release' and 'Update is available
  for current release:' to .pot and .ru.po files

78 tests pass.
2026-08-03 21:35:06 +03:00
Dushnilin 5eef78b877 fix: DNS петля + watchdog автоисправление + централизация file_is_usable
Ключевые изменения:

1. core/helpers.uc: file_is_usable(path, min_bytes) + file_size_value(path)
   для единообразной проверки файлов (минимальный размер порог).

2. singbox/dns.uc: WAN fallback DNS серверы (fallback_wan_main) теперь
   используют прямой UDP без detour — исправлена петля когда
   DNS шёл через мёртвую прокси-секцию.
   Health probes для ВСЕХ DNS серверов (включая DoH) идут direct —
   failover может определить доступность DNS серверов.

3. watchdog.uc: ai_heal_empty_sections() — автообнаружение пустых
   proxy-секций с подписками → запуск subscription_update_async.
   ai_heal_dns_loop() — при обнаружении DNS-петли (dead proxy +
   dead DNS) → временно отключает DNS detour → загружает подписку →
   восстанавливает настройки.

4. Единая file_is_usable: nft/apply.uc, generator_routes.uc,
   components/{updates,action}.uc, config/validator.uc,
   subscription/cache.uc — все используют helpers.file_is_usable.

5. Тест tests/file_usable.sh для проверки helpers CLI.

6. Исправлен components_updater_job.sh mock lib — добавлен core/helpers.uc
2026-08-03 14:07:57 +03:00
Dushnilin ac209457d7 feat: кнопка Переустановить для Tachyon на странице обновлений 2026-07-31 17:34:11 +03:00
Dushnilin 7e64eb10b1 Fix updates: split arch.candidates string into array for zapret2 release resolution 2026-07-30 20:24:17 +03:00
Dushnilin 79ed7b03cf fix: add cortex-a53 fallback for zapret2 generic aarch64 resolution 2026-07-30 18:39:07 +03:00
Dushnilin af620a2f45 fix: исправление резолвинга пакета zapret2 для роутеров и поиск релизов 2026-07-30 17:52:16 +03:00
Dushnilin e9a9ead675 fix(updater): add fallback resolution for sing-box-extended when GitHub API rate-limits 2026-07-28 00:01:04 +03:00
Dushnilin 0eec769a90 fix(updates): fallback filenames without _all suffix to match actual release assets 2026-07-27 12:34:31 +03:00
Dushnilin 7cd48ad5fe fix(updates): порядок объявления функций ucode и автоматический fallback скачивания пакетов (v1.2.29) 2026-07-26 12:54:07 +03:00
Dushnilin 93516e13cd fix(updates): исправление репозитория релизов на Dushnilin/tachyon и добавление HTTP Location fallback (v1.2.29) 2026-07-26 12:47:32 +03:00
Dushnilin 09342e38b3 fix(updates): add fallback to location header for GitHub release tag checks when API rate-limited
- Parse location header from https://github.com/OWNER/REPO/releases/latest directly and via ghproxy mirrors when api.github.com returns rate-limit (403/429)
- Use command_output_from_args in action.uc for shell command captures
2026-07-25 12:43:58 +03:00
Dushnilin 254595c9b4 Исправлено зависание установки из-за блокировок GitHub (добавлены зеркала gh-proxy) и исправлено удаление sing-box при ошибке обновления 2026-07-21 15:16:12 +03:00
Dushnilin 16359d260c fix: исправление проблемы обновления Leadaxe (sing-box-lx) 2026-07-21 10:16:11 +03:00
Dushnilin 28b8d4ceef Fix sing-box binary validation for Leadaxe (lx) and modern alpha builds 2026-07-20 13:26:37 +03:00
Dushnilin e0b70d6b99 feat: добавлена поддержка варианта sing-box Leadaxe (lx) 2026-07-20 08:29:56 +03:00
Dushnilin 46ef97fe89 Release 1.0.6: синхронизировать изменения из upstream и исправить баг фильтра URLTest/Priority 2026-07-14 08:56:31 +03:00
Dushnilin f017d01a52 Рефакторинг кода: дедупликация ucode, исправления shellcheck и глобальное улучшение install.sh 2026-07-13 22:38:24 +03:00
Dushnilin ed9fb7ba5d fix(updates): обеспечение успешной установки пакетов в apk-системах при некритических ошибках apk add 2026-07-13 16:05:59 +03:00
Dushnilin f57dac6b52 refactor(rebrand): полный ребрендинг в Tachyon и перенос служб watchdog/doctor на Ucode 2026-07-13 14:09:38 +03:00
Dushnilin e89a795566 refactor(rebrand): полный ребрендинг в Tachyon и перенос служб watchdog/doctor на Ucode 2026-07-13 14:03:31 +03:00