📜 ⬆️ ⬇️

Group site development through git - automatic creation / deletion of sites from git-brunch

In this article I will tell how to create a group development environment of sites through git using git-hooks. The article is designed for experienced system administrators, I will only describe the algorithm.
Much on this topic has already been discussed, and I will add how to automatically create or delete sites when creating / deleting brunches in the git repository. This feature can be useful, for example, if different programmers work on different parts of the site and need different platforms (branches). After the main development and testing, merge to the main branch is performed, and the branches and test sites are deleted or archived.



How it works: by default, a master branch is created on which the main site is accessible. By necessity, programmers create branches that automatically become available at branchname.projectname.domain.ru. Changes made are tested and merged into the main branch (be it master or any other). And if the brunch is deleted, the site of the same name is automatically deleted.
')
Git setup


We create a git-repository, configure its availability at factory.domain.ru/git/projectname and allow authorization without a password for IP, from which the development server will work. Setting up the git server has been repeatedly described, so I’ll skip the details of this item.

Create git-hooks


Create the file / srv / git / projectname / hooks / post-update (this script will automatically update the code on the site when there are changes in the repository; for the PROJECT variable, assign a project name, and for GIT_URL - a link to the git repository):
#!/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 


Create the file / srv / git / projectname / hooks / update (this script will automatically create / delete sites when creating / deleting new branches; for the PROJECT variable, assign a project name):
 #!/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 


We configure nginx and apache for support of the branch.projectname.domain.ru domains


Create a vhost-config and connect it to the main nginx configuration:
 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; } } 


Only the vhost-config for apache remains:
 <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> 


That's all! This algorithm can be screwed, for example, to Redmine to automatically create repositories when creating new projects, as well as to control access rights. A good idea would be to write a plugin with access rights, which will enable you to deploy or rollback production (including using Capistrano).

We use this implementation for a large advertising agency with a staff of more than 100 people and they like it very much, because automation significantly reduces errors made by the human factor, and most importantly, do not wake the admin at night to create a new urgent project or prescribe accesses.

Write in the comments, what questions on this topic are most interesting to you - I will definitely describe in the new article!

Source: https://habr.com/ru/post/158855/


All Articles