Усунення несправностей

From docs/uk/TROUBLESHOOTING.md at 4e43843 View on GitHub

Збої, які ketch уже пояснює, зібрано в одному місці, щоб виправлення не доводилося шукати у виводі команди, яка про них повідомила.

ketch list показує ? або latest: offline

latest запитується в джерела кожного пакета. ? означає, що це джерело не відповіло. Звичайна причина — ліміт запитів GitHub без автентифікації (60 запитів на годину), наступна за частотою — репозиторій без релізів або перейменований чи видалений; рядок під таблицею перелічує всі такі пакети. Решта списку при цьому правильна. ketch list -v показує кожен збій; задайте GITHUB_TOKEN (підійде export GITHUB_TOKEN=$(gh auth token)), щоб підняти ліміт запитів.

latest: offline під встановленими пакетами означає, що не відповіло жодне джерело, тому ketch показав те, що знає без мережі. ketch list remote у такому разі завершується з помилкою, бо без мережі йому нічого показати.

Відповіді кешуються на 10 хвилин у ~/.ketch/cache/latest.json, причому лише відповіді: ? запитується знову під час наступного запуску, а версія, знайдена хвилину тому, — ні. Видаліть файл, щоб просто зараз запитати все наново. Подробиці — у розділі ketch list довідника команд.

"another ketch process holds the lock"

Команди, що змінюють дерево встановлення (install, upgrade, uninstall, rollback, prune, pin, link, синхронізація lock, self ...), беруть одне блокування на корінь ketch, і друга команда не чекає: вона одразу завершується з кодом виходу 8.

$ ketch install ripgrep
error: another ketch process holds the lock (pid 4242)

pid — це власник блокування: інший термінал, скрипт або застосунок, що викликає ketch усередині свого процесу (тоді це pid самого застосунку, і операція ще триває). Дочекайтеся її завершення й запустіть команду знову. Два процеси ketch, що одночасно пишуть state.json, зберегли б кожен своє бачення без пакета іншого, тому блокування ніколи не пропускається.

Після аварійного завершення лишається ~/.ketch/.lock. ketch читає з нього pid і забирає файл собі, якщо цього процесу вже немає, тож вручну нічого видаляти не треба. Якщо процес із цим pid ще працює, блокування справжнє; ketch doctor повідомляє про файл блокування й каже, чи живий його власник, чи блокування застаріле.

Виконуваний файл Windows заблоковано посеред оновлення

Інший процес запущено з файлу, який ketch збирається замінити. ketch перелічує ці процеси, питає, чи зупинити їх, і в разі згоди надсилає TERM, потім KILL (taskkill /F у Windows); поточний pid ketch ніколи не пропонується. Якщо відмовитися, процеси працюють далі, а заміна йде як раніше — у Windows зайнятий бінарник спершу перейменовується, щоб новий однаково міг стати на його місце.

$ ketch upgrade
testtool 1.0.0 -> 2.0.0
stop 1 process using testtool? [y/N]

Встановлення зупиняється на "ships several binaries sharing its name"

Реліз містить більше ніж один виконуваний файл, що відповідає назві пакета (rtok-cli і rtok-hook для пакета rtok), жоден із них не називається точно як пакет, у маніфесті немає запису bin, і не було термінала, щоб запитати, — вивід через пайп, CI або запуск із --yes. Нічого не встановлюється.

$ ketch install owner/rtok --yes
error: `rtok` ships several binaries sharing its name (rtok-cli, rtok-hook) and none is named `rtok`; ...

Передайте --bin з потрібним файлом — ketch install owner/rtok --bin rtok-cli, термінал для цього не потрібен, — або запустіть ту саму команду в терміналі без --yes і виберіть варіант зі списку. В обох випадках вибір запам'ятовується в state.json, використовується під час кожного оновлення й копіюється в ketch.lock командою ketch lock, тож ketch sync повторює його на іншій машині. Або вкажіть бінарник у власному маніфесті, який має пріоритет над реєстром:

# ~/.ketch/manifests/rtok.toml
name = "rtok"
source = "github:owner/rtok"
bin = [{ name = "rtok-cli" }]

Той самий вибір робиться на macOS, Linux і Windows; порядок описано в розділі bin MANIFESTS.md.

ketch.exe.old досі лежить у каталозі bin

Windows не видаляє файл, з якого запущено робочий образ. self upgrade перейменовує запущений ketch.exe на ketch.exe.old, і видалення цієї копії не вдається, доки процес не завершиться. Наступний ketch self upgrade або ketch self install видаляє її. ketch doctor називає цей файл, якщо він ще на місці; видаліть його вручну, коли з нього нічого не буде запущено.

Заміна, яка падає з Access is denied (os error 5) на самому ketch.exe, — це короткочасне блокування, зазвичай антивірус перевіряє новий файл. Перейменування й копіювання повторюються впродовж частки секунди. Якщо блокування тримається довше за ці повтори, відновлюється попередній бінарник.

Якщо новий бінарник або отримання списку процесів так і не завершуються, ketch зупиняє цей процес і повідомляє про це, зазначаючи його pid, якщо процес устиг створитися. Запуск, який так і не повернувся, не має pid, який можна зупинити; повідомлення каже, що очікування перервано. Якщо таке стається з перевіркою версії після заміни, попередній бінарник зберігається.

brew upgrade не оновлює сам ketch

Homebrew зберігає лише бінарник початкового завантаження; ketch, який він встановив, — це ketch, завантажений і перевірений самим ketch. Після оновлення cask передайте керування явно:

brew upgrade --cask ketch
ketch self upgrade

ketch self update залишено як аліас, тож наявні скрипти працюють далі.

ketch self upgrade каже, що ketch керується mise

ketch, встановлений через mise use -g github:pyrlyn/ketch, лежить у дереві встановлення mise, у каталозі з назвою своєї версії. Перезапис цього бінарника змусив би mise повідомляти версію, якої вже немає на диску, тому ketch відмовляється. Або дозвольте mise оновити його:

mise upgrade

або один раз передайте ketch самому собі, після чого ketch self upgrade працює, а копія mise слугує лише для початкового завантаження:

ketch self install

Запис реєстру конфліктує або не проходить перевірку

Конфлікти назв і аліасів фатальні в ketch registry validate (щоб вони не потрапили до реєстру) і є попередженнями в ketch update (щоб одна погана тека ніколи не ламала робочу копію). З кореня клону реєстру:

ketch registry validate .
ketch registry validate . --fixture ./ci/fixtures --changed ripgrep --changed fd

У репозиторії ketch-registry за рішенням власника немає CI (plan.md F2), тому перевіряйте локально й тримайте встановленим pre-push хук із REGISTRY.md.

Нотаризація падає під час запуску релізу

Крок Notarise у release.yml (з .github/build-check.yml) запускається, лише коли змінна репозиторію KETCH_NOTARIZE дорівнює true, і тоді він радше впаде, ніж випустить непідписану збірку: мають існувати три секрети — APPSTORE_CONNECT_KEY (.p8 у base64), APPSTORE_CONNECT_KEY_ID, APPSTORE_CONNECT_ISSUER_ID. Smoke-тесту потрібно, щоб spctl повідомляв source=Notarized Developer ID; до голого бінарника Mach-O не можна прикріпити тікет (staple), тому Gatekeeper перевіряє його тікет онлайн. Див. розділ Releasing в AGENTS.md і tests/release-workflows.sh.