508 lines
16 KiB
Markdown
508 lines
16 KiB
Markdown
# ALR-Updater
|
||
|
||
Автоматизированный бот для проверки обновлений пакетов и их отправки в репозиторий [alr-repo](https://gitea.plemya-x.ru/Plemya-x/alr-repo).
|
||
|
||
---
|
||
|
||
## Описание
|
||
|
||
ALR-Updater — это модульный бот, предназначенный для автоматического отслеживания обновлений программного обеспечения и автоматического обновления пакетов в репозитории ALR. Система основана на плагинах написанных на языке [Starlark](https://github.com/bazelbuild/starlark), что обеспечивает гибкость и расширяемость.
|
||
|
||
### Принцип работы
|
||
|
||
Бот использует систему плагинов для мониторинга различных источников обновлений:
|
||
|
||
- **GitHub API** — для отслеживания релизов проектов на GitHub
|
||
- **API разработчиков** — для проверки обновлений через официальные API
|
||
- **Веб-хуки** — для мгновенного получения уведомлений о новых версиях
|
||
- **RSS/Atom ленты** — для мониторинга блогов и сайтов проектов
|
||
|
||
Каждый плагин может:
|
||
- Запускаться по расписанию (например, каждый час или день)
|
||
- Обрабатывать входящие веб-хуки
|
||
- Использовать постоянное хранилище ключ-значение для отслеживания состояния
|
||
- Автоматически обновлять файлы `alr.sh` в репозитории
|
||
|
||
### Примеры работы
|
||
|
||
**Discord-bin**: Плагин каждый час опрашивает API Discord для получения ссылки на последнюю версию. При обнаружении изменений он извлекает номер версии из URL и обновляет скрипт сборки.
|
||
|
||
**NodeJS**: Плагин отслеживает релизы на GitHub через API, проверяет доступность новых версий и автоматически обновляет зависимости и ссылки на исходный код.
|
||
|
||
---
|
||
|
||
## Установка
|
||
|
||
### Требования
|
||
|
||
- Go 1.20 или новее
|
||
- Git
|
||
- Доступ к репозиторию alr-repo
|
||
|
||
### Сборка из исходного кода
|
||
|
||
```bash
|
||
# Клонирование репозитория
|
||
git clone https://github.com/your-username/ALR-updater.git
|
||
cd ALR-updater
|
||
|
||
# Сборка
|
||
go build -o alr-updater main.go
|
||
|
||
# Установка (опционально)
|
||
sudo cp alr-updater /usr/local/bin/
|
||
```
|
||
|
||
---
|
||
|
||
## Настройка
|
||
|
||
### 1. Конфигурационный файл
|
||
|
||
Создайте конфигурационный файл на основе примера:
|
||
|
||
```bash
|
||
sudo mkdir -p /etc/alr-updater
|
||
sudo cp alr-updater.example.toml /etc/alr-updater/config.toml
|
||
```
|
||
|
||
Отредактируйте `/etc/alr-updater/config.toml`:
|
||
|
||
```toml
|
||
[git]
|
||
repoURL = "https://gitverse.ru/Xpamych/xpamych-alr-repo"
|
||
repoDir = "/etc/alr-updater/repo"
|
||
|
||
[git.commit]
|
||
name = "ALR Updater Bot"
|
||
email = "bot@example.com"
|
||
|
||
[git.credentials]
|
||
username = "your-username"
|
||
password = "your-token" # Используйте персональный токен доступа
|
||
|
||
[webhook]
|
||
pwd_hash = "$2a$10$..." # Сгенерируйте командой: alr-updater -g
|
||
```
|
||
|
||
### 2. Генерация хеша пароля для веб-хуков
|
||
|
||
```bash
|
||
alr-updater -g
|
||
# Введите пароль и скопируйте полученный хеш в конфигурацию
|
||
```
|
||
|
||
### 3. Создание директории для плагинов
|
||
|
||
```bash
|
||
sudo mkdir -p /etc/alr-updater/plugins
|
||
```
|
||
|
||
---
|
||
|
||
## Создание плагинов
|
||
|
||
### Структура плагина
|
||
|
||
Плагины представляют собой файлы `.star` с кодом на языке Starlark. Пример базового плагина:
|
||
|
||
```python
|
||
# /etc/alr-updater/plugins/discord-bin.star
|
||
|
||
def check_discord_updates():
|
||
"""Проверка обновлений Discord"""
|
||
|
||
# Получение текущей версии из пакета
|
||
current_content = updater.get_package_file("discord-bin", "alr.sh")
|
||
current_version = regex.find(r"version=([0-9.]+)", current_content)
|
||
|
||
# Проверка новой версии через API
|
||
response = http.get("https://discord.com/api/download/stable?platform=linux&format=tar.gz")
|
||
download_url = response.url
|
||
new_version = regex.find(r"/([0-9.]+)/discord", download_url)
|
||
|
||
if new_version != current_version:
|
||
log.info("Найдена новая версия Discord: " + new_version)
|
||
|
||
# Обновление файла пакета
|
||
new_content = regex.replace(
|
||
current_content,
|
||
r"version=[0-9.]+",
|
||
"version=" + new_version
|
||
)
|
||
|
||
updater.write_package_file("discord-bin", "alr.sh", new_content)
|
||
updater.push_changes("discord-bin: обновление до версии " + new_version)
|
||
else:
|
||
log.info("Discord уже актуален: " + current_version)
|
||
|
||
# Запуск проверки каждый час
|
||
run_every.hour(check_discord_updates)
|
||
```
|
||
|
||
### Плагин для GitHub пакетов
|
||
|
||
```python
|
||
# /etc/alr-updater/plugins/github-packages.star
|
||
|
||
def update_github_package(package_name, repo_path, version_prefix="v"):
|
||
"""Универсальная функция для обновления GitHub пакетов"""
|
||
|
||
# Получение последнего релиза
|
||
api_url = "https://api.github.com/repos/" + repo_path + "/releases/latest"
|
||
response = http.get(api_url)
|
||
release_data = response.json()
|
||
|
||
latest_version = release_data["tag_name"]
|
||
if latest_version.startswith(version_prefix):
|
||
latest_version = latest_version[len(version_prefix):]
|
||
|
||
# Получение текущей версии
|
||
current_content = updater.get_package_file(package_name, "alr.sh")
|
||
current_version = regex.find(r"version='([^']+)'", current_content)
|
||
|
||
if latest_version != current_version:
|
||
log.info("Обновление " + package_name + ": " + current_version + " -> " + latest_version)
|
||
|
||
# Обновление версии в файле
|
||
new_content = regex.replace(
|
||
current_content,
|
||
r"version='[^']+'",
|
||
"version='" + latest_version + "'"
|
||
)
|
||
|
||
# Обновление ссылки на архив
|
||
new_content = regex.replace(
|
||
new_content,
|
||
r"https://github\.com/" + repo_path + "/archive/refs/tags/[^)]+",
|
||
"https://github.com/" + repo_path + "/archive/refs/tags/" + version_prefix + latest_version + ".tar.gz"
|
||
)
|
||
|
||
updater.write_package_file(package_name, "alr.sh", new_content)
|
||
updater.push_changes(package_name + ": обновление до версии " + latest_version)
|
||
|
||
def check_fastfetch():
|
||
update_github_package("fastfetch", "fastfetch-cli/fastfetch")
|
||
|
||
def check_nodejs():
|
||
update_github_package("nodejs", "nodejs/node")
|
||
|
||
# Запуск проверок
|
||
run_every.day(check_fastfetch)
|
||
run_every.day(check_nodejs)
|
||
```
|
||
|
||
### Плагин для Python пакетов
|
||
|
||
```python
|
||
# /etc/alr-updater/plugins/python-packages.star
|
||
|
||
def update_python_package(package_name, pypi_name=None):
|
||
"""Обновление Python пакетов через PyPI API"""
|
||
|
||
if not pypi_name:
|
||
pypi_name = package_name.replace("python3-", "").replace("-", "_")
|
||
|
||
# Запрос к PyPI API
|
||
api_url = "https://pypi.org/pypi/" + pypi_name + "/json"
|
||
response = http.get(api_url)
|
||
|
||
if response.status_code != 200:
|
||
log.error("Не удалось получить информацию о пакете " + pypi_name)
|
||
return
|
||
|
||
data = response.json()
|
||
latest_version = data["info"]["version"]
|
||
|
||
# Получение текущей версии
|
||
current_content = updater.get_package_file(package_name, "alr.sh")
|
||
current_version = regex.find(r"version='([^']+)'", current_content)
|
||
|
||
if latest_version != current_version:
|
||
log.info("Обновление " + package_name + ": " + current_version + " -> " + latest_version)
|
||
|
||
# Обновление версии
|
||
new_content = regex.replace(
|
||
current_content,
|
||
r"version='[^']+'",
|
||
"version='" + latest_version + "'"
|
||
)
|
||
|
||
updater.write_package_file(package_name, "alr.sh", new_content)
|
||
updater.push_changes(package_name + ": обновление до версии " + latest_version)
|
||
|
||
# Регистрация пакетов для проверки
|
||
python_packages = [
|
||
"python3-rich",
|
||
"python3-poetry-core",
|
||
"python3-wheel",
|
||
"python3-setuptools-rust"
|
||
]
|
||
|
||
def check_python_packages():
|
||
for package in python_packages:
|
||
update_python_package(package)
|
||
|
||
# Запуск еженедельно
|
||
run_every.week(check_python_packages)
|
||
```
|
||
|
||
---
|
||
|
||
## Запуск
|
||
|
||
### Ручной запуск
|
||
|
||
```bash
|
||
# Запуск с конфигурацией по умолчанию
|
||
alr-updater
|
||
|
||
# Запуск с кастомной конфигурацией
|
||
alr-updater -c /path/to/config.toml
|
||
|
||
# Запуск с другой директорией плагинов
|
||
alr-updater -p /path/to/plugins
|
||
|
||
# Включение отладочного режима
|
||
alr-updater -D
|
||
```
|
||
|
||
### Systemd сервис
|
||
|
||
Создайте файл `/etc/systemd/system/alr-updater.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=ALR Updater Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=alr-updater
|
||
Group=alr-updater
|
||
ExecStart=/usr/local/bin/alr-updater
|
||
Restart=always
|
||
RestartSec=30
|
||
Environment=HOME=/var/lib/alr-updater
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
Создайте пользователя и запустите сервис:
|
||
|
||
```bash
|
||
sudo useradd -r -s /bin/false alr-updater
|
||
sudo mkdir -p /var/lib/alr-updater
|
||
sudo chown alr-updater:alr-updater /var/lib/alr-updater
|
||
sudo chown -R alr-updater:alr-updater /etc/alr-updater
|
||
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable alr-updater
|
||
sudo systemctl start alr-updater
|
||
```
|
||
|
||
### Docker
|
||
|
||
```dockerfile
|
||
FROM golang:1.20-alpine AS builder
|
||
WORKDIR /app
|
||
COPY . .
|
||
RUN go build -o alr-updater main.go
|
||
|
||
FROM alpine:latest
|
||
RUN apk --no-cache add ca-certificates git
|
||
WORKDIR /root/
|
||
COPY --from=builder /app/alr-updater .
|
||
COPY alr-updater.example.toml /etc/alr-updater/config.toml
|
||
CMD ["./alr-updater"]
|
||
```
|
||
|
||
---
|
||
|
||
## Настройка веб-хуков
|
||
|
||
### GitHub веб-хуки
|
||
|
||
1. Перейдите в настройки репозитория → Webhooks
|
||
2. Добавьте новый веб-хук:
|
||
- **URL**: `http://your-server:8080/webhook/github`
|
||
- **Content type**: `application/json`
|
||
- **Events**: `Releases`
|
||
3. Добавьте секрет, соответствующий паролю в конфигурации
|
||
|
||
### Обработка веб-хуков в плагине
|
||
|
||
```python
|
||
# /etc/alr-updater/plugins/webhooks.star
|
||
|
||
def handle_github_release(data):
|
||
"""Обработка веб-хука GitHub релиза"""
|
||
|
||
if data["action"] != "published":
|
||
return
|
||
|
||
repo_name = data["repository"]["full_name"]
|
||
tag_name = data["release"]["tag_name"]
|
||
|
||
# Маппинг репозиториев к пакетам
|
||
repo_to_package = {
|
||
"fastfetch-cli/fastfetch": "fastfetch",
|
||
"nodejs/node": "nodejs"
|
||
}
|
||
|
||
package_name = repo_to_package.get(repo_name)
|
||
if package_name:
|
||
log.info("Получен веб-хук для " + package_name + " версии " + tag_name)
|
||
update_github_package(package_name, repo_name)
|
||
|
||
# Регистрация обработчика веб-хуков
|
||
webhook.github(handle_github_release, password="your-webhook-password")
|
||
```
|
||
|
||
---
|
||
|
||
## Мониторинг и логирование
|
||
|
||
### Просмотр логов
|
||
|
||
```bash
|
||
# Логи systemd сервиса
|
||
sudo journalctl -u alr-updater -f
|
||
|
||
# Логи в файл
|
||
alr-updater 2>&1 | tee /var/log/alr-updater.log
|
||
```
|
||
|
||
### Уведомления в Telegram
|
||
|
||
```python
|
||
# В плагине
|
||
def send_telegram_notification(message):
|
||
telegram_bot_token = "YOUR_BOT_TOKEN"
|
||
chat_id = "YOUR_CHAT_ID"
|
||
|
||
url = "https://api.telegram.org/bot" + telegram_bot_token + "/sendMessage"
|
||
data = {
|
||
"chat_id": chat_id,
|
||
"text": message,
|
||
"parse_mode": "Markdown"
|
||
}
|
||
|
||
http.post(url, json=data)
|
||
|
||
# Использование в функции обновления
|
||
def update_package_with_notification(package_name, new_version):
|
||
# ... логика обновления ...
|
||
|
||
message = "🔄 *ALR-Updater*\n\n" \
|
||
+ "Обновлен пакет: `" + package_name + "`\n" \
|
||
+ "Новая версия: `" + new_version + "`"
|
||
|
||
send_telegram_notification(message)
|
||
```
|
||
|
||
---
|
||
|
||
## Расширенные возможности
|
||
|
||
### Переменные окружения
|
||
|
||
Вы можете использовать переменные окружения вместо файла конфигурации:
|
||
|
||
```bash
|
||
export GIT_REPO_URL="https://gitverse.ru/Xpamych/xpamych-alr-repo"
|
||
export GIT_REPO_DIR="/tmp/alr-repo"
|
||
export GIT_COMMIT_NAME="ALR Updater"
|
||
export GIT_COMMIT_EMAIL="bot@example.com"
|
||
export GIT_CREDENTIALS_USERNAME="username"
|
||
export GIT_CREDENTIALS_PASSWORD="token"
|
||
export WEBHOOK_PASSWORD_HASH="$2a$10$..."
|
||
|
||
alr-updater -E # Использование переменных окружения
|
||
```
|
||
|
||
### Тестирование плагинов
|
||
|
||
```bash
|
||
# Создайте тестовый плагин
|
||
cat > /tmp/test-plugin.star << 'EOF'
|
||
def test_function():
|
||
log.info("Тестовый плагин работает!")
|
||
|
||
# Тест получения файла пакета
|
||
content = updater.get_package_file("fastfetch", "alr.sh")
|
||
log.info("Получен файл пакета, размер: " + str(len(content)))
|
||
|
||
run_every.minute(test_function)
|
||
EOF
|
||
|
||
# Запуск с тестовым плагином
|
||
alr-updater -p /tmp -D
|
||
```
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Частые проблемы
|
||
|
||
**1. Ошибка аутентификации Git**
|
||
```
|
||
Error: authentication required
|
||
```
|
||
Решение: Проверьте правильность токена доступа и имени пользователя в конфигурации.
|
||
|
||
**2. Плагин не выполняется**
|
||
```
|
||
Error executing starlark file
|
||
```
|
||
Решение: Проверьте синтаксис Starlark кода, включите отладочный режим (`-D`).
|
||
|
||
**3. Не удается получить файл пакета**
|
||
```
|
||
Error: no such file or directory
|
||
```
|
||
Решение: Убедитесь, что репозиторий успешно клонирован и пакет существует.
|
||
|
||
### Отладка
|
||
|
||
```bash
|
||
# Включение подробного логирования
|
||
alr-updater -D
|
||
|
||
# Проверка состояния базы данных
|
||
ls -la /etc/alr-updater/db
|
||
|
||
# Проверка Git репозитория
|
||
cd /etc/alr-updater/repo && git status
|
||
```
|
||
|
||
---
|
||
|
||
## Участие в разработке
|
||
|
||
1. Форкните репозиторий
|
||
2. Создайте ветку для новой функции
|
||
3. Внесите изменения
|
||
4. Создайте Pull Request
|
||
|
||
### Структура проекта
|
||
|
||
```
|
||
ALR-updater/
|
||
├── main.go # Основной файл приложения
|
||
├── internal/
|
||
│ ├── builtins/ # Встроенные функции для Starlark
|
||
│ ├── config/ # Конфигурация
|
||
│ └── convert/ # Утилиты конвертации
|
||
├── alr-updater.example.toml # Пример конфигурации
|
||
└── README.md # Эта документация
|
||
```
|
||
|
||
---
|
||
|
||
## Лицензия
|
||
|
||
Этот проект распространяется под лицензией GPL v3. См. файл LICENSE для подробностей.
|