If you use a Git hook to deploy your projects you might have run across the problem of accidentally deploying the wrong branch. This can easily be resolved by adding a check in your post-receive hook but what if you have a project that you build locally before deploying and your
dist folder is not under version control? I wrote a quick inline Grunt task to guard against accidentally deploying the wrong branch. You can use this code directly within your Gruntfile. I may roll this into a plugin in the future.
I have a project with two long running branches;
master for the latest stable release and
develop for the latest changes. It’s a static website that I deploy using rsync. I would normally opt for a Git hook but in my case I don’t want to have to keep my built and packaged files in my Git repo. After all, there are a few things you should never keep in version control:
Things not to keep under version control
- Dependencies – These should be easy to install locally whenever you get a fresh clone of a project
- System and editor files – OS X always drops a
.DS_Storefile in random folders and your
.sublime-projectfile shouldn’t be committed either because you and your team should be free to use any editor or IDE you want without having your Git repository force someone else’s project-specific settings on you.
style.cb83ac322.min.cssor something similar (note the hash in the file name) while the previous build produced file names with different hashes? And so then you had to go back into
git status, identify the built files that no long have the same name and then
git rmthem from your repository? Why go through the trouble?
It would be easy to simply keep the folder containing my built project under version control and have a Git hook deploy it but because of reason number 3 above, I refuse to do that. An alternative would be to deploy the project to the server and have the build script triggered there after a deploy. In that case you’d push, the post-receive hook would checkout the latest version of your project to
/www/myproject.com/ and then run
grunt build (or whatever) to reproduce your built files on the server. Then I could just set the site’s document root to
/www/myproject.com/dist/ in my Nginx or Apache config. I actually am considering this but there are a few circumstances that could prevent that from being possible:
(Excuses for why) You can’t always run builds on the server
- It’s kind of hard. There’s a lot of troubleshooting that goes into writing a post-receive hook that does all that without fail. My build process still isn’t perfect enough for this solution.
- You may be running a task like
imageoptimon all your images that only works on OS X but you deploy to a Linux server. This applies to me too.
So for now, I have a Grunt task that creates a fresh build of my project and puts it in
/dist. When I run the
deploy task the
build task gets fired and then my tests are run with CasperJS, and if those tests pass then I have a simple bash script which will use rsync to deploy my built project into production. The only problem is that I only want to deploy from the master branch. There are a lot of ways you can configure your Git repo so that two branches actually contain slightly different versions of a project even after a merge and because of that, its very important that only your official release branch gets pushed into production.
The Grunt task for guarding your deploy branches
I’ve given a ton of background, now for the Grunt task. Like I mentioned, this task will check the current branch and if it doesn’t match the one you choose as the “deploy” branch then it will fail and stop the deploy process. I use it as the line line of defense before my deploy script is run:
1 2 3 4 5 6 7 8 9 10 11 12 13
You can stick that task right into your Gruntfile and it’ll work (with caveats*). No need to write a full plugin.
I kind of lied. If you want to use this task for real then you need to do some setup work. Very little:
You’ll need the
git-rev library from npm.
Prep your Gruntfile
You’ll need to require
git-rev in your Gruntfile and maybe add a few options to make this task a little cleaner. Here’s a sample Gruntfile you can use as a base. This Gruntfile on its own will work as-is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
If you add this task as part of a series of tasks that builds, tests, and deploys your project you can save yourself from accidentally deploying the latest experimental branch into production.
I would really like to make this into a Grunt plugin but the fact that its so incredibly simple doesn’t allow me to justify the effort and I doubt it’ll be any more valuable to others as a plugin. If you have any ideas for features that would make this plugin-worthy let me know because it’s something I’d love to work on.