Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Minimal Race-free Deployment

View deploy.sh
1 2 3 4 5 6 7
#!/bin/sh
# deploy.sh
N="`readlink \"$1\"`"
mv -T "$1.stage" "$1"
ln -s "$N" "$1.stage"
rm -rf "$N"
cp -aH "$1" "$N"
View deploy.sh
1 2 3 4 5 6 7
#!/bin/sh
# initialize-deployable.sh
mkdir "$1.d"
mv "$1" "$1.d/1"
ln -s "$1.d/1" "$1"
cp -aH "$1" "$1.d/2"
ln -s "$1.d/2" "$1.stage"
View deploy.sh
1 2 3 4 5 6 7 8
#!/bin/sh
# deploy.sh
N="`readlink \"$1.prev\"`"
cp -PT "$1" "$1.prev"
mv -T "$1.stage" "$1"
ln -s "$N" "$1.stage"
rm -rf "$N"
cp -aH "$1" "$N"
View deploy.sh
1 2 3 4 5 6 7 8 9
#!/bin/sh
# initialize-deployable.sh
mkdir "$1.d"
mv "$1" "$1.d/1"
ln -s "$1.d/1" "$1"
cp -aH "$1" "$1.d/2"
ln -s "$1.d/2" "$1.stage"
ln -s "$1.d/3" "$1.prev"
 
View deploy.sh
1 2 3 4 5 6 7 8 9 10 11
#!/bin/sh
# rollback.sh
[ ! -e "$1.prev" ] && echo "Can't roll back." && exit 1
N="`readlink \"$1.stage\"`"
cp -PT "$1" "$1.stage"
mv -T "$1.prev" "$1"
ln -s "$N" "$1.prev"
rm -rf "$N"
# Keep current as stage on rollback? If no, uncomment:
# mkdir "`readlink \"$1.stg\"`"
# cp -alH "$1" "$1.stg"

If somebody is looking for a more sophisticated method with the same idea for deploying Rails or PHP applications, it's better to check Capistrano. We are using it to deploy Magento changes as well.

Yep, check cap or vlad the deployer. you don't need to reinvent the wheel.

The great advantage of this technique is that it is easily documented, and someone looking at the directory full of "web-20121009" and similar directories with a symlink "web" -> "web-2012-10-23" should be able to figure out what is going on.

It's simple, it works, and can be reverse-engineered relatively easily. The only caveat is the reliance on GNU "ln", but the atomic replacement of symlinks is only covering the few milliseconds it takes to replace the symlink. If your website users are that sensitive to documents changing from underneath them, you'll need a different solution such as switching VMs on the fly.

#!/bin/sh
ACTION=$1
NAME=$2

if [ $# -ne 2 ]
then
    echo "Usage: deploy-tool.sh <action> <dir> "
    echo "Actions:"
    echo "  init        Initialize an existig directory <dir> for deployment"
    echo "  deploy      Deploy the content <dir>.stage to <dir> also back up"
    echo "              to <dir>.prev"
    echo "  rollback    Rollback from <dir>.prev"
    exit 1
fi

if [ ! -d $NAME ]; then
    echo "Directory '"${NAME}"' does not exist."
    exit 1
fi

if [ $ACTION = "init" ]; then

    echo "Initialize dir '"${NAME}"'"
    mkdir "${NAME}.d"
    mv "${NAME}" "${NAME}.d/1"
    ln -s "${NAME}.d/1" "${NAME}"
    cp -aH "${NAME}" "${NAME}.d/2"
    ln -s "${NAME}.d/2" "${NAME}.stage"
    ln -s "${NAME}.d/3" "${NAME}.prev"

elif [ $ACTION = "deploy" ]; then

    echo "Backup from '"${NAME}"' to '"${NAME}".prev'"
    N="`readlink \"${NAME}.prev\"`"
    cp -PT "${NAME}" "${NAME}.prev"
    echo "Deploy from '"${NAME}".stage' to '"${NAME}"'"
    mv -T "${NAME}.stage" "${NAME}"
    ln -s "$N" "${NAME}.stage"
    rm -rf "$N"
    cp -aH "${NAME}" "$N"

elif [ $ACTION = "rollback" ]; then

    if [ ! -e "$NAME.prev" ]; then
        echo "Cannot roll back."
        exit 1
    fi

    N="`readlink \"$NAME.stage\"`"
    cp -PT "$NAME" "$NAME.stage"
    echo "Roll back from '"${NAME}".prev'"
    mv -T "$NAME.prev" "$NAME"
    ln -s "$N" "$NAME.prev"
    rm -rf "$N" 

else
    echo "Unknown action."
    exit 1
fi

echo "Done."

@czettnersandor , @bitboxer , capistrano and such other tools are usually used for deploying form local server to remote server directly. Our team needed automatic deployment from github to staging server, so I had to create my own wheel after hours of research about existing deployment tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.