Введение
Как у организации, создающей вручную несколько качественных сайтов в год, у нас быстро возникла необходимость извлечения максимальной выгоды из определенного набора базовых средств. Несмотря на то, что некоторые из них были публичными или аутсорсными, как, например, наш фреймворк Wonderwp или библиотека pew.js, остальные мы бы хотели по возможности оставить приватными.
Главным техническим средством в наших процессах сборки является Composer. Мы используем его из-за удобства управления нашими зависимостями, поэтому мы бы очень хотели, чтобы он позаботился и о наших приватных плагинах. Поэтому первым нашим шагом стало изучение официальной документации composer относительно приватных репозиториев. Ниже приведена некоторая квинтэссенция информации, как мне кажется, релевантной для нашей ситуации:
По умолчанию, когда вам требуется установить зависимость, первым делом composer будет искать ее в своем собственном индексе packagist. Если ваша библиотека или репозиторий отсутствует в этом индексе, как в случае с приватными репозиториями, вы должны показать composer’у, где их можно найти, с помощью раздела repositories в вашем файле composer.json.
У вас есть выбор между разными типами репозиториев, но в нашем случае это либо vcs, либо composer. Другими словами, либо вы добавляете запись vcs для каждой приватной зависимости в ваш файл composer.json, чтобы composer знал, где найти ваши приватные репозитории, либо вы можете создать свой собственный приватный composer.
В наших проектах мы обычно задействуем от 6 до 10 приватных зависимостей. Таким образом, выбрав vcs, нам нужно будет вручную добавить столько vcs-записей, сколько приватных зависимостей мы задействовали. Как это выглядит, можно посмотреть в этом примере. Эти vcs-записи должны содержать полный GitHub-путь, а машина, которая будет выполнять вызов composer install, обязательно должна быть аутентифицирована на GitHub ключом ssh для получение доступа к извлечению пакетов. Как видите, это достаточно трудоемкий процесс, ведь количество работы пропорционально (растущему) списку наших приватных пакетов. Но наверняка существует более удобный способ.
Оказалось, composer — это и есть тот самый более удобный способ. Я не знаю, читали ли вы соответствующий параграф в официальной документации, я, в свою очередь, после прочтения не смог похвастаться полным пониманием происходящего. Но так как это больше всего остального походило на то, что мы искали, я решил попробовать, и вот что из этого получилось.
Trying out to make a private composer index
Создаем индекс для приватного composer’а
Как я уже говорил выше, когда я впервые прочитал документацию, я был немного сбит с толку. Но я был полон уверенности, что разберусь что к чему, стоит только начать работу. Итак, сначала нам нужно создать файл packages.json, в который мы поместим всю информацию о приватных репозиториях, а затем добавим ссылку на этот файл в наш файл composer.json, чтобы composer тоже знал о них.
Также я обратил внимание на информацию о том, что называлось определением минимального пакета (minimal package definition). Выглядит это примерно так:
{
“name”: “smarty/smarty”,
“version”: “3.1.7”,
“dist”: {
“url”: “http://www.smarty.net/files/Smarty-3.1.7.zip”,
“type”: “zip”
}
}
Что можно приблизительно перевести как следующее: “Composer, если потребуется smarty/smarty версии 3.1.7, zip можно найти здесь. Часть dist также может являться URL размещенного на виртуальном узле git-репозитория, но это, вероятно, больше про проприетарные приватные пакеты.
Итак, чтобы создать наш файл packages.json, нам нужно составить список определений пакетов. Для каждой приватной библиотеки, которую мы собираемся использовать, мы должны добавить одно определение пакета под каждый номер версии (и их количество может быть довольно большим).
Заметная разница между репозиториями vcs и zip заключается в том, что вам также необходимо указать в части dist номер ссылки, который на самом деле является id коммита. И это очень важно, потому что необходимость следить за правильностью и актуальностью этой ссылки, а также то, что для каждой версии библиотеки необходимо отдельное определение пакета, ясно намекают, что нам нужен такой инструмент, как private packagist или satis, для автоматизации сборки packages.json, что необходимо, чтобы сделать эту фичу composer’а пригодной для экплуатации.
Без автоматизированного решения вам приходится заниматься редактированием файла packages.json каждый раз, когда вы добавляете новую версию в один из ваших репозиториев, и, что еще хуже, каждый раз, когда вы добавляете новые коммиты в любую версию, чтобы обновить номер версии. Делать все это вручную — чистой воды безумие.
Автоматизация сборки
Я искал решение для автоматизации сборки packages.json, и, просматривая различные источники, быстро нашел два возможных (и очень популярных) варианта: private packagist и satis. Во время моих исследований private packagist был только зарелижен и не был бесплатным для такой организации, как наша. По этой причине я решил попробовать satis (не могу не отметить, что мне очень нравится решать такие рабочие проблемы, проводить исследования, путем проб и ошибок, поэтому это решение я принимал с энтузиазмом).
Private packagist был создан Хорди Богджано (Jordi Boggiano) и Нильсом Адерманном (Nils Adermann), создателями Composer. Они регулярно работают над улучшением своего продукта, который помогает создателям пакетов размещать свои приватные репозитории так же, как вы делаете это на опенсорсном packagist.org, чего мы и хотели в самом начале. Но все таки для сперва им нужно заплатить, чтобы попробовать его и узнать, действительно ли качество их услуг будет для вас лучшей альтернативой, чем заниматься всем этим самостоятельно.
Но если вы такие же любители приключений, как и я, то читайте дальше :)!
Установка Satis
Как описано в документации, чтобы установить satis, вам нужно запустить: composer create-project composer/satis:dev-master --keep-vcs
.
Команда satis
Satis можно запустить командой со следующим форматом: php bin/satis build <файл-конфигурации> <выходной-каталог>
Как вы можете заметить, эта команда состоит из трех частей. Сначала вам нужно указать путь к исполняемому файлу satis, затем вам нужно указать, какой файл конфигурации вы хотите использовать (обычно это файл satis.json, о котором мы поговорим в следующем абзаце), и, наконец, выходную папку, в которую он сгенерирует все необходимые файлы для работы вашего приватного composer, одним из которых будет файл packages.json. Он также сгенерирует веб-страницу, на которой будут представлены все ваши доступные пакеты, номера доступных версии и так далее.
Выходной каталог должен быть доступен онлайн, чтобы была возможность использовать его URL в разделе repositories файла composer.json для нашего проекта. Чтобы избежать https-варнингов на URL, который вы собираетесь использовать, лучше настроить https, например.
Файл satis.json
Файл satis.json нужен для конфигурации satis, которая в целом заключается в передаче ему информации о месте расположения ваших приватных пакетов, чтобы он мог находить их и работать с ними. В документации есть информация о доступных параметрах. В моем файле я перечислил все GitHub URL моих приватных пакетов и посредством параметра “require-all”: true указал, что хочу собрать каждую ветку, которую Satis найдет в них. Я дам ссылку на мой файл satis.json чуть ниже.
Сейчас же мы на том этапе, когда у нас есть команда satis, управляемая настроенным файлом statis.json, который генерирует индекс для нашего приватного composer’а. Но мы все еще должны вручную запускать команду satis каждый раз, когда мы хотим обновить наш индекс. В идеале мы могли бы автоматизировать запуск команды каждый раз, когда мы проищводим коммит в любой из наших репозиториев.
Для этого нам нужно подготовить скрипт, который будет вызываться через вебхуки GitHub (или эквивалентные) каждый раз, когда мы отправляем новые коммиты или новые теги версии. Вся работа этого скрипта будет заключаться в выполнении команды satis build для повторной генерации нашего приватного индекса composer.
Скрипт для обновления индекса
Я добавил скрипт обновления в zip файл, прилагаемый к этой статье.
Давайте посмотрим, что в нем нужно конфигурировать. На 9-й строке у вас есть массив $config, где вам нужно указать, где находится ваш исполняемый файл satis (это самая первая часть команды сборки statis), где находится ваш файл satis.json (это вторая часть) и вы указываете, куда будет генерироваться индекс packagist (это третья часть).
Это единственные конфигурации, которые вам нужно произвести. Эти аргументы будут использоваться для вызова команды satis build
, которую затем этот скрипт для вас выполнит.
Выполнение обновления может быть довольно долгим, и из этого факта мы можем сделать два следующих вывода:
Во-первых, нет смысла перестраивать весь индекс со всеми вашими приватными пакетами, если вы запушили только один из них. Мы должны рассмотреть возможность частичной пересборки.
Во-вторых, поскольку мы не знаем, сколько времени это займет, неплохо было бы настроить какое-то уведомление, чтобы мы знали, когда скрипт заканчивает работу. Это важно, потому что его завершение является сигналом того, что теперь вы можете выполнить обновление composer из своего проекта, чтобы получить актуальные версии ваших приватных пакетов.
Вебхуки
Разместите скрипт обновления в сети, где к нему можно будет получить доступ по URL, например. Мы будем использовать этот URL в качестве таргета для наших вебхуков.
Чтобы настроить вебхук в GitHub, вам нужно перейти в один из ваших репозиториев, открыть settings / webhooks и добавить туда новый вебхук, а затем указать, что вы хотите делать запрос к URL вашего удаленного скрипта обновления на https://yourprivatecomposer.com/satis_webhook.php по кадому push-событию.
Принимая во внимание частичные обновления индекса, в зависимости от того, как настроен вебхук, мы можем заранее знать, какого репозитория касаются изменения, и предоставлять эту информацию скрипту, чтобы он пересобирал только те части индекса, которые нужно. Пуш коммитов в репозиторий может означать, что мы добавили некоторые коммиты к существующему номеру версии или создали новый номер версии.
У Satis есть параметр –repository-url
, который нужен, чтобы приказать Satis сосредоточиться на сканировании только этого конкретного репозитория. Мы связали наши вебхуки с этим параметром, чтобы все вебхуки содержали имя репозитория в специальном параметре, например. В случае с GitHub-вебхуками вам может не понадобиться передавать параметры в URL, потому что вы также получаете json со всей необходимой информацией. Вся идея состоит в том, чтобы, когда скрипт обновления получал вебхук, он знал URL репозитория, который он должен обновить. Это улучшение ускорило выполнение нашего скрипта в 20 раз (потому что на то время у нас было около 20 приватных репозиториев), так что, это колоссальное улучшение производительности.
Уведомление
Поначалу, когда скрипт обновления запускался, я был более чем уверен в том, что он запускается должным образом благодаря вебхукам, но я понятия не имел, завершился ли он, или все еще работает. Таким образом, я наудачу запускал composer update в своем проекте, и в половине случаев он выдалвал мне “нечего обновлять или устанавливать”, а в другой он начинал обновлять или устанавливать обновленные зависимости.
Чтобы не заниматься этим бессмысленным выжиданием, я настроил простое уведомление в выделенном канале, которое предупреждало всех, кто следит за этим каналом, о том, что индекс одного пакета был обновлен и теперь доступен для всех. Так дела пошли намного лучше, и я настоятельно рекомендую вам сделать что-то подобное в вашей собственной среде.
Ссылка на ваш приватный packagist внутри ваших проектов
Теперь, когда у вас есть доступный в онлайне индекс приватного composer, откройте файл composer.json вашего проекта и найдите раздел repositories. Затем добавьте запись с типом composer и URL вашего индекса подобно тому, как показано ниже:
“repositories”: [{
“type”: “composer”,
“url”: “https://wpackagist.org”
},
{
“type”: “composer”,
“url”: “https://yourprivatecomposer.com”
}]
Заключение
Хостинг собственного приватного packagist может оказаться довольно сложной задачей, если вы никогда раньше этим не занимались. Я надеюсь, что это небольшое руководство поможет облегчить этот процесс. Например, поскольку я не был специалистом по composer, мне потребовалось несколько дней исследований, проб и ошибок, прежде чем я достиг уровня готовности для продакшена. Это можно рассматривать как неплохую инвестицию. Я очень надеюсь, что благодаря этой статье вы разберетесь во всем быстрее, чем я.
И как только вы все настроите и запустите, вашим разработчикам будет намного проще использовать приватные репозитории. Помимо дополнительной строки, которую нужно поместить в раздел репозиториев вашего проекта, запрос приватных зависимостей будет почти таким же простым, как и публичных. В этом и заключается весь смысл этой затеи.
Приглашаем всех желающих на открытый урок в OTUS «Рекурсия для самых маленьких», на котором обсудим рекурсивные функции, посмотрим практические примеры их использования и узнаем, насколько глубока рекурсивная кроличья нора. Регистрация по ссылке.