TeamCity + MSBuild: Tagging a deployment with a VCS build number - msbuild

I am using TeamCity 4.5.1 to build and deploy an ASP.Net application to development.
This is working perfectly so far, however, my manager has asked that I tag the folder with the specific SVN Revision from which the source was compiled.
I am using an MSBuild script to do the build and deployment, however, I am unable to successfully retrieve the build number.
Here is the MSBuild command I'm using (sanitized):
<Exec Command=">\\server08\D$\Websites\MYPROJECT\version.txt echo %env.BUILD_VCS_NUMBER%,%env.BUILD_VCS_NUMBER.1%,%system.build.vcs.number%,%system.build.vcs.number.1%,%system.build.number.format%,%system.build.number.format.1%,%system.build.vcs.number.MYPROJECT_Web_Root%,%env.TEAMCITY_VCS_NUMBER_MYPROJECT_Web_Root%" />
Version.txt turns up like this:
,,,,,,,,
Aka, empty. What am I doing wrong? Any better way to do this?

%env.XYZ% is TeamCity's method of referring to the environment variables, if you want to use them in ITS settings anywhere.
In a batch file or via msbuild, you only want the XYZ part.
echo %BUILD_VCS_NUMBER% > \\path\to\version.txt

Related

Deploying Azure Resource Group project as a part of MsBuild script

I'm trying to migrate our solution from classic to Resource Manager deployment and I've stuck with running the RM deployment as a step of MsBuild build script. For the classic project there is
<MSBuild Projects="SomeAzureProject\SomeAzureProject.ccproj"
Targets="Publish"
Properties="
VisualStudioVersion=$(VisualStudioVersion);
Configuration=$(CloudConfiguration);
Platform=$(Platform);
TargetProfile=$(CloudTargetProfile);
PublishProfile=$(CloudPublishProfile);
PublishDir=$(CloudPublishDir);"></MSBuild>
build step.
Is there something like this for the .deployproj ? If yes - what parameters should be passed to it? (we need to be able to pass at least resource group name, params file name and the template file name).

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.

How to create a TFS2010 Team Build Template for getting source and call msbuild.exe

I have a build.proj, that is a MSBuild file and can be run locally.
All I need from TFS is
Get the sources from TFS Source Control.
Call "MSBuild.exe /t:Deploy".
Update the build status based on the result of MSBuild.
I have tried to make a template combining the DefaultTemplate.xaml and UpgradeTemplate.xaml.
But so far, no luck :-(
Can someone help me make this template?
If you select the upgrade template that comes out of the box when you create a new TFS project with 2010, you can supply your old TFS2008 proj (MSBuild) file without problems. Please read http://msdn.microsoft.com/en-us/library/dd647553.aspx for more details.
You should use DefaultTemplate. I had the same problem and I solved it this way.
You can do it using UpgradeTempate also, but using DefaultTemplate was easier for me.
On Process section follow these steps:
Select Default template
Add your project into Items To Build collection
Set MSBuild Arguments (Advanced section) to "/t:Deploy"
I have MSBuild project file for running builds locally. This script is used also for sever builds. I have three MSBuild projects in Items To Build collection. One for PreBuild step (some checks before build is executed), main build script used also for local build and the last script for additional post build tasks (deploy process). I'm setting additional MSBuild propertires like IncrementalBuild and ServerBuild properties in MSBuild Arguments.

How can you publish a ClickOnce application through CruiseControl.NET?

I have CruiseControl.NET Version 1.4 set up on my development server. Whenever a developer checks in code, it makes a compile.
Now we're at a place where we can start giving our application to the testers. We'd like to use ClickOnce to distribute the application, with the idea being that when a tester goes to test the application, they have the latest build.
I can't find a way to make that happen with CruiseControl.NET. We're using MSBUILD to perform the builds.
We've done this and can give you some pointers to start.
2 things you should be aware of:
MSBuild can generate the necessary deployment files for you.
MSBuild won't deploy the files to the FTP or UNC share. You'll need a separate step for this.
To use MSBuild to generate the ClickOnce manifests, here's the command you'll need to issue:
msbuild /target:publish /p:Configuration=Release /p:Platform=AnyCPU; "c:\yourProject.csproj"
That will tell MSBuild to build your project and generate ClickOnce deployment files inside the bin\Release\YourProject.publish directory.
All that's left is to copy those files to the FTP/UNC share/wherever, and you're all set.
You can tell CruiseControl.NET to build using those MSBuild parameters.
You'll then need a CruiseControl.NET build task to take the generated deployment files and copy them to the FTP or UNC share. We use a custom little C# console program for this, but you could just as easily use a Powershell script.
Thanks for all the help. The final solution we implemented took a bit from every answer.
We found it easier to handle working with multiple environments using simple batch files. I'm not suggesting this is the best way to do this, but for our given scenario and requirements, this worked well. Supplement "Project" with your project name and "Environment" with your environment name (dev, test, stage, production, whatever).
Here is the tasks area of our "ccnet.config" file.
<!-- override settings -->
<exec>
<executable>F:\Source\Project\Environment\CruiseControl\CopySettings.bat</executable>
</exec>
<!-- compile -->
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe</executable>
<workingDirectory>F:\Source\Project\Environment\</workingDirectory>
<projectFile>Project.sln</projectFile>
<buildArgs>/noconsolelogger /p:Configuration=Debug /v:diag</buildArgs>
<targets>Rebuild</targets>
<timeout>0</timeout>
<logger>ThoughtWorks.CruiseControl.MsBuild.XmlLogger,ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
<!-- clickonce publish -->
<exec>
<executable>F:\Source\Project\Environment\CruiseControl\Publish.bat</executable>
</exec>
The first thing you will notice is that CopySettings.bat runs. This copies specific settings for the environment, such as database connections.
Next, the standard MSBUILD task runs. Any compile errors are caught here and handled as normal.
The last thing to execute is Publish.bat. This actually performs a MSBUILD "rebuild" again from command line, and parameters from CruiseControl are automatically passed in and built. Next, MSBUILD is called for the "publish" target. The exact same parameters are given to the publish as the rebuild was issued. This keeps the build numbers in sync. Also, our executables are named differently (i.e. - ProjectDev and ProjectTest). We end up with different version numbers and names, and this allows ClickOnce to do its thing.
The last part of Publish.bat copies the actual files to their new homes. We don't use the publish.htm as all our users are on the network, we just give them a shortcut to the manifest file on their desktop and they can click and always be running the correct executable with a version number that ties out in CruiseControl.
Here is CopySettings.bat
XCOPY "F:\Source\Project\Environment\CruiseControl\Project\app.config" "F:\Source\Project\Environment\Project" /Y /I /R
XCOPY "F:\Source\Project\Environment\CruiseControl\Project\My Project\Settings.Designer.vb" "F:\Source\Project\Environment\Project\My Project" /Y /I /R
XCOPY "F:\Source\Project\Environment\CruiseControl\Project\My Project\Settings.settings" "F:\Source\Project\Environment\Project\My Project" /Y /I /R
And lastly, here is Publish.bat
C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /target:rebuild "F:\Source\Project\Environment\Project\Project.vbproj" /property:ApplicationRevision=%CCNetLabel% /property:AssemblyName="ProjectEnvironment" /property:PublishUrl="\\Server\bin\Project\Environment\\"
C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /target:publish "F:\Source\Project\Environment\Project\Project.vbproj" /property:ApplicationVersion="1.0.0.%CCNetLabel%" /property:AssemblyVersion="1.0.0.%CCNetLabel%" /property:AssemblyName="ProjectEnvironment"
XCOPY "F:\Source\Project\Environment\Project\bin\Debug\app.publish" "F:\Binary\Project\Environment" /Y /I
XCOPY "F:\Source\Project\Environment\Project\bin\Debug\app.publish\Application Files" "F:\Binary\Project\Environment\Application Files" /Y /I /S
Like I said, it's probably not done the way that CruiseControl and MSBUILD developers had intended things to work, but it does work. If you need to get this working yesterday, it might be the solution you're looking for. Good luck!
I remember doing this last year for a ClickOnce project I was working on. I remember it taking me forever to figure out but here it is. What I wanted my scripts to do was to generate a different installer that pointed to our dev env and a different one for prod. Not only that but i needed it to inject the right versioning information so the existing clients would 'realize' there is a new version out there which is the whole point of clickOnce.
In this script you have to replace with your own server names etc. The trick is to save the publish.htm and project.publish file and inject the new version number based on the version that is provided to you by CC.NET.
Here is what my build script looked like:
<target name="deployProd">
<exec program="<framework_dir>\msbuild.exe" commandline="<project>/<project>.csproj /property:Configuration=PublishProd /property:ApplicationVersion=${build.label}.*;PublishUrl=\\<prod_location>\binups$\;InstallUrl=\\<prod_location>\binups$\;UpdateUrl=\\<prod_location>\binups$\;BootstrapperComponentsUrl=\\<prod_location>\prereqs$\ /target:publish"/>
<copy todir="<project>\bin\PublishProd\<project>.publish">
<fileset basedir=".">
<include name="publish.htm"/>
</fileset>
<filterchain>
<replacetokens>
<token key="CURRENT_VERSION" value="${build.label}"/>
</replacetokens>
</filterchain>
</copy>
</target>
Hope this helps
Just be able passing the ${CCNetLabel} in the CCNET.config msbuild task would be a great improvement.
You want to use the ClickOnce manifest generation tasks in msbuild. The process is a little long winded, so I am just going to point you to a couple of links. Here is the reference on msdn and a sample article to hopefully get you started.