Git Deploy for the win

Using git as a source of truth is a great practice. Using git to deploy code has all sorts of benefits to your health. 

While managing a team of coders for a web design firm, it became commonplace for code deployments to go south far too often. One coder would upload just the code they had touched, and another would come and overwrite the same code with a previous version. Despite the fact we were using git as a code repository, people's commits were infrequent and their understanding of what other coders were doing was incomplete. We needed a way to enforce good habits and give back the time I would spend constructing what a site was supposed to be from disparate parts. It took a conference call to convince everyone that I was right -- we were going to have full git buy-in. Coders would no longer be part of a staff group with permissions to edit files in the web root. The would push their code to the server, and the server would handle the rest. This post covers how to set up git deployments in a very basic setup. A post-receive hook puts the files where they should be (you can expand upon this to run tests and build if needed, but I'll save some of that for another post)

Without further ado, here's some steps to get you started:

navigate to your ssh directory:

cd ~/.ssh/

Generate ssh key

ssh-keygen -t rsa -b 4096 -f serverName-git -C "Git Deploy - serverName"

Add Key to ssh-agent:

ssh-add ~/.ssh/serverName-git

Copy public key to server:

ssh git@serverName 'cat >> ~/.ssh/authorized_keys' < ~/.ssh/serverName-git.pub

edit ssh config:

Host serverName-as-git

      HostName <serverName>

      User git

      IdentityFile ~/.ssh/serverName-git

      IdentitiesOnly yes

add the remote to your git repo:

git remote add production git@serverName-as-git:<reponame>.git

Now for setup on the server:

set up a git user account

adduser git

make yourself git user:

su git

initialize bare repository:

git init --bare repoName.git

navigate to hooks folder

cd reponame/hooks

create post-receive hook:

touch post-receive

make post-receive executable:

chmod +x post-receive

add the logic for the post-receive hook:

#!/bin/bash 

TARGET="/var/www/repoName.com"
GIT_DIR="/home/git/repoName.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

exit git user and navigate to the level below target directory, in this case: /var/www

make git owner of the directory: 

chown -R git:www-data /var/www/repoName.com

Bring it all together

Now, when you add a commit, you can:

git push production master

and the files will be automatically deployed. *note, the repo gets put in your web root in this example, so make sure you put the files you want web facing in a folder like dist and have nginx look there for files to serve. 

There are many more neat options to be had here, like running tests and building from source, but I'll leave those for another post. 

Written by Mark on Monday March 12, 2018
Permalink -

« I have a blog - ODM Paramerter Testing »