Многое на эту тему уже обсуждалось, а я добавлю, как автоматически создавать или удалять сайты при создании/удалении бранчей в git-репозитории. Такая возможность может пригодиться, к примеру, если над разными частями сайта работают разные программисты и нужны разные площадки (бранчи). После основной разработки и тестирования выполняется merge в основную ветку, а бранчи и тестовые сайты удаляются или архивируются.
Как это работает: по-умолчанию создается master-ветка, по которой доступен основной сайт. По необходимости программисты создают бранчи, которые автоматически становятся доступны по адресу branchname.projectname.domain.ru. Внесенные изменения тестируются и мержатся в основную ветку (будь то master или любая другая). А если бранч удалить, автоматически удаляется и одноименный сайт.
Настройка git
Создаем git-репозиторий, настраиваем его доступность по адресу factory.domain.ru/git/projectname и разрешаем авторизацию без пароля для IP, с которого будет работать сервер разработки. Настройка git-сервера неоднократно описывалась, поэтому детали этого пункта я пропущу.
Создаем git-хуки
Создаем файл /srv/git/projectname/hooks/post-update (этот скрипт будет автоматически обновлять код на сайте при изменениях в репозитории; для переменной PROJECT назначьте название проекта, а для GIT_URL — ссылку к git-репозиторию):
#!/bin/sh PATH=/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH PROJECT="projectname" GIT_URL="http://factory.domain.ru/git" git update-server-info if [ ! -f $1 ]; then exit 0 fi while [ -n "$1" ] do REF=`echo $1 | awk --field-separator="/" '{print $2}'` if [ $REF = "branches" -o $REF = "heads" ]; then BRANCH=`echo $1 | awk --field-separator="/" '{print $3}'` if [ ! -d /srv/www/$PROJECT/repo/master ]; then mkdir -p /srv/www/$PROJECT/repo GIT_SSL_NO_VERIFY=true git clone $GIT_URL/$PROJECT /srv/www/$PROJECT/repo/master fi if [ ! -d /srv/www/$PROJECT/repo/$BRANCH ]; then GIT_SSL_NO_VERIFY=true git clone -b $BRANCH $GIT_URL/$PROJECT /srv/www/$PROJECT/repo/$BRANCH else cd /srv/www/$PROJECT/repo/$BRANCH GIT_SSL_NO_VERIFY=true git fetch origin GIT_SSL_NO_VERIFY=true git reset --hard origin/$BRANCH GIT_SSL_NO_VERIFY=true git clean -d -f GIT_SSL_NO_VERIFY=true git checkout GIT_SSL_NO_VERIFY=true git pull fi fi shift done
Создаем файл /srv/git/projectname/hooks/update (этот скрипт будет автоматически создавать/удалять сайты при создании/удалении новых бранчей; для переменной PROJECT назначьте название проекта):
#!/bin/sh refname="$1" oldrev="$2" newrev="$3" PROJECT="projectname" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 <ref> <oldrev> <newrev>)" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "Usage: $0 <ref> <oldrev> <newrev>" >&2 exit 1 fi # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero="0000000000000000000000000000000000000000" if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git cat-file -t $newrev) fi BRANCH=`echo $1 | awk --field-separator="/" '{print $3}'` delete () { mv /srv/www/$PROJECT/repo/$BRANCH /srv/www/$PROJECT/repo/$BRANCH.removed_by_git rm -rf /srv/www/$PROJECT/repo/$BRANCH.removed_by_git } case "$refname","$newrev_type" in refs/heads/*,delete) # delete branch delete ;; refs/remotes/*,delete) # delete tracking branch delete ;; esac exit 0
Настраиваем nginx и apache для поддержки доменов branch.projectname.domain.ru
Создаем vhost-конфиг и подключаем его к основному конфигу nginx:
server { listen 80; # projectname замените на название проекта, а domain - на основную часть домена. master-ветка будет доступна по адресу projectname.domain.ru server_name ~^(?P<branch>.*)\.projectname\.domain\.ru$ projectname.domain.ru; if ($branch = "") { set $branch "master"; } access_log /srv/www/projectname/logs/projectname.domain.ru-acc main; error_log /srv/www/projectname/logs/projectname.domain.ru-err; # Пример проксирования трафика на apache mod_php location / { proxy_pass http://127.0.0.1:8080; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_read_timeout 300; client_max_body_size 256m; proxy_buffer_size 16k; proxy_buffers 32 16k; } # За исключением папки "data", которая будет доступна по адресу http://projectname.domain.ru/data. Из этой папки отдается только статика, даже если будут загружены исполняемые файлы. # Я сделал, чтобы запись через php была разрешена только в data, таким образом можно избежать git-конфликтов, а так же частично обезопаситься от уязвимостей в коде. # Если на уровне кода сложно сделать загрузку файлов вне DOCUMENT_ROOT, можно сделать симлинк и добавить его в репозиторий. # Таким образом, права на /srv/www/projectname/data делаем, к примеру, apache:apache (или chmod 777), а на /srv/www/projectname/repo - username:username. location ^~ /data/ { root /srv/www/projectname; } # Статику отдаем в обход apache. location ~* \.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf|flv|avi|djvu|mp3|mp4|ogv)$ { root /srv/www/projectname/repo/$branch/htdocs; } # Запрещаем доступ к папке ".git". location ~ /\.git { deny all; } # Если площадка используется исключительно для разработки, рекомендую создать файл /srv/www/robots.txt с содержимым, запрещающим индексацию сайта (комментарии в начале строк в robots.txt нужно убрать): # User-Agent: * # Disallow: / # Таким образом, внезависимости от того, есть в репозитории robots.txt или нет, поисковики будут получать файл из /srv/www, который будет запрещать индексацию разрабатываемого сайта. location = /robots.txt { root /srv/www; } }
Остался лишь vhost-конфиг для apache:
<VirtualHost *> # Хардкод-домен для master-бранча DocumentRoot /srv/www/projectname/repo/master/htdocs ServerName projectname.domain.ru ErrorLog /srv/www/projectname/logs/projectname.domain.ru-err <Location /> php_admin_value open_basedir "/usr/share/pear:/srv/www/projectname:/tmp" php_admin_value upload_tmp_dir "/srv/www/projectname/tmp" php_admin_value session.save_path "/srv/www/projectname/tmp" php_admin_value memory_limit "256M" php_value post_max_size "256M" php_value upload_max_filesize "256M" </Location> <Directory /srv/www/projectname/repo> Options Includes FollowSymLinks MultiViews AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost> <VirtualHost *> # Реализация "бранчей на лету" с использованием VirtualDocumentRoot # При использовании rewrite-правил через .htaccess в рамках VirtualDocumentRoot может возникать ошибка 500, в этом случае может помочь настройка "RewriteBase /" в .htaccess. VirtualDocumentRoot /srv/www/projectname/repo/%1/htdocs ServerName dev.projectname.domain.ru ServerAlias *.projectname.domain.ru ErrorLog /srv/www/projectname/logs/projectname.domain.ru-err <Location /> php_admin_value open_basedir "/usr/share/pear:/srv/www/projectname:/tmp" php_admin_value upload_tmp_dir "/srv/www/projectname/tmp" php_admin_value session.save_path "/srv/www/projectname/tmp" php_admin_value memory_limit "256M" php_value post_max_size "256M" php_value upload_max_filesize "256M" </Location> <Directory /srv/www/projectname/repo> Options Includes FollowSymLinks MultiViews AllowOverride All Order allow,deny Allow from all </Directory> </VirtualHost>
Вот и все! Этот алгоритм можно прикрутить, например, к Redmine для автоматического создания репозиториев при создании новых проектов, а так же для управления правами доступа. Хорошей идеей будет написать плагин с разграничением прав доступа, который даст возможность делать деплой или роллбек на продакшен (в том числе с использованием Capistrano).
Подобную реализацию мы используем для большого рекламного агентства со штатом больше 100 человек и им очень нравится, ведь автоматизация значительно уменьшает ошибки, допущенные за счет человеческого фактора, а главное — не надо ночью будить админа, чтобы создать новый срочный проект или прописать доступы.
Пишите в комментариях, какие вопросы по этой теме вам наиболее интересны — в новой статье обязательно опишу!
ссылка на оригинал статьи http://habrahabr.ru/post/158855/
Добавить комментарий