Azure continuous deployment for multiple projects - azure

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 this worked for a solution with one project, but now I have added a Web API project as a back end. This is named such that it is the first of the two projects alphabetically, and so now it is the only project that gets built and deployed whenever files are checked in. Which leads to my question:
How can I modify the default continuous deployment build to deploy both applications?
I'm sure it must be a fairly simple change to either the build template or parameters, or the publish profiles that are being used by the build. The only problem is I don't know: A) how to change those settings in the default TfvcContinuousDeploymentTemplate.12.xaml build template, and B) how to modify the publish profiles that are used in the continuous deployment build.
I have already, from within Visual Studio, manually published the two projects and got them to deploy to the right locations by following the instructions in this answer. I right-clicked on each project, clicked publish, then selected the "Microsoft Azure Web Apps" publish target which (after filling in all the settings) added the publish profiles to my projects and allowed me to manually deploy them how I wanted.
Unfortunately there seems to be no way to re-upload those publish profiles so that they can be used in the CD build. I've checked them into source control, I just need to know how I can get the CD build to make use of them. How can I do this?

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.

Related

WebJobs publishing to Azure doesn't create App_Data directory structure

I am trying to setup the CI for Azure Web Jobs using local TFS 2013. The build server itself is fully patched and has Build Tools 2017 installed. I have tried a standalone Web Jobs project in a solution as well as a solution with a Web project and Web Jobs project. From VS2017 the publish (in case of Web project and Web Jobs project) and Publish as WebJobs (in case of standalone Web Jobs project) work just fine and everything gets deployed. NuGet package Microsoft.Web.WebJobs.Publish is included. In both scenarios, the local build/publish publish properly website as well as jobs in app_data/... folder but TFS builds don't even create app_data folders. It seems the final collection of files for publishing is trying to pick the files from WebJobs/bin/** folder which isn't even created in TFS build. The TFS builds add additional argument /p:OutDir="C:\Builds\2\iPayment.Core\Dev-iPayment.ServiceBus.Agents\Binaries\\ and the assembly files for WebJobs are not collected and thus not dropped into app_data/... The build parameters are passed as
/p:PublishProfile=ReleaseWebDeploy
/p:_DestinationType=AzureWebSite
/p:DeployOnBuild=True
/p:WebPublishMethod=Package
/p:PackageAsSingleFile=true
/p:SkipInvalidConfigurations=true
The symptoms are similar to what are described in http://chamindac.blogspot.com/2015/08/package-azure-web-job-with-tfs-build-to.html but my version of XAML build is slightly different than in the blog post and there is nothing to override the OutDir without probably modifying the build template itself.
In a standalone WebJobs project, if I use the MSBuild command line without the OutDir, the bin/** are created and packaged properly and get deployed to Azure but that option doesn't work for the solution where both WebProject and WebJobs are in a single solution and need to be deployed together. Also, I could not find any way to empty the OutDir outside of XAML definition.
I have confirmed the presence of webjob-publish-settings.json (in both cases) and webjobs-list.json (in case of where solution has WebProject as well as WebJobs), which is actually needed and works fine from VS2017 deployment. The publish profile is also correct and it is used by the VS2017 deployment. The TFS build is configured to build the solution in both cases. Microsoft.Web.WebJobs.Publish.1.1.0 is used which is the latest version.
It turns out that the OutputPath property was not being set in our template. There is no "Output Location" to be set as "As Configured". I ended up passing MSBuild Arguments and modifying the template to do the replacement for $(OutDir) in two places
MSBuildArguments.Replace("$(OutDir)", [BinariesDirectory]))] and MSBuildArguments.Replace("$(OutDir)", [outputDirectory]))] respectively for <mtbwa:MSBuild ...> under "Try to Compile the Project" and "For Each Configuration in BuildSettings.PlatformConfigurations"

TFS: Automated publish a folder to Azure website

I am trying to create automated build to publish a folder with files onto Azure web-site. And I cannot accomplish this.
I am NOT publishing a solution (.sln), but rather a folder with files. I am using VS2013 and Visual Studio Online.
I have experience with TFS web publishing, so I published solutions many times.
So, what I did so far:
Created an MSBuild build.xml file that just copies files from the folder to the output.
Created a build definition based on AzureContinuousDeployment.11.xaml
Specified build.xml in my build definition, Process tab, in "Solution to build" parameter:
If I build my project, it is correctly built, files are copied to the output, etc (I can verify it by opening drop location, all files are there).
Then, I:
Created a web-site in Azure, linked it to my TFS subscription.
Downloaded a publish profile (.PublishSettings from a web-site).
Created a Web publish profile (.pubxml) in Visual Studio based on .PublishSettings file).
Specified Web Deploy Publish Profile and Deployment Settings Name:
But now I am getting an error during build:
Exception Message: Please specify a Visual Studio Solution (.sln) to build. (type BuildFromSolutionException)
So it asks me for a Visual Studio solution, but earlier it worked perfectly with MSBuild file (after step 3).
I tried to rename my .xml to .sln (probably it is not what I should have done), and build now says "There was no Windows Azure project (.ccproj) detected in the solution. Continuous delivery to an Azure Cloud Service requires an Azure project. (type CCProjNotFoundException)"
If I don't specify "Deployment Settings Name", build completes without errors, but again no publishing to Azure.
So, the question is, how to publish a custom MSBuild build, without a solution, onto Azure? Is TFS continuous Azure publishing for Solutions only? I expect it to be agile, like I published folders from Local Git to Web-site without any hassle.
What should I do?
There are a few confused ideas in your question. Fits, there is no relationship between and automated build and Git. You are using Team Foundation Build to run the workflow of deployment. It is the workflow that is not working for you. In effect the build and deployment script. In fact the script you are using works with both Git and TFVC so that is not the issue.
That specific script is designed specifically for building an azure project that is then continuously delivers to Azure and you likley can't use it as you are. You can however create another script and use that. I would suggest you try instead to use the Default build script and use a powershell script within the build to collect the files and then push them to Azure.
If you want to go a little more advanced you could create a copy of the default and make one that does not require MSBuild at all.

Specify which Publish script to use on build?

How do I have SSDT run my publish script when I build my solution file?
If you:
1) Right click on your solution
2) Click Configration Properties
3) Click Configuration
I can see the database project and where it is checked to deploy on build, it does not let me specify what publish script to use.
As far as I know this isn't possible out of the box.
Why? They are two very different things.
Building (if you were to think of it as code) compiles and checks, producing artefacts. For .NET code those artefacts are DLL's/.exe etc. For .sqlproj it's the .dacpac etc that turn up in /sql/[Build Configuration Name].
Publishing is akin to Deploying if you were talking .NET code. Building won't include Publishing as an action.
Ironically, a Publish action also Builds the solution, so my suggestion would instead be to consider one of the following:
Publish the project (right click Publish, or double click your chosen .publish.xml file) whenever you want to build.
Use the Post-Build command line in the project Properties to call sqlpackage.exe to deploy your newly compiled .dacpac with your specified .publish.xml profile - but note that this will also impact your use of the Publish action from within Visual Studio as a Publish builds and then publishes (so you'd end up publishing twice).
Depending on your comfort levels/if you are a command-line fan, then use the command line (bash file? Powershell?) to call msbuild followed by sqlpackage.exe. Whenever you want to build, run your command in cmd.exe.
Similar to #3, add a menu item to the Tools menu that would do exactly the same thing (msbuild followed by sqlpackage deployment) but from within Visual Studio itself.
Look at a Continuous Integration model (TFS/TeamCity/Bamboo/Jenkins and about 3000-others), which could build and deploy for you automatically with every change - either on another server, or running locally (I put this in without knowing your scenario, so may be very much unsuitable to solve your problem).

How to specify specific projects in build settings for web deploy

I have created a new release build in TFS 2013 and I want to configure it to perform a web deploy. I am not sure how to specify which project to deploy. Ideally I want to web deploy 2 web projects to IIS on the server (both projects will have a corresponding website in IIS), but if it not possible I can live with having 2 separate builds. I have added the following setings to MSBuild Arguments (in Advanced section of the process) in build definition:
/p:DeployOnBuild=True
/p:DeployTarget=MsDeployPublish
/p:Configuration=Release
/p:CreatePackageOnPublish=True
/p:DeployIisAppPath="<IISSIteName>"
/p:MsDeployServiceUrl=https://<my server IP>/MsDeploy.axd
/p:AllowUntrustedCertificate=True
/p:username=Administrator
/p:password=xxxxx
I can see it is conneting fine, but it doesn't publish anything. I also tried to specify my web project in Items to build section, but that didn't help. What am I missing? Must be some setting.
If I have understood correctly, you have 2 web projects in the solution and you want to create build definition to deploy them as two different web sites on IIS server.
There could be better ways of handling this but what I have done in my project is to have two separate build definitions for 2 web projects.
For each build definition, specify the csporj file of the project to build under “items to build” section of the process tab.
Even after doing this TFS may not publish the web site at desired location. It may show success but files won’t be copied to the destination location.
In this case, check the log messages of the build activity. If you find a warning similar to this:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (484, 9): warning: The OutputPath property is not set for project ProjectName.csproj'.
Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='Release' Platform='Any CPU'
Then it may be related to build configuration. If you are using “Any CPU” as build configuration then change it to “AnyCPU” (remove space).
Refer following link for the detailed explanation:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/0bb277ec-a08c-4795-88f0-3207654e2560/the-outputpath-property-is-not-set-for-project-xxxxxbtproj-please-check-to-make-sure-that-you?forum=tfsbuild
Amey

Changing deployment project on TFS2010 build

The solution I'm building contains a whole lot of projects. One of them, Web, is the front end web site, and is being built and deployed to the QA server by default when a QA build is run. I have another project, called Service (and an associated Service.TestHarness), which I'd like to deploy to the same server as part of the same build. Where in the build's settings, or in the BuildProcessTemplate, can I configure this?
I've tried creating a deployment package via Visual Studio and importing this manually in IIS on the QA server, but got the error "This access control list is not in canonical form and therefore cannot be modified" which I haven't been able to resolve either.
Current build settings:
DeploymentApplicationPath = QA server's address
DeploymentComputer = QA server's name
DeploymentPackageSource = Web.zip
PerformDeploy = true
PerformDeploymentBackup = true
There's four ways you can do this:
1) pass everything as parameters to msbuild using the Team Build Process settings This is the least flexible and doesn't work well if you have multiple deployment projects as you currently have
2) create a custom target and a set of conditions in the project files and let msbuild handle the deployment, don't configure anything in the Build Definition itself (other than maybe setting a property on the msbuild command line arguments to enable a specific deployment)
3) use the Solution Configuration to create a specific solution configuration for each deployment you want to do and when specifying the solution/configuration to build in the build definition, enter your own custom configuration
4) let Team Build handle the build and use something like TFS Deployer or Powershell to handle the actual deployment of the packages.

Resources