Устранение неполадок
Сбои, которые 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.