python

Как устроен поиск и парсинг ченьджлогов в AllMyChanges

  • вторник, 30 июня 2015 г. в 02:10:57
http://habrahabr.ru/company/allmychanges/blog/261341/

Хотите заглянуть вовнутрь и узнать, как устроен AllMyChanges.com? Сегодня я немного расскажу вам, как работает наш робот и почему ему удается так хорошо находить информацию о релизах.

На самом деле, весь наш робот, это просто набор функций.
Поиск и обработка ченьджлогов состоит из нескольких этапов:

  1. надо понять, каким образом получать данные по урлу;
  2. использовать выбранный метод, чтобы скачать данные на диск;
  3. пройтись по скачанным файлам и извлечь из них куски, которые имеют номер версии и описание;
  4. понять, какие куски реально являются частью ченьджлога, а какие – просто мусор;
  5. сложить найденное добро в базу.

Части 1,2 и 5 вполне себе механические и не требуют от робота особого интеллекта.

Получение данных


В предыдущей статье я упоминал о том, что AllMyChanges поддерживает несколько различных источников данных. Во-первых, он умеет выкачивать из из Git и Mercurial. Во-вторых — умеет скачивать HTML страницы, как по одной, так и рекурсивно обходя весь сайт. Ну и в-третьих, наш робот может скачивать некоторую информацию из App Store и Google Play.

На первом этапе, мы, согласно неким эвристическим правилам, определяем, какую функцию вызывать на этапе номер два. Этот выбор, если он был успешен, запоминается в базе, чтобы его не приходилось делать каждый раз.

Во время скачивания, робот либо просто складывает файлы на диск, либо производит дополнительную их обработку. Так, забирая данные через GitHub Releases API, он формирует из них файл в Markdown формате. Примерно то же самое происходит с данными, вынимаемыми из сторов или истории VCS.

Извлечение


Harvesting New Potatoes

Извлечение данных дело непростое. Особенно, когда дело касается больших репозиториев с кучей файлов. Ведь каждый из них нужно обойти, и если есть подходящий парсер, то распарсить и поискать части, имеющие отношение к релиз-нотам.

На данный момент, сервис поддерживает три основных формата файлов:

  • Markdown;
  • reStructured Text;
  • HTML.

Но за счет того, что этапы обработки не зависят друг от друга, можно легко добавлять, как новые функции для скачивания данных, так и расширять список поддерживаемых форматов.

Чтобы роботу было проще, можно его направить в нужное место файловой системы, используя дополнительные настройки. Для этого, при добавлении в сервис нового пакета, можно указать список директорий и файлов где следует искать ченьджлог, или список директорий, которые лучше обходить стороной.

К примеру, вы знаете, что у проекта есть поддиректория с документами, и ченьджлог надо искать там. В таком случае, в поле «search list», вписываем docs/, и робот будет искать только там. Если же вы не знаете, где точно следует искать, но знаете, что папке src/ ничего про релиз-ноуты точно нет, тогда стоит добавить эту директорию в поле «ignore list».

Постобработка


sorting!

Самое интересное начинается, когда получены какие-то кусочки данных, которые могут представлять собой ченьджлог. Тут то и начинается основная магия. Сложность заключается в том, что не всегда можно сказать наверняка,
относится ли извлеченный текст к ченьджлогу или нет. Конечно, если у него в метаданных записано, что он извлечен из файла c названием ChangeLog.md, то это не составит труда. Но к сожалению, так бывает не всегда.

Поэтому, для определения того, является ли номер и описание версии частью ченьджлога, или данных кусок данных был извлечен по ошибке, робот AllMyChanges использует ряд эвристических правил.

Для начала, все извлеченные куски группируются по файлам из которых они были извлечены, потом по директориям и так далее. Для каждой группы производится оценка вероятности того, что она может являться ченьджлогом. Оцениваются имена файлов и директорий, и так же суммарное количество кусков, которые в них содержатся.

Это нужно для того, чтобы корректно обрабатывать релиз-ноуты, разбросанные по разным файлам. Такие, например, как у Django: …tree/master/docs/releases

Далее, убираются дубликаты, которые могут возникать по самым разным причинам. Наиболее частая причина — сложная структура внутри документа, где одна и та же версия упоминается в заголовках разного уровня.

Так же, на этапе пост-обработки производится вычисление дат релиза, если конечно они указаны в файле. Тут тоже действует определенное эвристическое правило — если у всех версий в файле даты релиза присутствуют, а у одной из версий нет, значит её надо считать ещё не выпущенной в свет. Такая версия помечается, как «Unreleased».

Кстати, о датах. AllMyChanges держит для каждой версии библиотеки две даты: дату релиза и дату обнаружения. Очень часто, в письмах уведомлениях указаны обе эти даты, и они различаются. «Дата релиза», это всегда та дата, которая указана в первоисточнике. Иногда её может не быть, иногда она может быть даже в будущем, тут могут быть любые чудеса. «Дата обнаружения» же, соответствует тому времени, когда наш робот впервые нашел эту версию. Дата обнаружения есть всегда, и если при этом в первоисточнике не указана «дата релиза», то вместо неё будет использована «дата обнаружения».

Для чего нужно две даты? В первой мы фиксируем то, что записано в документе, вторую же используем для того, чтобы знать, нужно ли уведомлять пользователей о выходе новой версии.

Представьте себе такую ситуацию. Русский разработчик некой библиотеки запилил новую версию с красивым номером 1.2.3 как раз под новый год. Проставил ей дату релиза 2015-01-01 и, так и не запушив на GitHub, отправился баиньки. Проснувшись и протрезвев 7 января, он решает таки сделать git push.

Что произойдет, когда робот AllMyChanges увидит версию 1.2.3 в репозитории? Правильно! Он зафиксирует, что дата релиза у неё 2015-01-01, но в качестве даты обнаружения проставит 2015-01-07. Нужно это для того, чтобы при формировании на следующий день дайжеста, в него попала эта версия 1.2.3. И она должна попасть в дайжест даже несмотря на то, что дата релиза у неё проставлена старая. Таким образом вы получите уведомление о выходе обновления, несмотря ни на что и вопреки всему :)

Всё это позволяет AllMyChanges прекрасно справляться с поиском информации о релизах во всех труднодоступных местах и доставлять её в ваши инбоксы вовремя.

Вопросы?


Если у вас остались вопросы, не стесняйтесь задавать их в зале, или пишите на support@allmychanges.com. Я с радостью на них отвечу.