Paulund
2017-02-04 #git

Deploy Code With Git Push

In this tutorial we're going to learn about quite possibly the easiest way of deploying your code onto a staging or production environment. In the past it was common place to use an FTP client such as FileZilla but since it's moved on to more reliable ways of deploying your code, such as SCP, rsync or using a deployment tool. Some of the most common tools you'll find to help deploy code are Ansible, Capistrano, Beanstalk, DeployHQ etc. But you can deploy your code using Git hooks, which means you're able to deploy your code by simply doing a git push.

git push production master

The endpoint of this tutorial we're going to use the above command to deploy the code on master to the production server.

Prerequisites

Before we get started I need to assume that you have a production server ready to go, you have GIT installed on the server and you have a local development environment where your code is using a GIT repository. If you need a production server created quickly I recommend DigitalOcean they have very fast servers and are very cheap starting at only $5 a month. On you're production server you will also need to make sure that you have an SSH key pair setup correctly so you can log into the server with the command.


ssh [email protected]

Todo

  1. Create a deployment folder on the production server
  2. Create a bare git repository on the production server
  3. Add a post receive GIT hook on the server
  4. Add remote repository to the production server
  5. Push to the production server

Create A Deployment Folder On The Production Server

First you need to log on to the production production server via SSH.


> ssh [email protected]

Once logged in then you can create a folder to be used by the repository.


> cd /var
> mkdir repo && cd repo

Create A Bare Git Repository

Creating a bare git repository on the production server will allow us to push the code into this repository.


> mkdir site.git && cd site.git
> git init --bare

Inside the site.git folder we now have an empty git repository. This allows us to add a hook inside the repository to set the working folder of the code pushed to the repository.

Add A Post Receive GIT Hook On The Server

Use the following code to create the post receive hook that will run when code is pushed to it.


> sudo nano /var/repo/site.git/hooks/post-receive

Inside this file we need to set the working directory of the code (which will be the document root of the virtual host) then force checkout the code from the repository into the working directory.


> #!/bin/sh
> git --work-tree=/var/www/website --git-dir=/var/repo/site.git checkout -f

If you want to run any post deploy tasks such as a composer install then you can add these commands to the end of this file.

Change Permissions

We will need to change the permissions on the post-receive file so that the file can be executable.


> sudo chmod +x post-receive

Add Remote Repository Locally

Inside the local working copy directory we need to add the remote repository and name the repositories as the certain environments.


> cd ~/path/to/working-copy/
> git remote add production ssh://[email protected]/var/repo/site.git
> git remote add staging ssh://[email protected]/var/repo/site.git

Deploy The Code

With the remote repository accessible from the local environment we can now deploy the code to the environment by simply using git push.


> git push production master

Only Allow Master To Be Deployed

On your staging environment you might want to deploy any development branch but on the production branch you might want to restrict access to only deploy the master branch, therefore in your post-receive file you can use the following code.


#!/bin/bash
TARGET="/var/www/website"
GIT_DIR="/var/repo/site.git"
BRANCH="master"

while read oldrev newrev ref
do
	# only checking out the master (or whatever branch you would like to deploy)
	if [[ $ref = refs/heads/$BRANCH ]];
	then
		echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
		git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f
	else
		echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
	fi
done