When I first started deploying code from TFS I took the simple approach and created a batch file and deployed the websites via RoboCopy. I’m a very “Keep it simple” kind of guy, so this worked for us for a long time and so nothing was changed.
With my most recent project however, we were deploying code over a slow VPN tunnel from our servers in Chicago to servers located in Europe. Due to this, the RoboCopy was taking over 4.5 hours to complete. I needed a better/faster way so I started looking into Web Deploy (MSDeploy). I was able to get it working fairly easily and I was pleasantly surprised how easy it was to get it working, and how much time its saved me! I can now deploy the code in less than 20 minutes!
I’ve outlined the process in detail below, but in general you only need to do this:
- Add MSBuild parameters to your automated build
- Customize the deployment parameters for the website
- Create a batch file to an auto-generated MSDeploy script
- Execute the batch file from the automated build
Note: In order to use MSDeploy, you need to install MSDeploy on the destination server. Details can be found on the Web Deploy/MSDeploy website here:
Step 1: Create an automated Build in TFS
This is obvious, but worth mentioning. If you don’t have an automated build, you can’t do automated deployment. here is an MSDN Article that walks you through it: http://msdn.microsoft.com/en-us/library/ms181716.aspx
Kick off your build and verify that it builds and deploys the websites properly. You can do this by making sure the build completes properly and that the code is moved out to the code drop location. The code should be in the following location:
<Code Drop Location from Build Defaults Tab>\<Build Name>\<BuildName>_<timestamp>\PublishedWebsites
Example:
Step 2: Customize the build for MSDeploy
After the build is created, there are a few MSDeploy specific changes you need to do.
1. For the Default Template, create a new template by clicking on “New…”, selecting the Default template, naming it and clicking “OK”. This is the template we’ll be editing later on.
2. On the “Process” tab, you need to enter the following for the MSBuild Arguments:
/p:DeployOnBuild=True /p:Configuration=Release
Step 3: Kick off the build and verify MSBuild Arguments:
Now that the MSDeploy stuff has been added, you want to kick off another build. When it completes you should now start seeing some “_Package” folders in the Code Drop Location:
If you don’t see these, then go back to steps 1 and 2 and make sure you’ve got everything set up properly.
Take a look at the contents. You can see that TFS/MSBuild take care of a lot of the heavy lifting.
- Deploy.cmd: This is a batch file that can be executed to publish code to a server that has Web Deploy installed on it. You can open it and take a look to get an idea of what its doing. Its some pretty cool stuff
- SetParameters.xml: This is an xml file that allows you to set some specific parameters for the deployment like IISWebsite name, etc. We’ll be using this file later to tell MSDeploy where to put the code.
- Sourcemanifest.xml: Config file used by MSDeploy to Locate where the code files are
- zip file: Compressed version of the published website. This is what is deployed to the server during deployments
Step 4: Save off “SetParameters.xml” files
I like using batch files for deployments and I like to save them on the build server so they are easily executed during deployments. When I do this, I add folders into the Code drop location for each build definition and create a new folder called “Batches”. We’ll need to save off the SetParameters.xml files as well, so lets create another folder in the Batches folder called SetParameters. Grab the SetParameters.xml file from step 3 and copy it into this folder.
Now we need to customize this XML file for our deployment.
Open the SetParameters.xml file in a text editor. You’ll see a “setParameter” XML node where the IIS Web Application name is being set. Update this to match the Website/Web app in IIS on the server where this will be deployed:
In my example, the WebService is actually deployed on the server to the Default Web Site –> NewsService location
IIS on the server:
WebService.Setparameters.xml:
Step 5: Create a batch file to execute the Deployment
Now that we have the Package folder being created and we’ve customized our XML file, we need to set up a batch file to execute MSDeploy and have it published to the server. The auto generated deploy.cmd file comes in extremely handy.
Again, we’ll leverage the “Batches” folder on the build server.
Create a new batch file called “RunDeployment.cmd” in the Batches folder and add the following lines into it:
- Here we set up variables used to execute the MSDeploy. I use variables so that we can easily change things like server names, etc. without changing the actual MSDeploy calls
- _xcopyFlag: normal xCopy flags used to silently overwrite files via batch files
- _location: this trims extra quotes from the location parameter passed in. (We’ll pass in this from the Deployment workflow later on)
- _logfile: Sets up a log file. Very useful for troubleshooting/verification of deployments
- _Server: name of the server were this will be deployed
- svcname: name of the website/web service that is being deployed
- This moves the customized SetParameters.xml file back into the _Package folder to overwrite the auto generated one.
- This calls the deploy cmd file to execute the deployment.
- In my example, I’ve got a few extra flags for usename/password for security.
- There are other flags that can be used such as “-skip:objectName” that will ignore folders, but in this case we’ll keep it simple.
Step 7: Modify the Build workflow:
Now we need to make a few simple additions to the build workflow to call the batch file.
Open the Build template XAML file that was created in step 2. Typically these are stored in Source Control at $Project\BuildProcessTemplates:
When the workflow opens, add a new Sequence workflow after “Check in gated Changes..” step named “Deploy to Servers”
Open the Sequence object and drag an “InvokeProcess” task onto the surface:
Right click and select properties and enter the following information:
- Arguments:The arguments we want to pass into the batch file
- Example: """" + BuildDetail.DropLocation + "\_PublishedWebsites\" + """"
- FileName:The location of the batch file created in step 5
- Example: <Code Drop Location>\<BuildDefinition>\Batches\RunDeployment.bat”
Step 8: Run the build
Run the build and check your server. If the bits have been updated, you’ve been successful. If not, check the log file created by the batch file(filecopy.txt) and troubleshoot.
Important: Before you run the build, please make sure to backup the deployed folder on the server if you are concerned about losing anything. MSDeploy cleans up files on the server that aren’t part of the deployment, so if you have images or other files that are not part of the build, they will be deleted from the server. Also, run this on non-production environments first and hone this process down before you use it in production. If you build the batch files with parameters and variables, using MSDeploy in Staging/production environments will be easy.
Summary:
While the information above may seem complex, most of the work is done by the auto generated files. Basically you only need to update your build with the MSBuild parameters, create a batch file and execute the batch file from the build.
there is a lot of power in MSDeploy that is not being used at this point, but I’ll post something else if I come across anything else useful
Enjoy!
Shouldnt there be an easy way to preserve the etParameters.xml by now? I find it odd that I need to manually swap that out every time i run a build.
ReplyDeleteI believe so, at least for some of them. I think you can pass some of the values in as parameters to the MSDeploy Script.
ReplyDelete