Continuous deployment with git on Windows
These are some notes to accompany my talk on continuous deployment for ASP.NET with git. Here you'll find all the tools, commands & setup that I mentioned.
I've tried a bunch of different methods of deploying, and find this to be the simplest, easiest way to set up continuous deploy for ASP.NET while still being powerfull and flexible.
Firstly, I like to ensure I have the following tools installed, to make life on windows a bit less painful:
- Github for Windows - http://windows.github.com/ or:
cinst git cinst poshgit
- (Optional) set up vs powershell command: https://gist.github.com/rdsimes/6190832
- (Optional) Vim editor, especially for commit message editing: http://www.vim.org/download.php or
Step 1 - Reliable builds
You want to be able to checkout and build first time, without having to set up any external dependencies or complex configuration. To do this you'll need to:
- Ensure all your dependencies are installed as NuGet packages
- Enable NuGet package restore - http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
- Ensure you have a good .gitignore file and dont have any crap checked in to your repository - https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
- Ensure you can compile your solution from the commandline with msbuild
I've seen several solutions take almost a whole day to set up when new devs do thier first checkout.
Step 1.1 - Deploy to a Windows Azure website
If you're able to host on a windows azure website, the whole thing is super easy:
- Setup the Windows Azure command line tools: http://www.windowsazure.com/en-us/develop/nodejs/how-to-guides/command-line-tools/
azure site create <site> --git git push azure master
While this is super super easy, there are some limitations. You can run unit tests, though don't have much control over this.
Step 2 - Web Deploy
Web Deploy - it's not perfect, but it's certainly the best Microsoft provided option. The documentation is terribly lacking, and it took me far too long to actually get it working first time.
- Install Web deploy on the destination server (I'd avoid the Web Platform Installer version - the direct download seems easier) - http://www.iis.net/learn/install/installing-publishing-technologies/installing-and-configuring-web-deploy
- Test that web deploy is set up properly on the destination server by visiting: https://:8172/msdeploy.axd in a browser. You should be prompted for a password, and then a blank page will show. Try this page for help when something goes wrong http://www.iis.net/learn/publish/troubleshooting-web-deploy/troubleshooting-web-deploy-problems-with-visual-studio
- Configure a publish profile for your solution in Visual Studio: BUILD -> Publish selection -> create new profile with Publish Method: Web Deploy Package (all other fields can be left blank/default)
- Manually edit the publish profile XML to ensure the package path is relative
- Run msbuild to test package creation:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild /p:PublishProfile="<Publish profile name>" /P:DeployOnBuild=true
- Test that you can deploy the package:
.\<package location>.deploy.cmd /M:<server name> /U:<username> /P:<password> /Y
NB: for the /M switch, just use the server name - there is some outdated documentation suggesting you use: /M:https://:8172/msdeploy.axd, but I found that this didn't work
Step 3 - Team City
Team City seems to be the best option for continuous integration for ASP.NET, especially version 7+ with the addition of full blown support for git/DVCS & nuget integration.
Set it up on a server somewhere: http://www.jetbrains.com/teamcity/ - I'd recommend investing in decent hardware for this, especially for larger projects, as build/test time will probably be the slowest part of your deploy process.
You'll then want to create a project in team city and create a build configuration, named something like 'Build':
- Specify your Web Deploy Package as the build artifacts (eg: build/*)
- Setup/attach to your VCS root
- Add an "MSbuild" build step
- Specify commandline parameters to trigger building of the Web Deploy package:
/p:PublishProfile="Web Deploy publish" /P:DeployOnBuild=true
- Add a second build step to run your unit tests (not in demo, sorry!)
- Add a VCS build trigger
- It's also worth ensuring your SCM username is set up in your Team City settings
We now have CI set up, so to make it CD too, add a second build configuration to your project, named something like: "Deploy":
- Leave most fields blank, skipping the SCM root etc
- Add a "Command Line" build step:
.\YourApplication.deploy.cmd /M:<destination servername> /U:<user> /P:<password> /Y
- Set up an artifact dependency on your "Build" build configuration
- Set up a "Finish build trigger" dependant on your "Build" build configuration, only after a successful build
Now push a new change and test out your deploy! That wasn't too bad eh?
Rollbacks are now super simple too, as we have split the "Build" & "Deploy" steps, we can ask Team City to rollback by running the "Deploy" using an earlier version of the build
You're probably thinking at this point: but how do I deploy my database changes? This is definitely a harder problem to solve, I think because everyone does databases differently. There are a number of .NET databse migration tools available, of which, FluentMigrator seems to be the front-runner. You may find this final step not appropriate, or wish to do it manually.
Step 4 - Fluent migrator
Firstly, install Fluent Migrator with nuget:
Then create a migration as per the documentation: https://github.com/schambers/fluentmigrator/wiki
Then you'll want to test out your migration:
.\packages\FluentMigrator.126.96.36.199\tools\Migrate.exe -db SQLite -a .\MvcApplication1\bin\MvcApplication1.dll -conn "Data Source=test.db" -p --verbose=true
This command gives you a preview of what will be executed, remove the -p flag to actually run the command. To make this part of your deploy, you'll need to:
- Install Fluent Migrator somewhere on your build server(s)
- Edit your 'Build' build configuration, to include your migrations .DLL in the build artifacts
- Add a second Command Line build step to your 'Deploy' build configuration, called something like 'DB Migration'
- Enter the appropriate migration command:
C:\Migrate.exe -db SQLite -a Migrations.dll -conn "Data Source=test.db" --verbose=true
- You probably want to make this build step come before the Web Deploy step
NB: This won't rollback your database if you use Team City to deploy previous builds as your rollback method. It's possibly best just to do the rollback of database manually, as rolling back a schema change can be quite scary & risky.
Another (great) option: Octopus deploy
Octopus deploy is a great alternative to Web Deploy, with several advantages:
- Good documentation
- Nice web-based user interface
- Easy setup of multiple environments, server groups
The only downsides are that:
- while the setup is easier, there is more of it to do
- It does have a cost, though the price is very reasonable
To set up continuos deploy with octopus, there is a great Team City plugin that you can use to call Octopack, which packages up your application for deploy and it can also call the octopus API to create and "promote" a release of your application automatically. Check out the octopus documentation for more info: http://octopusdeploy.com/documentation/integration/teamcity
So, hopefully you can now see that continuous deployment for ASP.NET is actually really easy, so get deploying!