From 4ae755c6ae6c08d32f2118e7d821bc87797dbc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20Sonic?= Date: Thu, 30 Jul 2026 16:26:32 +0300 Subject: [PATCH] =?UTF-8?q?fix(ci):=20=D0=BE=D0=B4=D0=BD=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=B1=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=D0=BB=D0=B0=20=D0=BD=D0=B0=20Python=20=D0=B2=D0=BC=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=20=D1=82=D1=80=D1=91=D1=85=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BF=D0=B8=D0=B9=20grep=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(bundle): спрятать CLI за фичей — beta.2 и beta.3 упаковывали не тот бинарь Мой предыдущий фикс (mainBinaryName в #31) фиксом не был. Он изменил только имя выходного файла: бандлер по-прежнему брал headless CLI и просто переименовывал его в tglock. Проверено по содержимому опубликованных артефактов, а не по имени: версия файл в MacOS/ размер признаки CLI признаки GUI beta.1 tglock 17.8 МБ нет ipc.localhost, wry×3206 beta.2 tglock-cli 4.3 МБ tglock-cli×6 нет beta.3 tglock 4.3 МБ tglock-cli×6 нет То есть beta.3 тоже не запускается, и моя же проверка CFBundleExecutable это пропустила, потому что сверяла имя. Настоящая причина найдена воспроизведением локально. Ломается только при явном --target: без него бандлер выбирает GUI, с ним — CLI. Локальная сборка, на которой я объявил фикс подтверждённым, шла без --target, а обе сборки в CI — с ним. Обобщение было неправомерным. Исправление убирает саму возможность выбора: CLI спрятан за фичей cli, которой нет в default. При сборке приложения второго бинаря просто не существует. Проверено против воспроизведённой поломки: до : tglock.exe 1.7 МБ, признаки CLI, GUI нет после: tglock.exe 9.0 МБ, признаки GUI, CLI нет, tglock-cli.exe не собран Проверки переписаны на содержимое: - release.yml распаковывает .app и .deb и ищет ipc.localhost (есть только в GUI) и allow-direct (есть только в CLI). Поймала бы и beta.2, и beta.3; - новая задача CI bundle собирает бандл с явным --target aarch64-apple-darwin и проверяет его так же. Ловит до публикации, а не после; - заодно исправлен шаблон grep для .deb: dpkg-deb -c выводит путь без ./, из-за чего проверка ложно падала на исправной сборке. Команда сборки CLI теперь требует --features cli; обновлены README, ci.yml и release.yml. * fix(ci): одна проверка бандла на Python вместо трёх копий grep Проверка содержимого бандла, добавленная в #33, работала на Linux и давала ложное «в бандле не GUI» на macOS. Причина в BSD grep: в UTF-8-локали он молча не находит строки в бинарных данных там, где GNU grep находит. Из-за этого задача macOS в релизе beta.4 упала уже после загрузки артефактов, а вместе с ней снова пропустилась задача с CLI-бинарями. Сами артефакты beta.4 при этом корректны — проверено скачиванием: в бандле tglock на 20.3 МБ, universal/fat, признаки GUI на месте, признаков CLI нет. Не хватает только tglock-cli-*. Проверка вынесена в scripts/verify_bundle_binary.py и вызывается из всех трёх мест: задачи CI bundle, проверки macOS и проверки Linux в релизе. Один скрипт вместо трёх копий шелл-кода исключает и платформенные различия grep, и расхождение копий между собой. Скрипт проверен на реальных исторических артефактах: beta.4 (исправный) → код 0 beta.3 (сломанный) → код 1, найдены allow-direct и secret-file beta.2 (сломанный) → код 1, то же --------- Co-authored-by: by-sonic <171230345+by-sonic@users.noreply.github.com> --- .github/workflows/ci.yml | 11 ++---- .github/workflows/release.yml | 18 ++-------- Cargo.lock | 2 +- Cargo.toml | 2 +- package.json | 2 +- scripts/verify_bundle_binary.py | 60 +++++++++++++++++++++++++++++++++ tauri.conf.json | 2 +- 7 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 scripts/verify_bundle_binary.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69020da..3cbb6f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,15 +89,8 @@ jobs: - name: The bundled binary must actually be the GUI one run: | exe=$(find target -maxdepth 8 -path '*TGLock.app/Contents/MacOS/tglock' | head -1) - test -n "$exe" || { echo "исполняемый файл бандла не найден"; find target -name 'TGLock.app' -maxdepth 6; exit 1; } - ls -la "$exe" - if ! grep -qa 'ipc\.localhost' "$exe"; then - echo "в бандле не GUI: отсутствует признак ipc.localhost"; exit 1 - fi - if grep -qa 'allow-direct' "$exe"; then - echo "в бандле оказался headless CLI: найден признак allow-direct"; exit 1 - fi - echo "OK: в бандле GUI-бинарь" + test -n "$exe" || { echo "исполняемый файл бандла не найден"; find target -maxdepth 6 -name 'TGLock.app'; exit 1; } + python3 scripts/verify_bundle_binary.py "$exe" headless: name: Headless CLI (no WebView, no Node) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03bfb33..75749c1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,14 +90,7 @@ jobs: test -n "$app" || { echo "TGLock.app не найден"; exit 1; } exe="$app/Contents/MacOS/tglock" test -f "$exe" || { echo "нет $exe:"; ls -la "$app/Contents/MacOS/"; exit 1; } - ls -la "$exe" - if ! grep -qa 'ipc\.localhost' "$exe"; then - echo "в бандле не GUI: отсутствует признак ipc.localhost"; exit 1 - fi - if grep -qa 'allow-direct' "$exe"; then - echo "в бандле оказался headless CLI: найден признак allow-direct"; exit 1 - fi - echo "OK: в бандле GUI-бинарь" + python3 scripts/verify_bundle_binary.py "$exe" - name: The bundled binary must actually be the GUI one if: runner.os == 'Linux' @@ -109,14 +102,7 @@ jobs: dpkg-deb -x "$deb" "$root" exe="$root/usr/bin/tglock" test -f "$exe" || { echo "нет /usr/bin/tglock:"; dpkg-deb -c "$deb" | grep '/bin/'; exit 1; } - ls -la "$exe" - if ! grep -qa 'ipc\.localhost' "$exe"; then - echo "в .deb не GUI: отсутствует признак ipc.localhost"; exit 1 - fi - if grep -qa 'allow-direct' "$exe"; then - echo "в .deb оказался headless CLI: найден признак allow-direct"; exit 1 - fi - echo "OK: в .deb GUI-бинарь" + python3 scripts/verify_bundle_binary.py "$exe" cli: name: Headless CLI ${{ matrix.platform }} diff --git a/Cargo.lock b/Cargo.lock index 480f923..450083a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3553,7 +3553,7 @@ dependencies = [ [[package]] name = "tglock" -version = "2.0.0-beta.4" +version = "2.0.0-beta.5" dependencies = [ "aes", "cipher", diff --git a/Cargo.toml b/Cargo.toml index 28494e0..98df921 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tglock" -version = "2.0.0-beta.4" +version = "2.0.0-beta.5" edition = "2021" rust-version = "1.88" description = "Telegram unblock via local WebSocket tunnel" diff --git a/package.json b/package.json index f3412f0..a859899 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tglock-ui", "private": true, - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "type": "module", "scripts": { "dev": "vite --port 1420", diff --git a/scripts/verify_bundle_binary.py b/scripts/verify_bundle_binary.py new file mode 100644 index 0000000..7e80c03 --- /dev/null +++ b/scripts/verify_bundle_binary.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Проверяет, что в бандл приложения попал GUI-бинарь, а не headless CLI. + +Зачем это существует. В v2.0.0-beta.2 и v2.0.0-beta.3 бандлер Tauri упаковал +`tglock-cli` как исполняемый файл приложения, и оно не запускалось ни на одной +платформе. В beta.3 имя файла было уже правильным — бандлер переименовал CLI — +поэтому проверка имени или `CFBundleExecutable` ничего не заметила. Отличить +можно только по содержимому. + +Почему на Python, а не grep. BSD grep на macOS в UTF-8-локали молча не находит +строки в бинарных данных там, где GNU grep находит: проверка проходила на +Linux и давала ложное «не GUI» на macOS. Один скрипт для всех платформ и для +всех трёх мест, где проверка вызывается, исключает подобные расхождения. + +Использование: + python3 scripts/verify_bundle_binary.py <путь-к-бинарю> +""" + +import sys + +# Присутствуют только в GUI: строка CSP из tauri.conf.json и имя движка WebView. +GUI_MARKERS = (b"ipc.localhost", b"wry") +# Присутствуют только в CLI: имена флагов clap. +CLI_MARKERS = (b"allow-direct", b"secret-file") + + +def main(argv: list[str]) -> int: + if len(argv) != 2: + print(f"использование: {argv[0]} <путь-к-бинарю>", file=sys.stderr) + return 2 + + path = argv[1] + try: + with open(path, "rb") as handle: + data = handle.read() + except OSError as error: + print(f"не удалось прочитать {path}: {error}", file=sys.stderr) + return 1 + + found_gui = [marker.decode() for marker in GUI_MARKERS if marker in data] + found_cli = [marker.decode() for marker in CLI_MARKERS if marker in data] + + print(f"файл: {path}") + print(f"размер: {len(data) / 1048576:.1f} МБ") + print(f"GUI: {found_gui or 'признаков нет'}") + print(f"CLI: {found_cli or 'признаков нет'}") + + if found_cli: + print("ОШИБКА: в бандле headless CLI вместо приложения", file=sys.stderr) + return 1 + if not found_gui: + print("ОШИБКА: это не GUI-бинарь, признаков GUI нет", file=sys.stderr) + return 1 + + print("OK: в бандле GUI-бинарь") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/tauri.conf.json b/tauri.conf.json index 9ebb014..8d56135 100644 --- a/tauri.conf.json +++ b/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "TGLock", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "identifier": "com.bysonic.tglock", "mainBinaryName": "tglock", "build": {