Skip to content

About

Analyze GitHub commits

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation


Commit Chronicle

Telegram-бот для инкрементального сбора, постоянного хранения и анализа активности на GitHub. Бот собирает историю изменений, сохраняет ее в СУБД SQLite, мгновенно генерирует компактные отчеты (JSON) для передачи в контекстное окно LLM и поддерживает обновление данных в реальном времени через вебхуки GitHub.


Ключевые возможности и архитектура

1. Постоянное хранилище коммитов и инкрементальная синхронизация

Вместо летучего кэширования запросов бот использует постоянные таблицы tracked_repos (отслеживаемые репозитории) и commits (атомарные записи коммитов с деталями измененных файлов):

  • Холодный запуск (Backfill): При первой проверке или принудительном сбросе (needs_full_resync) бот скачивает полную историю за период глубиной max_backfill_days (по умолчанию 2 года).
  • Инкрементальный добор (Delta-sync): Последующие проверки запрашивают у GitHub GraphQL API только изменения с момента последнего известного коммита (last_synced_sha / last_synced_at), минимизируя накладные расходы на сетевые запросы и лимиты токенов API.

2. Мгновенный отклик «Fast-Path» (0.1 секунды)

Если данные по запрашиваемому пользователем профилю (или конкретному репозиторию) обновлялись недавно (в пределах настроенного fast_path_max_age, например, последние 120 секунд), бот мгновенно извлекает и компилирует отчет прямо из локальной СУБД SQLite, минуя очередь фоновых задач Arq. Сразу после отправки отчета бот асинхронно запускает тихую фоновую досинхронизацию (silent_background_sync), чтобы обновить данные к следующему запросу без отправки дублирующих уведомлений в чат.

3. Обработка событий в реальном времени (GitHub Webhooks)

Бот может выступать в роли приемника вебхуков GitHub:

  • Тонкий вебхук-сервис (aiohttp): Принимает push-события от GitHub, проверяет подпись X-Hub-Signature-256 и мгновенно регистрирует задачу в очереди воркеров, отвечая серверу GitHub менее чем за 50 мс.
  • Асинхронная обработка коммитов: Воркер Arq разбирает пуш, фильтрует коммиты по отслеживаемому автору, добирает детали измененных файлов через REST API и сохраняет их в базу данных.
  • Safety-Net Реконсиляция (Cron-задача): Раз в 6 часов воркер выполняет фоновую сверку метаданных репозиториев, работающих в режиме вебхуков. Если push-событие было утеряно из-за сетевого сбоя или даунтайма, кросс-проверка обнаружит расхождение по дате pushed_at и автоматически дозагрузит пропущенные коммиты.

4. Интерактивный UI с пагинацией страниц

  • Команда /repos: Показывает список всех отслеживаемых репозиториев пользователя с инлайн-кнопками включения/отключения отслеживания (is_active). Списки клавиатур автоматически разбиваются на страницы ( пагинируются), предотвращая падение по лимитам размера сообщений Telegram.
  • Интерактивный запуск: При нажатии кнопки «📊 Мой анализ» бот выводит меню выбора репозиториев. Пользователь может точечно проанализировать один конкретный репозиторий или весь профиль целиком («📁 Все репозитории»).

Стек технологий

  • Язык: Python 3.11
  • Telegram Bot: python-telegram-bot (v20, асинхронный режим)
  • Фоновые задачи & Очередь: arq + Redis
  • База данных: SQLite + SQLAlchemy Core + aiosqlite (WAL-режим для конкурентного чтения/записи)
  • Транспорт GitHub API: httpx (поддержка HTTP/2, раздельные лимиты REST/GraphQL, pre-flight оценка стоимости запросов)
  • Вебхук-сервер: aiohttp

Команды бота

Команда Описание
/start Приветственное сообщение, вывод главного Reply-меню.
/analyze @username Запуск анализа (или вывод меню выбора репозиториев) профиля.
/repos Интерактивный список отслеживаемых репозиториев с инлайн-кнопками.
/status <job_id> Проверка статуса выполнения фонового анализа по его идентификатору.

Быстрый старт

1. Настройка переменных среды

Скопируйте пример файла конфигурации и заполните переменные:

cp .env.example .env

2. Запуск через Docker Compose

Для запуска бота, воркера Arq и Redis в стандартном режиме (опрос по расписанию):

docker compose up -d

Для запуска с поддержкой приема вебхуков GitHub (поднимает дополнительный сервис webhook на порту 8080):

docker compose --profile webhook up -d

3. Ручной запуск (без Docker)

pip install -r requirements.txt

# 1. Запустить Redis
# 2. Запустить воркер фоновых задач:
arq src.worker.settings.WorkerSettings

# 3. Запустить бота:
python -m src.bot.main

# 4. (Опционально) Запустить вебхук-приемник:
python -m src.webhook.server

Конфигурация (.env)

Переменная Обязательна Описание
GITHUB_TOKEN ✅ Основной токен GitHub (с правами public_repo или repo).
GITHUB_EXTRA_TOKENS — Дополнительные токены через запятую для ротации пула токенов.
TELEGRAM_BOT_TOKEN ✅ Токен бота от @BotFather.
REDIS_URL ✅ URL для подключения к Redis (например, redis://localhost:6379/0).
DATABASE_URL — Путь к SQLite: sqlite+aiosqlite:///data/app.db?timeout=20.0.
MAX_WORKERS — Максимальное число параллельных потоков сбора репозиториев (по умолчанию: 10).
MAX_REQUESTS_PER_USER — Суточный лимит запросов на одного пользователя Telegram (по умолчанию: 10).
USER_COOLDOWN_MINUTES — Кулдаун между запросами к одному профилю (по умолчанию: 30 мин).
MAX_BACKFILL_DAYS — Глубина первоначального сбора истории коммитов в днях (по умолчанию: 730).
FAST_PATH_MAX_AGE — Время жизни кэша отчета в секундах для срабатывания Fast-path (по умолчанию: 120).
WEBHOOK_ENABLED — Активация приема push-событий вебхуков (true/false).
WEBHOOK_SECRET — Секретный ключ вебхука для проверки подписи (обязателен, если вебхуки включены).
WEBHOOK_PUBLIC_URL — Публичный URL для GitHub (например, https://yourdomain.com/webhook/github).
OWNER_GITHUB_USERNAME — GitHub-логин владельца бота для автоматической регистрации вебхуков CLI-скриптом.

Формат сжатия JSON (CompactResult)

Для передачи истории изменений в контекстное окно LLM бот преобразует собранные данные в ультракомпактный формат CompactResult, экономящий до 60% токенов:

{
  "user": "torvalds",
  "from": "2024-01-01",
  "ext": [
    ".c",
    ".h"
  ],
  "repos": {
    "torvalds/linux": [
      {
        "d": 74,
        "m": "tcp: fix memory leak in error path",
        "f": [
          [
            "net/ipv4/tcp",
            0,
            12,
            3
          ],
          [
            "include/net/tcp",
            1,
            2
          ]
        ]
      }
    ]
  }
}
  • from — базовая дата отсчета периода.
  • ext — упорядоченный по частоте список уникальных расширений файлов (индекс).
  • d — смещение в днях от базовой даты (from + d дней), исключающее передачу длинных строк дат.
  • m — тема (subject) коммита, усеченная до 72 символов.
  • f — измененные файлы в формате массива: [путь_без_расширения, индекс_расширения_в_ext, добавлено_строк?, удалено_строк?]. Нули в конце опускаются.

Структура проекта

src/
 ├── config.py              # Конфигурация pydantic-settings
 ├── logger.py              # Настройки логов через loguru
 ├── models/
 │    └── models.py         # Модели Pydantic (AnalysisResult, CompactResult) и сжатие
 ├── core/
 │    ├── sync.py           # Инкрементальная синхронизация коммитов с GitHub в БД
 │    ├── report.py         # Сборка отчетов AnalysisResult из локальной СУБД, Fast-path
 │    ├── exceptions.py     # Исключения сборщика (CollectorError, RateLimitError)
 │    └── validator.py      # Валидация юзернеймов GitHub
 ├── github/
 │    ├── client.py         # HTTP-клиент (httpx + HTTP/2), единый транспорт
 │    ├── auth.py           # TokenPool (раздельные бюджеты токенов REST/GraphQL)
 │    ├── ratelimit.py      # Стратегии RateLimiter (оценка стоимости, задержки)
 │    ├── models.py         # Модели данных GitHub (Repository, CommitHeader)
 │    ├── queries.py        # Описание GraphQL-запросов и пакетных алиасов
 │    ├── paginator.py      # Асинхронная постраничная навигация по курсорам
 │    ├── graphql.py        # GraphQL-интеграция
 │    ├── rest.py           # REST-добор файлов коммита
 │    ├── filters.py        # Логика фильтрации (needs_rest_details)
 │    └── service.py        # Публичный фасад GitHubService для проекта
 ├── storage/
 │    ├── database.py       # API работы со SQLite (aiosqlite + SQLAlchemy)
 │    ├── redis.py          # Инициализация клиента Redis
 │    ├── cache.py          # Быстрый кэш Redis (блокировки, суточные лимиты, кулдауны)
 │    └── pubsub.py         # Реализация очередей Pub/Sub для бота
 ├── bot/
 │    ├── app.py            # Фабрика приложения и логика отправки уведомлений
 │    ├── main.py           # Инициализация бота, регистрация хендлеров
 │    ├── keyboards.py      # reply-клавиатуры главного меню и утилиты пагинации инлайн-кнопок
 │    └── handlers/
 │         ├── analyze.py   # Логика Fast-path, старт фоновых задач, инлайн-выбор репозиториев
 │         ├── menu.py      # Обработка текстового Reply-меню бота
 │         ├── status.py    # Просмотр статуса фоновых задач по их ID
 │         └── repos.py     # Обработка команды /repos и инлайн-кнопок управления репозиториями
 └── worker/
      ├── tasks.py          # Задачи фонового воркера (анализ, вебхуки, реконсиляция)
      └── settings.py       # Настройки воркера Arq, инициализация БД, cron-расписание

About

Analyze GitHub commits

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages