I’ve been wanting to blog about the new build system in Visual Studio Online for a little while now. One minor surprise I discovered was the lack of support for MSDeploy by not including a specific build step type. Powershell seems to be the new defacto deployment method, but I still prefer the ease of creating Web Deploy packages and syncing via MSDeploy.exe or the Powershell Cmdlets that come with it.
So, I set of in search of a way to use MSDeploy with the future VSO Release Management system in mind with regard to artifacts, a generic deployment process and variablised environment replacement.
I went through a few ideas to get a package deployed as part of a build;
Using the cmd script that gets created when publishing to a package using a Batch Script build step
Calling MSDeploy.exe directly from a Powershell script in a common repository from a Powershell build step.
I’ve settled on the Powershell Cmdlets though because they make it very easy to accomplish the goals I had in mind. They give you a way of exploring details about a package, specifically for this task, the package parameters. So I’ve made a script in a new Github repo that I intend to put all the stuff I create for Visual Studio Online.
The script takes all the parameters you would expect:
||✔||N/A||The path to the Web Deploy
||✔||N/A||The destination in IIS. Eg
||✔||N/A||The user name to connect to the
||✔||N/A||The password to connect to the
||The MSDeploy agent endpoint type. Either
||Whether SSL certificate errors should be disregarded. Use this switch if deploying to a self-signed server.|
||Use the Environment variable collection as a source of package parameters. If a package parameter
|PackageParameters||Dynamic||N/A||Parameters created from
Let’s setup a solution that we can use it with. Here we have a simple project that has an ASP.Net 4.6 application, a set of unit tests and some Selenium acceptence tests.
The important stuff is in the Website project; it has a Package publish profile which is simply:
It also has a
parameters.xml file which MSDeploy automatically merges in package variables with. It can be used for many merge types but for most projects, simple web.config transformations. It should be fairly familiar if you’re used to using XDT.
If you need to do anything more advanced, like remove config sections and the like, XDT is still the answer. What we’re using it for here is to simply change an app.config setting which is written to the page title. Locally the page looks like this (notice ‘Dev’ the value in the web.config in the top corner, we’ll come back to this later):
We’re nearly ready to get to the build but lastly I set up the VSO scripts as a GIT submodule so they can be pulled down as part of repo.
git submodule add https://github.com/dibble-james/VSO.git
So now we set up the Repository section of our new build to checkout submodules (Yes we finally got to Visual Studio Online).
Now lets look at the first step of our build.
The important section to note is
MSBuild Arguments. These arguments essentially do the same thing as using the Publish command in Visual Studio whilst also building the entire solution. Note that if you have multiple ASP.Net applications in your solution it will look for a Publish Profile called Package in all of them and fail if it is missing.
We’re then running our unit tests, nothing special there and then we’ve added a Powershell utility build step.
Script filename will change depending on whether your using a submodule but this is where it will be if you are.
At this point it would be good to take a look at our Build Variables.
As one of my goals was to gear this utility towards Release Management, I’m heavily utilising build variables. This should make it much easier to react if something needs to change too, and as Build has a change history, we can revert variable values if we have too. We can secure the user and password for the application server. Note that we set
Below is some example script parameters (
-ApplicationName being one of the dynamic package parameters), it’s important to note that you need to quote around variables with spaces etc. in them:
-WebDeployPackage $(WebsiteArtifact) -PackageDestinations $(DeploymentDestinations) -VirtualDirectory $(WebsiteVirtualDirectory) -WebDeployUser $(StagingWebDeployUser) -WebDeployPassword $(StagingWebDeployPassword) -AllowUntrusted -ApplicationName $(ApplicationName)
The script is rather verbose, displaying every file that is published so it’s way to big to show in it’s entirety here but here’s what a sucessful build looks like and the script confirming that the package was deployed correctly:
Now we can see that the site was deployed to the staging server and our page title has changed as part of the deployment (see I told you we’d come back to it!).
Now we can set the ApplicationName variable to something different:
Complete a build and see that it deployed the change:
There are several places to go from here; MSDeploy does so much more than just web sites. It would be good to create a script that can deploy database scripts and Windows services. Support for ASP.Net 5 website packages are also a must!