Team Build: Publish locally using MSDeploy - tfs

I'm just getting started with the team build functionality and I'm finding the sheer amount of things required to do something pretty simple a bit overwhelming. My setup at the moment is a solution with a web app, an assembly app and a test app. The web app has a PublishProfile set up which publishes via the filesystem.
I have a TFS build definition set up which currently builds the entire solution nightly and drops it onto a network share as a backup of old builds. All I want to do now is have the PublishProfile I've already setup publish the web app for me. I'm sure this is really simple but I've been playing with MSBuild commands for a full day now with no luck. Help!

Unfortunately sharing of the Publish Profile is not supported or implemented in MSBuild. The logic to publish from the profile is contained in VS itself. Fortunately the profile doesn't contain much information so there are ways to achieve what you are looking for. Our targets do not specifically support the exact same steps as followed by the publish dialog, but to achieve the same result from team build you have two choices, I will outline both here.
When you setup your Team Build definition in order to deploy you need to pass in some values for the MSBuild Arguments for the build process. See image below where I have highlighted this.
Option 1:
Pass in the following arguments:
/p:DeployOnBuild=true;DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;PackageTempRootDir="\\sayedha-w500\BuildDrops\Publish";AutoParameterizationWebConfigConnectionStrings=false
Let me explain these parameters a bit, show you the result then explain the next option.
DeployOnBuild=true:This tells the project to execute the target(s) defined in the DeployTarget property.
DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder: This specifies the DeployTarget target.
PackageTempRootDir="\\sayedha-w500\BuildDrops\Publish": This specifies the location where the package files will be written. This is the location where the files are written before they are packaged.
AutoParameterizationWebConfigConnectionStrings=false: This tells the Web Publishing Pipeline (WPP) to not parameterize the connection strings in the web.config file. If you do not specify this then your connection string values will be replaced with placeholders like $(ReplacableToken_dummyConStr-Web.config Connection String_0)
After you do this you can kick off a build then inside of the PackageTempRootDir location you will find a PackageTmp folder and this contains the content that you are looking for.
Option 2:
So for the previous option you probably noticed that it creates a folder named PackageTmp and if you do not want that then you can use the following options instead.
/p:DeployOnBuild=true;DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;_PackageTempDir="\\sayedha-w500\BuildDrops\Publish";AutoParameterizationWebConfigConnectionStrings=false
The difference here is that instead of PackageTempRootDir you would pass in _PackageTempDir. The reason why I don't suggest that to begin with is because MSBuild properties that start with _ signify that the property in essentially "internal" in the sense that in a future version it may mean something else or not exist at all. So use at your own risk.
Option 3
With all that said, you could just use the build to package your web. If you want to do this then use the following arguments.
/p:DeployOnBuild=true;DeployTarget=Package
When you do this in the drop folder for your build you will find the _PublishedWebsites folder as you normally would, then inside of that there will be a folder {ProjectName}_Package where {ProjectName} is the name of the project. This folder will contain the package, the .cmd file, the parameters file and a couple others. You can use these files to deploy your web.
I hope that wasn't information over load.

The ability to publish web sites, configure IIS and push schema changes for the DEV->QA->RELEASE cycle has required either custom configuration to imitate publish or custom code where IIS settings are involved.
As of Visual Studio 2013.2 Microsoft has added a third party product that manages deployment of web sites, configuration changes and database deployment with windows workflow and would be the recommended solution for automating deployment from TFS build.
More information can be found here:
http://www.visualstudio.com/en-us/explore/release-management-vs.aspx

You can use the Publish/Deploy in Visual Studio 2010.
See http://www.ewaldhofman.nl/post/2010/04/12/Auto-deployment-of-my-web-application-with-Team-Build-2010-to-add-Interactive-Testing.aspx for more information

Related

What is the appropriate location of Azure Devops/TFS Release "support files" (Powershell, Configuration etc.)?

On TFS 2018.2, I am building a release pipeline implying the use of :
Applications configuration files
PowerShell scripts
HTML/Markdown templates (for release notes)
My applications configuration files are located on a net share for now and that works fine but I would like to version them later on.
I was about to store other files on my existing TFVC repository but I did not find a way to get them (with their directory) without adding the entire repository as a release input artifact.
I do not want to add them to my build artifacts since these files will be used for all my releases, no matter the applications I am building.
What is the recommended way
to store these files
to get them on release execution ?
I have been tempted to use the library but I feel this would be a misuse of it since it has been designed for secure files...
The correct solution to this problem is something you've already hit upon: Add them to your build artifacts. In fact, it's better than pulling them from a separate repo for a very important reason:
Your deployment scripts are going to evolve along with your application. You lose the connection between "this version of the application was deployed with these particular scripts" if the scripts come from a separate location.
You have a lot of options to control the circumstances under which they get pubilshed/downloaded:
You can use conditions on the publish artifacts tasks to control when they get published
You can use artifact filters on the release definition to control when they get downloaded as part of a release

Customizing Drop Folder Structure with TFS Team Build

I'm using TFS 2012 to automate a build of a solution which contains multiple windows services and two web applicaitons.
I've used the guide I found here to customize the build process template so that the windows services are put in a folder structure that I like. Specifically:
\dropserver\droproot\MyApp\BuildNumber\
\Service1
\Service2
\Service3
\Service4
This works great, but unfortunately it doesn't work for web applicaitons. If I used the same strategy for those, I just get the contents of /bin for each web app, rather than the full site contents.
MSBuild typically uses the web application targets to handle this, but for some reason, this doesn't work when you customize the build as I have. I no longer get the _PublishedWebSites folder in the build output. (I'm guessing that's because I cleared our the OutDir property of the MSBuild task.)
Has anybody done something like this and gotten it to work with web applications as well?
I think I can help with this, it looks like in the build targets that the published websites folder isn't created if the OutDir is the same as the OutputPath.
So this isn't perfect, but if you add the following into the csproj file in the first property group, you'll get everything deployed into "\bin\deploy\" including the _PublishedWebsites folder
<DeployOnBuild>True</DeployOnBuild>
<OutDir>bin\deploy\</OutDir>
With a bit of customization, this solution ended up working for me:
http://www.edsquared.com/2011/01/31/Customizable+Output+Directories+For+TFS+2010+Build.aspx
Basically, did what that link recommended, but also leveraged a new solution configuration (which I called TeamBuild) rather than conditional property definitions.
I believe the key to making this all work was the passing of the outputDirectory as the TeamBuildOutDir argument to MSBuild. Embedding this variable reference in the OutDir or OutputPath variable was allowed Team Build to build to the correct staging location and then automatically copy files from that location to the drop folder.
I'm going to take this a little futher and get rid of the whole _PublishedWebSites thing, but that will be done entirely in the build workflow.
EDIT: TFS 2013 supports this natively with a simply build configuration option:
Take a look at this thread as this post as well.
Team Build: Publish locally using MSDeploy
Since you need all the files for your web projects, you need to trigger the publishing process, and by tweaking the destination of that process, you can have all of your files copied where you need them.
I think option (2) from his answer will work for you.
I hope that helps.
As I can see in your reference link, it will just compile and package the binaries. It does not deploy the website by the steps mentioned in that.
If you want to get the .html, .css, .js etc. under the _PublishedWebSites folder, you need to do a Web Deployment. This manually we can do by clicking the publish option from right click menu of your VS project and by selecting Publish Method as File System.
But, since you need to automate this in your build and drop it in custom drop folder, you may need to manipulate your MSBuild script by calling a AspNetCompiler task. You can get more information on this at the MSDN link. By specifying the TargetPath while you call this target you can get your Web files deployed at the appropriate custom drop folder.
Happy Scripting.
Have you check this blog, this solved my problem where I wanted customized TeamBuild Ouput Directory.
Customizable O/P with TFS 2013
Customizaable O/P with TFS 2012 and .NET Framework 4.5

Including empty folders in tfs build

Our C# solution has a couple of folders that are populated via post-build events (i.e. they are initially empty).
The solution builds fine locally, however when using the TFS build agent, the folders don't show up in the published websites folder.
Any suggestions on how to force TFS to copy the folders over?
This is addressed here: publish empty directories to a web application in VS2010 web project
TFS does not execute the AfterBuild target of your proj file. I believe it will execute the AfterCompile target but this still might not do what you want.
I have used the approach of including dummy files which is simple enough even though its lame.
I've tried the approach of including a powershell script to do some post-publish tasks which works.
More recently I have adopted a convention of including a supplemental MSBuild file that ends in ".package.proj" and added an additional MSBuild execution activity to my Team Build Template that looks for it after the files are dropped to the drop location and then executes it. This provides a simple hook into the Team Build workflow without getting you deep into changing the workflow for a particular build. It's just a single additional activity wrapped in a conditional that looks for the file. If found, execute it.
You could also make a custom build template and use the Workflow activities to perform various cleanup tasks, but it's probably overkill and will increase maintenance on the build templates. Better to keep the customization simple if you can and have it function in a way that doesn't require "opt-out" configuration on builds that don't require the customization. Existing vanilla builds should continue to work as expected after the customization to the template.

Teambuild / MSBuild and stamping QA-approved builds

We have an automated build and QA process for our software, using tfs/teambuild and msbuild, and we want to be able to know (for audit purposes) whether a component has gone through that process or not.
For example, if a library is installed on a user's machine, I'd like to be able to inspect it in some way to tell that it went through the build. In particular, I want to be able to distinguish it from components built directly on a developer's machine, and then manually installed.
What is the best way to do this? Code signing as part of the build process seems closest to these requirements, but presumably this would not cover any 3rd-party libraries that might be used? I also read about the ILMerge tool to merge all assemblies into one, but then I don't know enough to work out whether they can then be signed or not?
I'm sure we're not the first people to have the requirement, so casting around for any ideas or hints from others who might have done such a thing
Thanks!
Our developer builds are set to keep the versions at "0.0.0.0", but our build server marks the build based on a pre-configured version and automagically generated build string. "1.0.3.xxx". Your build server doesn't allow for this?
Your build process should be updating each of your projects assemblyinfo.cs files (or a global linked equivalent), you can do this with the TFS changeset number, so like the previous poster indicated you end up with the property on each dll of 1.0.changeset.buildno or something similar. You can do this easily in msbuild.
You could have the values of each assembly info file set in source control to be something obvious like 0 or 999.
A lot of what your asking is about process and training as well though.
If your using installers or zips to package your deliverables then you can also label them with the build number as part of your build process.
But if you have changeset you have the link from dll to code, so traceable, coupled with links to third party dll references as defined in each csproj.

TFS 2010 Build Definition

In the TFS 2010 build definition window, under “Process” there are two required items. They are “Configurations to build” and “Projects to build”. Under projects to build, it will allow me to enter something like:
$/TeamProject/Area1/Area2/*
However, this doesn’t seem to do what I expect. The build fails because it’s looking for:
$/TeamProject/Area1/Area2/Sources/*
What I am trying to achieve by this is to build all the solutions held under this area. For example, I have:
$/TeamProject/Area1/Area2/Solution1/Solution1.sln
$/TeamProject/Area1/Area2/Solution2/Solution2.sln
$/TeamProject/Area1/Area2/Solution3/Solution3.sln
There are many more solutions than this, which is why I’m looking for a way to build all solutions under the specified path recursively. Is there a way to do this in TFS 2010?
You can modify the process template. Expand it with the Matching files (I don't have the exact naming now) activity. Add a parameter that passes the information you set in the build defintion to the MachingFiles actvity. Then pass into the build solution activity instead of the argument that you enter in the build definition the files that is found by the MatchingFiles activity.
Now add a dummy solution in the build definition for the solution to build (it is not used anymore).
See the blog post series on the build customization for more information on customizing the build process template.
FWIW,
I've got: "configurations to build" blank
and under "projects to build" I've added my solutions via the ellipsis button
I would setup mappings for
$/TeamProject/Area1/Area2/Solution1/
$/TeamProject/Area1/Area2/Solution2/
$/TeamProject/Area1/Area2/Solution3/
Then in the build definitions enter the three projects to build
$/TeamProject/Area1/Area2/Solution1/Solution1.sln
$/TeamProject/Area1/Area2/Solution2/Solution2.sln
$/TeamProject/Area1/Area2/Solution3/Solution3.sln
You can leave the configurations to build as blank, or if you want to do a certain build you can set it to (for example) something like Debug|Mixed Platforms (check your Configuration Manager... for the solutions you are building to see what is valid)
Alternatively, you can just map the following (depending on how much you have in this folder, if you have Solutions 4+ that you don't want to trigger builds on, don't do it at this level)
$/TeamProject/Area1/Area2
And have one solution which contains the Solution1, Solution2 and Solution3, and build that instead.
By default building your Solution1 which is mapped to
$/TeamProject/Area1/Area2
On a build agent with a working directory that is going to looks something like:
$(SystemDrive)\Builds\$(BuildAgentId)\$(BuildDefinitionPath)
You'll end up with it being build under
C:\Builds\1\Solution1\Binaries
C:\Builds\1\Solution1\Sources
C:\Builds\1\Solution1\TestResults
Which is why you want to make sure that your OutDir's etc are all correct and not hard coded!
If you have a look while building, you'll see the build agent populating the Sources folder, and it should (if configured correctly) put all outputs into the Binaries folder (and then copy them to the Drop Folder configured under Build Defaults in TFS.

Resources