Git for web application deployment
Basically, I currently have a very simple procedure for deploying software, it is called: git push, and I really want to be able to do that for my web applications as well.
I know that Rob Conery has talked about this in the past:
- http://blog.wekeroad.com/2009/11/23/deploying-a-web-application-with-git-and-ftp
- http://blog.wekeroad.com/danger-danger/git-and-dropbox-sitting-in-a-tree
And I know about Heroku and AppHarbor, that isn’t what I am talking about.
On my own server, I have a set of web application that I want to be able to update using git push.
Requirements:
- It has to be an explicit operation (pushing to a specific branch is okay).
- It can’t be something that happens periodically, I want to push, and as soon as possible, be able to see the changes. Waiting 5 minutes for the periodic check is going to be a non starter.
- It has to take into account local information (logs, data, etc).
- I have to be able to easily rollback.
- I don’t really care for things like migrations, those are handled by the application, or manually.
I specifically don’t care about actually building the code, I am perfectly fine with pushing binaries to the git repository.
At first I thought about simply making the site a git repository and just push there. But you can’t push to non bare repositories by default (and rightly so). When I gave it some more thought, I realized that there are more reasons to want to avoid that.
Any thoughts? Any existing solutions?
Comments
We use TeamCity and MSDeploy for deployments, along with Mercurial.
For our main system, we push code to the repository and let the build server deploy it. This takes advantage of the multiple config files feature of VS 2010. We're also using the new database project to change the DB schema when needed. We have a couple of build projects that check a different Mercurial repository such as Dev, Stable, Production, etc.
TeamCity always allows you to run a build manually, so that's what we do when we can't wait five minutes for it to notice the source control change.
For small sites without a build server we have a copy of the repository as the site and do a Mercurial pull when we want to deploy it. This is super easy, but doesn't give us the config file transformations (although we could probably add a hook to do so).
As you can imagine I've been trying to solve this very issue for a long time and I have a prototype working if you want to help (I'll Skype you).
You can push to Git over HTTP which means you can have a web site on the other end - which means you can do some of the things for deployment.
It goes like this - 1) Push to website 2) Website drops changes to a Bare repo 3) You CD into a predefined directory on your server 4) You pull from the bare
It almost works - but as you can imagine there are some security issues with all of this directory work :).
I tried a few approaches successfully in the past
the dropbox way. you do not wait 5 minutes. the update is almost instantaneous. that's how I deploy my blog. I also use this to get daily db backups back from the server to my machine.
post-commit hook on a github hosted source, that called an endpoint on the site causing it to get the latest source from github, build, and replace the existing site.
post commit hook on a github hosted 'released binary' package. the site then just git-pull and gets updated.
btw it is quite easy these days to setup git-http on your server (over https) and setup the post-commit hook to deploy locally. there are quite a few implementations in ruby and .NET.
We also use TeamCity + MSDeploy. It works wonderfully. We stopped publishing on each push though because we're using AWS and we're stingy on traffic :)
TeamCity can either check periodically (it checks every minute on our servers) or it can be set up with web hooks. I don't know how to do it with Git, since we using Mercurial and Kiln - and Kiln allows you to do that rather easily.
Git has post-push hooks (post-receive and post-update, to be precise) which are executed on the remote host (your web server in this case) after the repository has been updated following a push.
This takes care of 1 and 2, and since the hook can be as complex as needed 3 should be OK.
The only issue might be 4, I don't really see how you would handle it.
An alternative would be to use a deployment tool (e.g. fabric, or capistrano) instead of
git push
. They can perform arbitrary operations on both side, so they can handle rollback if you wish to.My org uses CruiseControl.NET. We do a push to a special "Prod" repo, and it monitors for changes. Once it sees a change it runs our entire deployment scripts (DB updates, code deployment to web servers, uninstalling / updating / installing a Windows Service, etc). You get nice build logs and a web interface to review if an issue occurs.
We do Visual Studio Publish into a SVN repository.
We then have a working copy of the repository on the production server, which we update.
Finally we run ViceVersa to sync the working copy with the production copy.
So it takes 3 manual steps, but the whole process can usually be performed in under a 1 minute.
You get both the ViceVersa and SVN logs in case you need them, and rolling back is as simple as pulling down the appropriate SVN revision and rerunning ViceVersa.
Rob,
I agree that git over http is way simpler, especially with: https://github.com/JeremySkinner/git-dot-aspx
That said, your process has a LOT of manual processes involved.
Ken,
Thanks for the hint, I found the git.aspx project, and it has drastically simplified things.
I've done something similar in the past... see my blog article:
thecodedecanter.wordpress.com/category/deployment/
Also see here:
wishfulcode.com/.../managing-code-and-configura...
This process becomes trickier when you wish to check things out from multiple repos (e.g. framework, third party scripts and your web app). Also, managing stateful files (logs, app config, etc) isnt straightforward either. I am yet to see a tool that coud do all of that gracefully and reliably.
Most of my projects are on linux so i am not sure how relevant this will be, but in my experience i have found that having a small bespoke script that does what you want is quite a nice wee and scalable solution. The script can be triggered by whichever way you wish. It can then pull code from repos in a temp dir, compile if required, handle local state / config files appropriately and finally do a simple file copy operation to ur web dir. Quite similar to what Ken described.
I've mentioned a brief overview of a similar script i wrote a few years back under 'using depro' here:
www.fuzedbulb.com/.../version-controlling-wordp...
No offense seems like your doing it wong. Your source control should not be your deployment process though they may be interconnected. But if its to the point where you are precompiling binaries and you dont actually care about building the source code. It seems that the git push is just a by product and not the end goal of the process. If thats the case seems trivial to create some, then would think a better solutions is you call some script, powershell or otherwise, that does the deploy and as part of its process does a git push. Cheif benefit of which its obvious and trivial how to create a script that does a git push as part of a deployment process, while seems figuring out how to do a git push that kicks off some scripted deployment process is not.
Asim,
You don't checkout from multiple locations. That is a recipe for disaster when you have those things change at a different rate.
Logs / data are not in the repo, config files _ARE_.
http://stackoverflow.com/questions/279169/deploy-php-using-git
http://toroid.org/ams/git-website-howto
Couple of options through remote branches and post-update
Comment preview