По мере распространения Go и Rust появляется всё больше программ, которые состоят из одного бинарника без каких-либо нестандартных зависимостей, и которые мы устанавливаем руками, скачивая релиз с GitHub: либо потому, что данного приложения ещё нет в вашем дистрибутиве, либо потому, что просто хочется всегда иметь актуальную версию, а не ждать, когда её затянут в дистрибутив.
Ставить (а особенно обновлять) такие приложения руками – занятие неблагодарное, особенно когда их количество становится больше одного-двух – и хочется какой-то автоматизации. У меня таких программ около десятка, и довольно долгое время я пользовался различными наколеночными скриптами вроде этого для поддержания их актуальности. Но bash-скрипт – это всё-таки как-то несерьёзно, и поэтому всегда хотелось чего-то более управляемого в виде нормального приложения. Найти что-то готовое, что удовлетворяло бы всем моим потребностям, мне сходу не удалось – поэтому некоторое время назад решил пойти моим излюбленным путём и написать своё приложение под эту конкретную задачу.
binup
Пара недель кодинга по вечерам – и родилась утилита binup. Сегодня я зарелизил версию 1.0.0 и полностью перешёл на неё со своих скриптов. Буду рад, если получившаяся тула будет полезна кому-то кроме меня.
Вот как она работает: вы создаёте конфигурационный файл ~/.config/binup/config.yaml
с примерно следующим содержимым, в котором описываете конкретное приложение (как его найти на GitHub):
tools:
binup:
project: KonishchevDmitry/binup
release_matcher: binup-linux-x64-*
… запускаете binup install
или binup upgrade
– и тула устанавливает, либо обновляет указанные вами приложения.
Работает binup
довольно просто: она нигде не хранит никакую информацию об установленных приложениях, а вместо этого при запуске смотрит на их текущий статус: если нужного бинарника нет, то устанавливает его; если же есть, то пробует запустить приложение с --version
, чтобы определить текущую версию приложения и сравнить её с последним релизом на GitHub. Если же версию определить не удалось (к примеру, программа вовсе может не поддерживать флаг --version
), то binup
ориентируется на время модификации файла, которое при установке приложения задаёт равным времени модификации релиза.
Конфигурация
Вот пример конфигурационного файла со всеми доступными на данный момент опциями:
# Path where to install the binaries (the default is ~/.local/bin)
path: /usr/local/bin
tools:
# Binary name
prometheus:
# GitHub project name
project: prometheus/prometheus
# Changelog URL (will be printed on app upgrade)
changelog: https://github.com/prometheus/prometheus/blob/main/CHANGELOG.md
# Release archive pattern:
# * By default shell-like glob matching is used (https://docs.rs/globset/latest/globset/#syntax)
# * Pattern started with '~' is treated as regular expression (https://docs.rs/regex/latest/regex/#syntax)
release_matcher: prometheus-*.linux-amd64.tar.gz
# Binary path to look for inside the release archive. If it's not specified, the tool name will be used.
binary_matcher: "*/prometheus"
# Post-install script
post: systemctl restart prometheus
# If you have a lot of tools, you may hit GitHub API rate limits for anonymous requests at some moment.
# So it's recommended to obtain GitHub token (https://github.com/settings/tokens) and specify it here.
# No permissions are required for the token – it's needed just to make API requests non-anonymous.
github:
token: $token
Последующее развитие
Развивать её в какой-то полноценный пакетный менеджер вроде Homebrew я точно не планирую, но вот в рамках решения вышеописанной задачи – вполне.
Пока что из наиболее явных потенциальных фичей видится поддержка GitLab, если возникнет такая необходимость (лично у меня пока что нет ни одного приложения с него), а также явно напрашивается генерация какого-то дефолтного release_matcher
‘а в зависимости от текущей ОС и архитектуры.
Прямо сейчас она закрывает все мои потребности, но вполне вероятно, что в процессе использования будут возникать новые – и тогда буду закрывать и их.