The final result is a single grunt task that will bundle and minify, copy the files to the server, unpack them and update any dependencies, restart the node process and make the new files live on the web server.
A couple of notes:
- The deploy repo exists only on your deployment machine and the live server. If you wanted to preserve it elsewhere, you could add another remote and push to that as well. Whenever you deploy to the webserver, you should also check in your source and tag it with the current version as well. The
grunt-bump
task by default actually automatically tags and commits your repo, so you can always checkout that tag and recompile from it if you needed to.
- Each deploy creates a separate folder on the server containing your site code, and it is labelled with the version and date. The location where your webserver looks for your files is symlinked to the latest version. If you need to rollback, just reset the symlink to the previous version and restart your node process - takes just a second. You can purge old versions periodically if needed.
I read a lot of articles about automating deployment (and tried a number of different ways), but they all didn't work for me for one reason or another.
There are many tutorials that will show you how to set up a bare repo on the server that you can push your development repo to. Most tutorial authors assume that whatever is checked into git is what you make available on your webserver. The post-receive hook is a simple git checkout, with no build steps. If I pushed my source code to the server, I would have to run my entire build process on the server. This would mean intalling all the grunt devDependencies, running all the concat, ngmin, uglify, less, minify and coffee compilations. That didn't seem like a great idea, since I have all that already set up on my local development environment. My server is supposed to be a production server, not a build server.
Other options involve having a separate build server or continuous integration server that automatically builds pushed source and can then deploy it to the server(s). However, this seemed like overkill for my single-developer small project. I'm just running on the free micro EC2 instance, so I don't want to spin up other servers that will cost me money just to build and deploy.
A number of sites pointed to tools like Capistrano and Fabric for deployment (also Chef and Puppet, although those seem more oriented towards provisioning servers rather than dev deployments). But I didn't really want the spend a lot of time learning a (to me) completely new language just to deploy. I'd rather just suck it up and use FTP in that case, or just enter all the deployment sequence commands manually.
I possibly wouldn't need grunt if my git-fu was better. I came across some talk about having separate branches and subtrees in which you could store compiled code and you could checkout to them and commit from there, but I was never quite able to make it all work. Since I was already using Grunt, this solution works for me.