Use Rsync Scripts for Painless Deployment During Development
I usually find myself writing code on a different machine than will actually be running it, even in the earliest stages of development. I'll be stuck on a cranky Windows box at a client site while the development server is a transient Linux machine in a big cloud platform, for example. Or perhaps it's a cranky machine in the home office and a cloud server, because swapping out those physical machines is starting to look more and more like actual work in comparison to rearranging the servers in your AWS account. But in this day and age a separation between your code editor and the place the code has to be in order to work really shouldn't be an issue: pushing text or bytecode across the network, or across the planet for that matter, should add no noticeable delays to your development process.
Most of my early stage development simply and straightforwardly requires that a copy of the current version of my code winds up on another machine somewhere far, far away. That's pretty simple. When you're in a formal later stage environment, part of a team moving builds out to staging and production, you pull in the version control system and one of a number of sophisticated deployment tools. It's all very high-tech. But when you're in the early stage of writing code, you just want whatever is here pushed out to the server over there quickly and easily. Involving the version control system, even if it's Git, is counterproductive when you're making a hundred and one quick and trivial adjustments, pushing them out one at a time, and abandoning half of them.
So when I find myself at this stage of development, I tend to use simple rsync scripts to repeated push code out to a remote server - rsync does all the hard work for you, is easily set up, and runs rapidly. You can even use it on Windows by installing Cygwin. The scripts are arranged something like this in a subdirectory of the main project:
/deploy/run-deploy
#!/bin/bash # Set the environment by loading from the file "environment" in the same directory DIR="$( cd "$( dirname "$0" )" && pwd)" source $DIR/environment if [ "$DEPLOY_KEY" == "" ]; then # access by tediously typing a password over and again rsync --chmod=ug=rwX -e ssh -axv --delete --exclude-from=$DIR/rsync-exclude \ $DEPLOY_SOURCE_DIR $DEPLOY_ACCOUNT@$DEPLOY_SERVER:$DEPLOY_DEST_DIR else # access by key rsync --chmod=ug=rwX -axv --delete --exclude-from=$DIR/rsync-exclude \ -e "ssh -i $DEPLOY_KEY" \ $DEPLOY_SOURCE_DIR $DEPLOY_ACCOUNT@$DEPLOY_SERVER:$DEPLOY_DEST_DIR fi
/deploy/rsync-exclude
**.svn .git .gitignore .project .settings
/deploy/environment
#!/bin/bash # Don't forget the trailing / on the source directory - if you omit it, # it will copy the directory over, rather than just its contents. export DEPLOY_SOURCE_DIR=/path/to/my/code/ export DEPLOY_DEST_DIR=/home/myaccount export DEPLOY_SERVER=myserver.com export DEPLOY_ACCOUNT=myaccount export DEPLOY_KEY=/optional/path/to/ssh/key
Note the options for a chmod command to change permissions on the destination files - adjust that to suit, and note that changing permissions on files requires the deploy account you are using to be the owner of those files. It is optional, so you could skip it if so desired, and if that works for your situation.
An alternative approach to the exclude settings is to use filters. This allows for far more versatile rules - but it is a far more complex set of options, and reading the Filter Rules section of the man page is very necessary. One of the more important options is the ability to protect remote files from being deleted when they are not present locally. Many frameworks create files once they get started, and you may want to keep those in place when you update your code. This would work as follows:
/deploy/run-deploy
#!/bin/bash # Set the environment by loading from the file "environment" in the same directory DIR="$( cd "$( dirname "$0" )" && pwd)" source $DIR/environment if [ "$DEPLOY_KEY" == "" ]; then # access by tediously typing a password over and again rsync --chmod=ug=rwX --perms -e ssh -axv --delete --filter="merge $DIR/rsync-filter" \ $DEPLOY_SOURCE_DIR $DEPLOY_ACCOUNT@$DEPLOY_SERVER:$DEPLOY_DEST_DIR else # access by key rsync --chmod=ug=rwX --perms -axv --delete --filter="merge $DIR/rsync-filter" \ -e "ssh -i $DEPLOY_KEY" \ $DEPLOY_SOURCE_DIR $DEPLOY_ACCOUNT@$DEPLOY_SERVER:$DEPLOY_DEST_DIR fi
/deploy/rsync-filter
exclude **.svn exclude .git exclude .gitignore exclude .project exclude .settings protect sites/default/settings.php protect sites/default/files**
/deploy/environment
#!/bin/bash # Don't forget the trailing / on the source directory - if you omit it, # it will copy the directory over, rather than just its contents. export DEPLOY_SOURCE_DIR=/path/to/my/code/ export DEPLOY_DEST_DIR=/home/myaccount export DEPLOY_SERVER=myserver.com export DEPLOY_ACCOUNT=myaccount export DEPLOY_KEY=/optional/path/to/ssh/key
To deploy, just execute run-deploy as a shell script and off it goes. It isn't hard to integrate this into most development environments, by hooking it up to a save or build action for example. I find it is rarely necessary to do anything more complex than this for the earlier development stages of a project. As you start in on later phases the deployment situation swiftly moves beyond the scope of home-grown scripts and into the realm of third party build and deployment management software - so there isn't much mileage to be gained from expanding a trivial piece of work like this. Use it while it's useful, then stop and use a more appropriate tool.