Давным-давно, давным-давно, я впервые вышел на сцену конференции и сказал, что, по-моему, я самый крутой PHP-разработчик в мире. Я на самом деле все еще думаю, что это довольно верно, и если вы будете работать со мной, вы поймете, что я в основном ломаю и чиню вещи примерно в равной степени. Имея это в виду, когда я недавно запустил свой собственный продукт (
BiteStatsвещь, которая автоматически отправляет вам сводку статистики аналитики каждый месяц), я знал, что мне нужен действительно надежный способ развертывания кода. В течение нескольких лет я делал несколько разных вещей, и я часто внедрял эти инструменты с другими организациями или для них, но у меня не так много странного кода в производстве, странно. Я решил, что Phing — это путь, установил его и решил
, что делать дальше.
build.xml
Я создал файл build.xml в корневом каталоге моего проекта, и изначально он содержал только следующее:
<?xml version="1.0" encoding="UTF-8"?> <project name="bitestats" basedir="." default="deploy"> <property name="builddir" value="./build" /> </project>
Этот атрибут по умолчанию указывает, какую задачу нужно запустить, если задача не указана, а тег свойства инициализирует переменную, которая понадобится мне в нескольких местах позже. Фактически это каталог сборки, каталог, который будет использоваться для хранения всех артефактов сборки.
Задачи
Задачи определены в файле сборки внутри тега проекта. У меня есть два очень простых, которые, как мне кажется, есть в большинстве проектов: построить и очистить. Они создают каталог сборки, готовый для использования при выполнении других задач, и удаляют его снова. Так что с учетом этого мой файл теперь выглядит так:
<?xml version="1.0" encoding="UTF-8"?> <project name="bitestats" basedir="." default="deploy"> <property name="builddir" value="./build" /> <target name="clean"> <echo msg="Clean..." /> <delete dir="${builddir}" /> </target> <target name="prepare"> <echo msg="Prepare..." /> <mkdir dir="${builddir}" /> </target> </project>
Чтобы запустить задачи, вы просто делаете
Phing prepare или
Phing Clean соответственно.
Реальные задачи развертывания
Для запуска самого развертывания у меня есть задание по умолчанию, которое вы объявили в первом фрагменте, развернуть. Определение задачи выглядит так:
<target name="deploy"> <echo msg="Next Tag ..." /> <exec command="echo $(($(hg tags | egrep -o '^deploy\-([0-9]*) ' | egrep -o '[0-9]* ' | sort -nr | head -n 1) + 1))" outputProperty="nextTag" /> <echo msg="... is ${nextTag}. Tagging ..." /> <exec command="hg tag deploy-${nextTag}" /> <echo msg="Grab code ..." /> <exec command="hg archive -r deploy-${nextTag} build/deploy-${nextTag}" /> <echo msg="Zip code ..." /> <exec command="tar zcf deploy-${nextTag}.tgz deploy-${nextTag}" dir="build" /> <!-- copy to live --> <echo msg="Put code onto live server ..." /> <exec command="scp -i /path/to/ssh/key build/deploy-${nextTag}.tgz [email protected]:/path/to/bitestats/htdocs/" /> <!-- make live--> <exec command="ssh -i /path/to/ssh/key [email protected] 'cd bitestats/htdocs && tar -zxf deploy-${nextTag}.tgz && ln -s deploy-${nextTag} next && ln -s /usr/local/Zend/ZendFramework-1.11.2-minimal/library/Zend/ public/library/Zend && php -f public/cli.php -- -a updatedbpatch && mv -fT next public'" logoutput="yes"/> <exec command="ssh [email protected] 'supervisorctl restart worker'" logoutput="yes"/> </target>
Краткий обзор того, что на самом деле происходит здесь:
- Мы выясняем, каким будет следующий тег, и помечаем кодовую базу. Я использую Mercurial для контроля исходного кода и размещаю свой код в частном репозитории на BitBucket
- Мы используем hg archive, который в основном похож на экспорт SVN, чтобы получить соответствующую версию кода, а затем tar и заархивировать ее.
- Код передается на сервер пользователем apache
- На удаленном сервере еще несколько команд запускаются сразу. Во-первых, код распакован
- Создается символическая ссылка «next», которая указывает на новую папку (я уже писал в блоге о моей стратегии символических ссылок, если вам интересно)
- Создается символическая ссылка на код библиотеки, в данном случае ZF, но вы также создадите символические ссылки на файлы конфигурации, каталоги загрузки / кэширования и все остальное, что необходимо на этом этапе.
- На этом этапе запускаются все необходимые исправления базы данных (опять же, я написал этот скрипт в блоге на тот случай, если вы захотите его увидеть)
- Мы переключаем символическую ссылку, чтобы новый контент работал
- Наконец, мы останавливаемся и запускаем работника gearman, чтобы он собирал новый код (один работник, все на одном сервере, на этом сайте действительно не так много нагрузки!). Мои процессы контролера контролируются супервизором , но он отвечает только моему пользователю. На самом деле он запрашивает у меня пароль
Наличие процесса развертывания
Весь процесс занимает несколько секунд, и пока он работает как шарм. Я очень доволен этим и очень рад, что нашел время, чтобы поставить это на место. Каждый раз, когда я выполняю развертывание, я чувствую себя немного самодовольным ? Я знаю, что может быть сложно настроить компоненты развертывания, в конце концов, мы можем довольно легко выполнить все отдельные шаги, и у каждого есть множество других вещей, о которых нужно беспокоиться — но я думаю, это важно, и хотя «правильное» решение будет отличаться для каждого приложения и платформы, я хотел бы поделиться тем, что работает для меня. Что работает для вас? Оставьте мне комментарий!