I have created an Azure Web Site and connected it to Visual Studio Online, and this automatically set up a continuous deployment build (as per this page).
Initially
After reading through the first link in my question again, I noticed that you can edit the build definition (or template) to point to the publish profile that you want to use:
Path to Deployment Settings: The path to your .pubxml file for a web app, relative to the root folder of the repo. Ignored for cloud services.
Unfortunately, this both doesn't work and only allows you to specify one publish profile file. Presumably, even if specifying this argument worked, the build would still only deploy the first app in alphabetical order.
This lead me to this question and answer though, which suggests that the Azure/TFVC continuous deployment works simply by using the ordinary Web Deploy arguments to MSBuild. Looking at the diagnostic logs of my build in Visual Studio Online proved this to be the case; here are the relevant arguments:
C:\Program Files (x86)\MSBuild\14.0\bin\amd64\msbuild.exe /p:DeployOnBuild=true /p:CreatePackageOnPublish=true /p:DeployIisAppPath=mysitename
So, as per that question, to use a specific publish profile you can just set the additional necessary MSBuild arguments in the build definition:
Each project needs to have a publish profile called "publishprofilename.pubxml", in this case, checked into source control. I found that the user name (which is your site name with a dollar sign in front of it) is not needed, but unfortunately the password string is required. If you don't include it you get an error like this in the build:
Web deployment task failed. (Connected to the remote computer ("[mysitename].scm.azurewebsites.net") using the Web Management Service, but could not authorize.
No other arguments were required for me, but it doesn't seem ideal that the password has to be included. The default deployment setup, without using publish profiles, must be authorising with that password somehow, but I don't know how.
So after making this change I navigated to [mysitename].azurewebsites.net, and it appeared that still only the Web API project was being deployed. However, by going to console for the site and entering dir D:\home\site\wwwroot
I can see that both projects are actually being deployed. It's just that both projects are being deployed to the root of the site, at D:\home\site\wwwroot
. The DeployIisAppPath
settings are different in each publish profile, but these values are being ignored. This is because the /p:DeployIisAppPath=mysitename
argument to MSBuild (mentioned above) overrides any PropertyGroup
settings in publish profile *.pubxml files, as described in this blog post.
What I have found is that the continuous deployment process for Azure/TFVC works by having an InitializeContinuousDeployment
build activity in the TfvcContinuousDeploymentTemplate.12.xaml build template, immediately before the RunMSBuild
activity. This takes the MSbuild arguments you specify in the build definition, and appends to them the ones needed to deploy to Azure. Unfortunately, this is mostly hard-coded, and that means it always specifies a single deployment path for all web projects in the solution. You can't deploy each web app to a different location using publish profiles alone.
So one workaround option is to add something like a BeforeBuild
MSBuild target to each project, to override the command line value of DeployIisAppPath
. The problem with this is that the path specified in the publish profile, and seen in the publish wizard, will no longer be the path actually being used for deployment.
So the solution I went with is marginally better; it is what we would describe in New Zealand as "huckery".
Basically I added an InvokeMethod
build activity between the InitializeContinuousDeployment
and RunMSBuild
activities. The arguments for this activity are as follows:
DisplayName:
Configure build for using publish profiles (removes DeployIisAppPath MSBuild parameter)
GenericTypeArguments:
System.String
MethodName:
SetValue
TargetObject:
AdvancedBuildSettings
Parameters:
Direction: Type: Value
In String "MSBuildArguments"
In String String.Join(" ", AdvancedBuildSettings.GetValue(Of String)("MSBuildArguments", String.Empty).Split(New String() {" "}, StringSplitOptions.RemoveEmptyEntries).Where(Function(s) Not s.StartsWith("/p:DeployIisAppPath=")))
What this does is removes the DeployIisAppPath
argument from the MSBuild command line arguments list completely, so that it doesn't override this same property in the publish profiles. Instead of the messing around with splitting and joining the string, it would be slightly nicer if you could just append /p:DeployIisAppPath=""
to the command line, but this just sets the property to an empty string and you get an error:
"ConcatFullServiceUrlWithSiteName" task was not given a value for the required parameter "SiteAppName"
So like I said, pretty huckery, but it's a solution that allows you to have continuous deployment of multiple web projects to Azure with a minimal amount of changes to the default setup.
You can override the deployment engine in Kudu by using the Azure CLI Tools. Running the azure site deploymentscript
command and passing in the parameters for one of your projects -s <solutionFile> --aspWAP <projectFilePath>
.
This will create a .deployment
file and a deploy.cmd
(or deploy.sh
if you pass the -t bash
parameter) modifying the deploy.cmd
to add build/deploy steps for the second project.
More information is on deployment hooks is available in the project kudu wiki.
EDIT
You can use App Setting COMMAND
to add a deployment script to your site.