По ряду причин я решил зеркалировать свои открытые GitHub-проекты на другие платформы совместной разработки. Сделать это оказалось не так просто. В этой короткой статье описаны трудности, с которыми мне пришлось столкнуться, и итоговое рабочее решение.


Иллюстрация Джона Тенниела


Ранее я пользовался функцией зеркалирования GitLab, которая называется pull mirroring. Она с определенной периодичностью копировала код, теги и обсуждения в issues и pull requests из моих GitHub-репозиториев в GitLab. Но некоторое время назад я заметил, что мои GitLab-зеркала стали отставать от основных репозиториев. Я вошел в GitLab и увидел вот такой неприятный баннер:



Функция pull mirroring исчезла из некоторых моих репозиториев. Включить ее бесплатно более невозможно:


Покупка премиум-поддержки GitLab (Premium Tier) невозможна в России. GitLab запрещает использовать даже ее бесплатную пробную версию. Поэтому я стал искать другие решения для зеркалирования моих GitHub-проектов:

  • Развертывание своего отдельного сервера разработки GitLab или Forgejo мне не подходило: я не хотел размещать свои open-source проекты на изолированном сервере. Это значительно ограничило бы взаимодействие с сообществом и стало бы препятствием для контрибьюторов.

  • Я проверил китайскую платформу Gitee, и мне не понравилась ее ограниченная поддержка английской локализации.

  • Я посмотрел на Radicle, пиринговую сеть для разработки программного обеспечения. Но ее «мощные функциональные возможности, основанные на блокчейне», показались мне слишком уж радикальными.

  • Затем я посмотрел на Codeberg. Эту платформу коллективной разработки поддерживает одноименная некоммерческая организация, продвигающая идеи свободного программного обеспечения (free software). Эти ребята мне нравятся гораздо больше, чем Microsoft, владеющая GitHub. Но в марте 2020 года они отключили функцию зеркалирования на серверах Codeberg из-за нехватки ресурсов. По их словам, «зеркалированные репозитории легко создаются, но потребляют ресурсы вечно» :(

  • Я также проверил SourceHut (спасибо paulmairo за ссылку). Эта платформа мне не подошла, потому что:
    1. Она предоставляет только платные услуги.
    2. Процесс разработки на ней выглядит несовместимым с GitHub: на платформе SourceHut для работы с задачами и кодом проектов используется электронная почта.

  • Я посмотрел на Salsa (спасибо Mic_92 за идею). Это сервер совместной разработки сообщества Debian, который работает на программном обеспечении GitLab. Сначала я зарегистрировал там учетную запись. Несколько дней спустя администратор Salsa активировал ее, и мне удалось скопировать один из моих проектов из GitHub в Salsa. Но оказалось, что функция pull mirroring в Salsa тоже отключена, как и на gitlab.com в бесплатном режиме. Я задал вопрос об этом в их трекере, но, к сожалению, не получил никакого ответа.

  • Затем я создал зеркала для своих GitHub-проектов на GitFlic. Это небольшая российская платформа коллективной разработки, которая сейчас активно развивается. Их служба поддержки разрешила мне создать публичные репозитории и настроить зеркалирование. Кроме того, они довольно оперативно отвечали на вопросы и давали комментарии по обнаруженным проблемам. К сожалению, в GitFlic нет CI и даже нет возможности копировать информацию из issues и pull requests с GitHub. Очевидно, зеркала на GitFlic не стали для меня окончательным решением.

Схема зеркалирования GitHub -> GitFlic


Кстати, я бы предложил команде GitFlic назвать раздел Issues для проектов на платформе не «Проблемы», а «Задачи».

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

Первая идея состояла в том, чтобы сделать эту информацию частью кода. Вскоре я нашел проект gh2md, который это позволяет. Инструмент gh2md выгружает содержимое GitHub issues и pull requests заданного проекта в Markdown-документ.

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


Токен доступа GitHub


Теперь мои проекты содержат файл issues.md с резервной копией всех задач и обсуждений. Можно было бы использовать gh2md в CI, чтобы обновлять issues.md автоматически. Но пока я воздерживаюсь от предоставления скриптам GitHub Actions полного доступа к репозиторию.

В определенный момент мне пришла мысль о CI-скрипте, который генерировал бы pull request с обновлениями файла issues.md. Но вскоре я понял, что это не очень умная идея: такой автоматически созданный запрос приведет к очередному срабатыванию CI-скрипта для обновления issues.md, что создаст еще один pull request, и так далее :) Я решил не изобретать самому себе проблемы и добавил ручное обновление issues.md в список релизных процедур для своих проектов.

Есть и другой способ: можно выгрузить задачи и обсуждения из GitHub в git-хранилище проекта. Это можно сделать с помощью специального трекера git-bug (спасибо Сергею Бронникову за ссылку):


Проект git-bug


В итоге после создания резервной копии информации из GitHub issues и pull requests я решил создать копии своих проектов на Codeberg и затем просто выполнять операцию git push одновременно и для GitHub, и для Codeberg. Платформа Codeberg успешно выполнила разовую миграцию моих проектов из GitHub, даже скопировала все обсуждения и задачи. Так что это было бы идеальным решением для меня, если бы в Codeberg было включено зеркалирование… Увы!

Тогда передо мной возник вопрос: что делать с устаревающей информацией в Codeberg issues? В крайнем случае можно было бы вручную удалять и воссоздавать проекты на Codeberg, чтобы поддерживать актуальность, но такое решение мне совсем не нравилось.


Схема зеркалирования GitHub -> Codeberg


Я стал изучать настройки репозиториев и нашел обходной путь: Codeberg позволяет использовать внешний трекер задач! Я задал ссылку на задачи в GitHub и формат нумерации, отключил запросы на слияние в Codeberg, и теперь зеркала моих проектов просто ссылаются на issues и pull requests в GitHub.


Настройка репозитория Codeberg


Вот это уже более или менее рабочее решение. Если что-то пойдет не так с GitHub, то я пересоздам репозитории в Codeberg, включу в них внутренний трекер и запросы на слияние, после чего анонсирую для сообщества и дистрибутивов GNU/Linux, что разработка моих открытых проектов переведена на эту платформу.


Финальная схема зеркалирования GitHub -> Codeberg


Спасибо за внимание. Буду рад комментариям и предложениям.