Hanalei, Hawaii 9/2/2010
438 Posts and Counting

Deploying A Web Application with Git and FTP

Monday, November 23, 2009 -

ASP.NET Web Deployment is, shall we say, problematic at times – at least for a hosted scenario where you can’t do dumps from a build server and you don’t have access to IIS (which means you can’t use WebDeploy). What you’re about to read isn’t specific to the Microsoft platform at all and works with any development tool. And NO, you don’t need a single thing installed on the server (save FTP) for it to work.

Have I tried..

  1. Publish Site in Visual Studio? Yes, it copies everything including my config stuff – no thanks. Yes, I know there’s ways to get around this, but by far the easiest way to get around it is to not use it.
  2. FTP Sync using [Tool X]? Yes – there are a number of solutions out there that I like, but none of them work quite the way I want them to – but the best (so far) is SyncBackSE. It’s actually a file backup that runs over FTP (and it’s free), but like every FTP sync tool out there has issues with file/time differences between client and server. These are OK to get around, but if you do a push between developers then these will get completely out of sync and you’ll regress changes.
  3. WebDeploy? Yes – there are ways of getting around the need for IIS locally and on the server, but there is nothing (that I’ve read) that will allow me to not touch the remote server AT ALL. I can’t install Web Deploy Remote Service (well I *can*, but I don’t want to and I shouldn’t have to). I don’t use IIS for local development (does anyone any more?) so “merging packages” makes no sense currently.
  4. Do I know that this will change with VS 2010? Why yes I do… it’s still 2009 however…
  5. Using MSBuild with FTPUpload/FTPUploadDirectoryContent (community add on)? Yes – it didn’t work. FTPUpload works on single files and there are some hacks to make it recursively load your site, but I don’t want all my stuff to be pushed – I don’t want config files and code files, etc.

The Best Option So Far…

Seems to be that I use a Web Deployment Project that compiles my stuff down for release, then I sync that directory using SyncBack or WebDrive up to my server. The downside here is that it repaves everything – it has to – since all of the files dropped by the Web Deployment Project have a newer timestamp than their brethren on the server. This isn’t all that big of a deal – except if you’re just correcting a typo – then you’re cutting ham with a hammer.

I still find it ironic that a Web Deployment Project doesn't deploy anything really – but that’s one of those little nuggets of “just accept it” in the same way that “wieldy” isn’t really a word, but it’s negative is.

And then last night, as I was falling asleep – right from the stars above came a lovely cadence from the Dream Angels of Deployment. I want to say it was a soft, lilting tune, but it really wasn’t … it was more Chuck D in nature.

Use Git Idiot.

Step 1: Setting Up Your Dev Box

This is the trickiest part of the whole deal and I just spent 2 days trying to get it to work. The skinny is that you need to map a drive to an FTP folder. If you’re a Git person you probably understand precisely what I’m about to lay out here – if not, read on.

This is no easy task on Windows 64 bit, strangely enough. If you’re going to offer me some Google links and you haven’t done this yourself – no thank you :). I’ve tried everything. The summary is that if you’re on 32-bit windows, go get NetDrive (it’s free). If you’re on 64-bit you’ll have to wait until they update it or cough up $60 (like I did) for WebDrive – it’s very worth it.

With these applications you can map a directory on an FTP server to a local drive on your machine – I’m using WebDrive here to map a drive on my WekeRoad server:

webdrive

With this drive mapped on my machine, the rest is butter.

Step 2: Create an Application and Add a Git Repository

This here is just an ASP.NET MVC application:

git_initial

It’s now loaded up into my repository (locally) and all’s well.

Step 3: Prepare the Origin (or Remote)

Let’s pretend I’ve done some work and am now ready to show my client – so I want to run a deployment. This is where Git is groovy, you can commit locally all you want, but be very, very selective about when you “push” your changes to a visible location – such as a remote branch on Github or on your network.

In this case we’re being good coders and considering our Master branch as “Must work, all the time”, which is synonymous with a deployment cycle, so we can feel good about setting up a situation where our server pulls straight from the Origin:Master branch.

First – we need to setup our remote (aka “origin” in Git parlance) and we can do this in a number of ways. If you’re working on a team you should put it on a network share so that all people can commit their changes. If you’re solo – you can put it wherever you like – local box, Github, whatever.

For this example I’m just going to use a directory on a local backup drive called “GitHaus”. I set it up using:

git init –bare

this tells Git that it can simply operate as Remote repository – it doesn’t need to index/track local files. This helps with disk space.

 

githaus

 

Now we can add a remote to our repository and push to it…

 

git_push

 

Our initial deployment is now ready to roll – we just need to get it to our server…

 

Step 4 – Prepare the Server

Our web server has been setup and our host has been kind enough to give us FTP access – as all hosts do. In our root directory I’ve created a sub directory which will hold our awesome website:

ftpfolder

Note the address bar? It’s a remote FTP site, but WebDrive is tricking our shell into thinking that it’s a local folder. This is key to the deployment magic…

There’s one last thing we want to do here – setup file ignore rules. Git will drop everything in our repository when we ask it for the deployment, but we can add a file to the root (called “.gitignore” – note the dot) that has some simple expressions for files and directories we don’t want (I might be missing some… massage as you need):

*resharper.user
build/
[Oo]bj/
*.suo
*.sln
*.sln.cache
_ReSharper.*/
*.user
*.csproj
*.cs
App_Data/
Controllers/
Models/
Properties/

This file will tell Git to ignore all of project-specific stuff we don’t want in there – ReSharper stuff, code files and code-only directories (Models, Controllers, etc) and other things you don’t want on a production box.

This file will get dragged to the root of our FTP folder after our first checkout.

Step 5: Deploy!

This is the fun part – right-click on your FTP folder from Windows Explorer, use “Git Bash Here” (because you’re a ninja that doesn’t need Visual Tooling right!?!?!) and then clone your orgin:master branch. This will pull the files from your origin:master and push them to your server using WebDrive/FTP:

 

git_checkout

The important thing to note here is that all file operations are happening locally on your machine – NOTHING is required on your server! After all is said and done we can delete out the files we don’t need and drop our .gitignore file right next to the .git repository. Here’s the site:

bam

Another note: you will probably need to massage the .gitignore file to get it to work as you need it to. I might suggest adding a line at some point that ignores the web.config (for obvious reasons) as well.

Side Effects

One of the great side of effects of running deployment this way is that you now have a deployment history, and should you need to rollback after a botched deployment – you can!

A downside to this is that the repo on your server will contain the entire history of your project. Git allows you to get around this using the “rebase” command – which “smooths out and rewrites” your source history – but that’s for another post.

A final note – you can do all of the above with Subversion as well – it just takes 10 times as long and speed, when working over FTP, is pretty important.

Summary


I just stumbled onto this solution in the last few days (as I mention above) and so far it’s working great for me, personally. It could be wrought with danger and unintended greasy substances – so if you find issues and it turns out I’m full of crap please do let me know!

Related