How do I deploy many MSDeploy publish profiles in a single MSBuild command? - msbuild

I have a project that I need to deploy with a couple of different configurations (specifically, deploying the same package to 2 different IIS applications). I have set up 2 Publish Profiles, and each creates a package when invoked individually. I'd like to create both packages with a single command.
I've tried commands like this, but they tend to simply ignore the second profile:
msbuild MyWebProject.csproj /p:DeployOnBuild=True "/p:PublishProfile=FirstProfile;PublishProfile=SecondProfile"
Is there a way that I can use a single command to deploy both profiles?

I know this isn't strictly what you are asking for, but have you considered building once and deploying twice?
To achieve this through msbuild, you could create an msbuild project which calls msdeploy.
Build (Create Package)
msbuild MyWebProject.csproj
/p:DeployTarget=Package
/p:PackageLocation=MyWebProject.zip
/p:CreatePackageOnPublish=True
Deploy Package Twice
msdeploy.exe
-verb:sync
-source:Package=MyWebProject.Zip
-destination:auto:ComputerName="my.server1.com"
-declareParamFile:Params1.xml
msdeploy.exe
-verb:sync
-source:Package=MyWebProject.Zip
-destination:auto:ComputerName="my.server2.com"
-declareParamFile:Params2.xml

Related

Accessing TeamCity artifacts in Build Step

I have been playing around with TeamCity to get a CI environment up and running.
I started by following Troy Hunt's 'You're deploying wrong', which was very useful, however I wanted to split the packaging and deployment into 2 seperate steps, for the following reasons:
I wanted to pass some additional flags to msdeploy, which isnt possible (to m,y knowledge) by using the MSBuild Package and Deploy that Troy describes.
I can easily disable the Second Build Step i.e. deployment, if I ever need to build the package but not deploy it.
I wanted to use the -skip flag on msdeploy to prevent it from deleting certain folders, which again I couldn't find any method of doing without passing as an argument to the command line.
So, in my first MSBuild step I just have the parameters:
/P:Configuration=%env.Configuration%
/P:VisualStudioVersion=11.0
/P:IgnoreDeployManagedRuntimeVersion=True
And then I have a second Build Step that uses a command line build runner to execute the following msdeploy command:
"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:package="C:\ProgramData\JetBrains\TeamCity\system\artifacts\MyProject\%system.teamcity.buildConfName%\%teamcity.build.id%\MyProject.Web.csproj.zip" -dest:auto,ComputerName='https://devserver:8172/msdeploy.axd?site=MyWebsite',UserName='domain\username',Password='password',IncludeAcls='False',AuthType='Basic' -skip:objectName=dirPath,absolutePath=media$ -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -retryAttempts=2 -allowuntrusted
The problem with this is that apparently TeamCity doesnt publish the artifacts until all the build steps are complete, so therefore the Command Line process fails because the package zip file doesnt actually exist at that point.
I have read something about publishing artifacts whilst the Build is still in progress but that does seem like a bit of a hack.
Any advice would be greatly appreciated.
You would be better have two builds vs two build steps.
The first (Build A) would have 1 build step that would do the building then the second (Build B) would just do the deployment in one build step using the artifacts from the first.
So under the first configuration tab of build A, you would specify the artifacts that would need to be made available from the first build. You can then run the build and confirm that under the artifacts section everything you need is available. (These will show when build A has completed running).
Then under the dependencies section (Can't remember the exact name, and I'm away from my TC instance) of Build B you can set it up to use the artifacts of build A which would then be used for the deployment.
Once you have all that working, you could add a build trigger to have Build B run after a successfull execution of Build A, then if you at one point just wanted to run Build A, disable the trigger on build B or pause the Build B configuration which will stop the trigger from firing.

How to deploy project with msdeploy instead of msbuild

Today I use msbuild to deploy a web application to an iis server. How can I do the same with msdeploy (command line)?
MSBuild.exe myproject.csproj
/P:VisualStudioVersion=11.0
/P:Password=pass
/P:AllowUntrustedCertificate=true
/P:DeployOnBuild=True
/P:PublishProfile=deploytest
/P:DeployIISAppPath="Default Web site"
/P:MsDeployServiceUrl=my.server.com
/P:Configuration=Release
It depends what you would like your workflow to be, if you want to package the output and deploy that seperately then you'll need to create a zip file from your build.
Create Package
Add the following to your msbuild command line to create a package:
/p:DeployTarget=Package
/p:PackageLocation=MyProject.zip
/p:CreatePackageOnPublish=True
Deploy Package
msdeploy.exe
-verb:sync
-source:Package=MyProject.Zip
-destination:auto:ComputerName="my.server.com"
You might also want to promote from one deployed site to another.
Clone Site
msdeploy.exe
-verb:sync
-source:appHostConfig="my.server.com"
-dest:appHostConfig="mynew.server.com"
Or you may already have a site that you want to target.
Clone Application
msdeploy.exe
-verb:sync
-source:iisApp="my.server.com/MyApp"
-dest:iisApp="my.server.com/MyNewApp"

How can I pass MSDeploy-style parameters to MSBuild via the commandline?

I am setting up TeamCity to deploy our Website Project application (using a *.wdproj) and Web Deploy application to IIS.
I have a build configuration that uses MSBuild.exe with the MSDeployPublish to build and then deploy the application.
We now want to get the application to deploy to multiple target environments, therefore need a way to supply different settings based on the target environment.
I have added a parameters.xml file to the Web Deployment Project, and have verified that the parameters set in here are making all the way through the target IIS server and being correctly applied - great!
Now what I want to do is have different parameter settings per environment. I was hoping I could use something like the MSDeploy.exe -setParam argument to specify different values for each environment, however I can find no way to get my parameter values into MSBuild via the commandline.
I suspect I might need to do one of the following:
Split MSBuild and MSDeploy into separate build steps.
Configure a task somewhere in the pipeline to take 1 of n versions of parameters.something.xml and move it into parameters.xml so it gets picked up by the rest of the pipeline.
I'm looking for the simplest way to move ahead at this point, any suggestions welcome.
For reference, here is the command I'm experimenting with now:
msbuild /target:MSDeployPublish MySite_deploy.wdproj /P:Configuration=Debug
/P:DeployOnBuild=True /P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl=www.myserver.com:8172/MsDeploy.axd
/P:AllowUntrustedCertificate=True /P:MSDeployPublishMethod=WMSvc
/P:CreatePackageOnPublish=True /P:UserName=MyUser /p:Password=MyPassword
/P:DeployIisAppPath=www.myserver.com/MySite
/P:ServerURL=http://www.tryingtoforcethis.com
It's working beautifully except the value for ServerURL, which is a parameter I've defined in my parameters.xml, is not making its way into the target site. The default I specified in parameters.xml, however, is. So I know that the parameters are working, I just can't figure out how to add them to the msbuild commandline.
Well, I think the short answer is that with MSBuild 4.0 and VS2010, you can't just pass arbitrary parameters into MSDeployPublish from the call to MSBuild.
I found these posts helpful:
http://forums.iis.net/t/1167657.aspx/1 - Ming Chen's comments
http://www.hanselman.com/blog/TinyHappyFeatures3PublishingImprovementsChainedConfigTransformsAndDeployingASPNETAppsFromTheCommandLine.aspx - the comments from Richard Szalay at the bottom
After reading these, and sifting through the Microsoft.Web.Publishing.targets file for some time trying to find a "way in", I finally settled on having multiple copies of Parameters.xml in my project folder in source control, labelled according to their environment eg:
Parameters.Test.xml
Parameters.Staging.xml
Parameters.Live.xml
Then, prior to the package and deploy, I just copy one of these files into Parameters.xml and it gets picked up by the rest of the pipeline - done!
BTW I had a temporary problem getting the parameters.xml copy and subsequent cleanup to work within a single MSBuild.exe call due to what seems to be some sort of file access issue, I've detailed it here:
MSBuild.exe Copy task not working properly unless a version of the file already appears in target
To answer your question, the parameterization of your command line is not a concern of MSBuild. Instead, you should utilize external tools. For example, if you run your msbuild command from a batch file you could pass the parameters to the batch file and run it for each environment with different parameters. Another approach is to use a build system like TeamCity or VSTS and utilize their parameterization mechanism. Adapted for the VSTS or TFS, your command could look like this:
msbuild MySite_deploy.wdproj /target:MSDeployPublish /p:Configuration=Debug
/p:DeployOnBuild=True /p:MsDeployServiceUrl=$(IIsHostNameIp)
/p:AllowUntrustedCertificate=True /p:MSDeployPublishMethod=WMSvc
/p:CreatePackageOnPublish=True /p:UserName=$(IIsUserName) /p:Password=$(IIsPassword)
/p:DeployIisAppPath=$(IIsSite)
In addition, I would suggest some clean up for your origianl command line:
Using both /p:target and /p:DeployTarget is redundant. Any one of them is enough. Also it could be replaced with /p:WebPublishMethod.
For /p:MSDeployServiceUrl it is enough to only provide a DNS name or IP. the port and the Url is automatically derived from the /p:MSDeployPublishingMethod=WMSVC.
The custom parameter /p:ServerURL is unknown and won't be mapped anywhere.
msbuild.exe {build-script.proj} /property:{someParameter=someValue}
In your build script you can use $(someParameter) as a variable

WebDeploy with MSBuild Not Deploying from TeamCity

I am trying to use MSDeploy to deploy an MVC project to the server using TeamCity. When I do this on my computer in powershell, using the following command:
msbuild.exe .\mvc.csproj /p:PublishProfile=DevServer /p:VisualStudioVersion=11.0
/p:DeployOnBuild=True /p:Password=MyPassword /p:AllowUntrustedCertificate=true
It builds the project and deploys it to the server (info defined in the DevServer publish profile) perfectly. The output shows an MSDeployPublish section at the end, in which I see text like Starting Web deployment task from source... and then with rows telling me what files are updated, etc.
When I run this on TeamCity, using an MSBuild Build step, on the same file, with the same parameters (from the same working directory) it builds the project but does not publish it. Instead it has the regular output from a build process (CoreCompile, _CopyFilesMarkedCopyLocal, GetCopyToOutputDirectoryItems, CopyFilesToOutputDirectory) but then does not actually go and publish anything.
What changes to I need to make to the setup in TeamCity to get it to publish deploy in the same way that it works using MSBuild from my computer?
(TeamCity 7.1, MSBuild 4.0, WebDeploy 3.0, Visual Studio 12, IIS 7. Related to my previous question)
We do our WebDeploys with a TeamCity MSBuild step configured as follows:
Build File Path: Server.csproj
Command Line Parameters:
/p:Configuration=%configuration%
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=https://%web.deploy.server%:8172/MsDeploy.axd
/p:DeployIisAppPath=%web.deploy.site%
/p:AllowUntrustedCertificate=True
/p:Username=
/p:AuthType=NTLM
We use integrated authentication; change as necessary to fit your scheme. The value of this, I think, is that it builds everything from scratch and doesn't rely on a pre-built package. From the gist you posted I noticed that you do some DB publishing, we don't use WebDeploy for that so I can't offer any guidance there. Hope this helps.
I use MSBuild.exe to package to zip, and MSdeploy.exe to deploy in separate steps.
To deploy the package.zip file on the command line:
"C:\Program Files\IIS\Microsoft Web Deploy V2\msdeploy.exe" -verb:sync
-source:package="C:\Build\MyAppName.Debug.zip"
-dest:auto,wmsvc=webservername,username=webdeploy,password=*******
-allowUntrusted=true
This command is also worth explaining in detail:
-verb:sync : makes the web site sync from the source to the destination
-source:package="C:\Build\MyAppName.Debug.zip" : source is an MSBuild zip file package
-dest:auto,wmsvc=webservername : use the settings in the package file to deploy to the server. The user account is an OS-level account with permission. The hostname is specified, but not the IIS web site name (which is previously specified in the MSBuild project file in the project properties).
You can modify parameters based on your configuration. I like it this way because with separate steps, its easier to debug problems.
Use TeamCity build step and the command line runner.
Update:
If you want an example of how to build the ZIP package using MSBuild, try something like this:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
MyWebApp/MyWebApp/MyWebApp.csproj
/T:Package
/P:Configuration=Debug;PackageLocation="C:\Build\MyWebApp.Debug.zip"
This should work the same on your local PC as well as on the CI server.
Here are the config settings that finally worked for me:
/p:Configuration=CONFIG-NAME
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=http://SITE-URL/MsDeployAgentService
/p:username="USERNAME"
/p:password=PASSWORD
/p:AllowUntrustedCertificate=True
/P:CreatePackageOnPublish=True
/p:DeployIisAppPath=SITE-URL
/p:MSDeployPublishMethod=RemoteAgent
/p:IgnoreDeployManagedRuntimeVersion=True
I had exactly the same issue! I've posted the solution I used over at: MsBuild not finding publish profile
Basics were:
Install the Azure SDK 1.8 on the build server
Force the /P:PublishProfileRootFolder value to ensure MSBuild can locate the publish profile
Ensure that you have the Microsoft Web Developer Tools feature installed for Visual Studio. This was missing on my build agent but once I added it the TeamCity build worked just fine.
This can happen when the build target paths are missing from your MSBuild directory. Instead of trying to get those to line up on every developer machine, install the targets from the Nuget. That way it will always be the same for everyone, regardless of how their machine is setup.

Specifying project name in msdeploy

I've got two web projects in one solution, and I'd like to deploy them both using msbuild and WebDeploy (this happens through a CI server).
Currently, I'm running a command line:
C:\ProjectFolder>msbuild <solution>.sln
/p:Configuration=<Release>
/p:OutputPath=bin
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=https://<ServerUrl:port>/msdeploy.axd
/p:username=<user>
/p:password=<password>
/p:AllowUntrustedCertificate=True
/p:DeployIisAppPath=<SiteName>
/p:MSDeployPublishMethod=WMSVC
This deploys one project, as expected. But how can I deploy the other as well? There's nowhere in this command line where I specified a project name - why did it choose one project to deploy over the other?
Ideally, I'd be able to deploy two project with the same command, something like
...
/p:Project=Project1
/p:DeployIisAppPath=<SiteName>/Project1
/p:Project=Project2
/p:DeployIisAppPath=<SiteName>/Project2
But I doubt that's possible. Alternatively, I just want to know how to specify a project name in the command line.
I think it would be better to divide the single call to three:
- Build sln;
- Deploy site1;
- Deploy site2;
msbuild.exe <solution>.sln
/p:Configuration=<Release>
/p:OutputPath=bin
msbuild.exe project1dir\proj1.csproj
/p:Configuration=<Release>
/p:OutputPath=<Path to common bin>
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=https://<ServerUrl:port>/msdeploy.axd
/p:username=<user>
/p:password=<password>
/p:AllowUntrustedCertificate=True
/p:DeployIisAppPath=<SiteName>/Project1
/p:MSDeployPublishMethod=WMSVC
msbuild.exe project1dir\proj2.csproj
/p:Configuration=<Release>
/p:OutputPath=<Path to common bin>
/p:DeployOnBuild=True
/p:DeployTarget=MSDeployPublish
/p:MsDeployServiceUrl=https://<ServerUrl:port>/msdeploy.axd
/p:username=<user>
/p:password=<password>
/p:AllowUntrustedCertificate=True
/p:DeployIisAppPath=<SiteName>/Project2
/p:MSDeployPublishMethod=WMSVC
If you run the command line from the projects' root folder(s), and don't specify a file to build, msbuild should automatically select the project in that folder.
This will require two separate command line calls, tho.
You can then build on this by building a batch file that cd's to each of the folders in turn and runs msbuild separately, or equally build your own proj file for msbuild that triggers each build.
Sorry I can't craft an example at the moment tho-on a phone!