Search code examples
gitserverstagingdev-to-production

How to set up a single git source on a single server deploying to both staging and production


As a sole developer on a project, I'm trying to thrash out a simple development and deployment workflow with git, constrained by using a single server for staging and production.

The production path is /var/www/vhosts/site.com

The staging path is /var/www/vhosts/staging.site.com

I understand how to create a branch for staging and that it's best to have prime (live site code) and hub (clone codebase) repos on the server, and then create a local working clone from the hub. But how do I create a git repo in /var/www/vhosts/ that serves both production and staging? Do I need separate repos?


Solution

  • You can use external work trees and change them "on the fly" for bare repos.

    Setup the bare repo on your server and then create a post-receive hook for it to do the deployments.

    #!/bin/bash
    # post-receive
    # deploy production and staging to vhost dirs
    
    # Directory we are deploying to. Should be the directory where the repo's root .gitignore would exist in.
    PRODDEST="/path/to/destination/of/production"
    STAGDEST="/path/to/destination/of/staging"
    
    while read oldrev newrev refname; do
        # Grab the name of the branch that was pushed.
        branch=$(git rev-parse --symbolic --abbrev-ref $refname)
    
        if [ "master" = "$branch" ]; then
            echo "Master push, deploy production..."
            GIT_WORK_TREE=$PRODDEST git checkout -f master
            GIT_WORK_TREE=$PRODDEST git clean -fd
    
        elif [ "develop" = "$branch" ]; then
            echo "Develop push, deploy staging..."
            GIT_WORK_TREE=$STAGDEST git checkout -f develop
            GIT_WORK_TREE=$STAGDEST git clean -fd
        fi
    done
    

    This has been adapted from a single-branch deployment script I use. I did not test it so it may need to be tweaked.

    Essentially the bare repo runs the hook and checks if the push was a master push (and deploys production) or a develop push (and deploys staging).

    You could also expand this hook to call build tools after the changes have been checked out to compile assets and what not. I usually remove all development packages, sources and build tools after everything is done.

    EDIT: this does not work if you need to push a single branch to multiple deploy locations. Not sure what parameters can be sent with pushes, or if remote names could be used somehow.