TFS 2010 Solution with multiple dependencies - build

I am new to build on TFS 2010.
I have 4 C# solutions. One of these solution has a dependency on the assembly produced by each of the other 3 "helper solutions".
I'd like to create a build definition which would build my 3 helper solutions then build the top level solution.
On the build definition dialog I have tried to add each of the 4 solution files to the Workspace tab, with a build agent folder of $(SourceDir) - but I get the error dialog "TF215040: The path $(SourceDir) can only be mapped one time in a given workspace". So I change the mapping for the helper solutions to the build folder used by their respective individual build definition.
On the Process Tab, under the Items to Build property I've added the solution file for each of the 4 solutions, with the parent solution listed last.
When I queue the top level build defintion I get the error message: "The path C:\Builds\3\x.Int.Common\x.Int.Common\Sources is already mapped in workspace xBLD01."
Note: when I run "tf.exe workspaces /owner:*" I notice that my workspaces is listed multiple times, with different owners but the computer name is also the same. I guess this is because there's 3 in the team using the same VM image - they're not connected to the domain. Maybe this is the cause of the problem?
Could anyone please suggest a solution?
Thanks
Rob.

Just map the root folder that contains all 4 solutions under it in the workspace mapping. For example, if your folder structure looks like this:
C:\MyProject\Solution1\1.sln
C:\MyProject\Solution2\2.sln
...
Just map C:\MyProject\ -> $(SourceDir)
If the workspace mappings have gotten messed up on your build server you can download the TFS SideKicks tool to delete all the workspaces on the build server, and the TFS Build will just recreate them proper ones next time you run it.

Related

VisualStudio 2017 multiple "Keep Target Branch Version"

After some changes I've to merge the master branch in a dev branch where we deleted tons of files, so the "Resolve Conflicts" page lists all of them and it seems I should process each and every conflict choosing "Keep Target Branch Version". Since they are around 4k of them, is there any way to select all the conflicts I want to be kept from the target branch and resolve them with few clicks? FYI the code is on VSTS. My only alternative I think is could be to delete the 4k files in the master (source) branch as well and then merge into the dev (target) one.
Thanks in advance
You can try below ways to achieve that:
Select all (select the first item, hold Shift and select the last item.) then click "Keep Target Branch Version".
Another way is using the Resolve Command:
tf resolve ..... /auto:TakeTheirs will "Take Source Branch Version." My suggestion is to do the resolve, then check your branch
and make sure that you have what you expect before you check in.
tf resolve .... /auto:KeepYours will "Keep Target Branch Version"
Following below steps to do that:
Merger from one branch to another from Visual Studio (Conflicts
appear)
Open cmd console Developer Command Prompt for VS2017
cd to workspace location
Run below command (It will prompt the dialog to enter your credential to login VSTS):
tf resolve /auto:KeepYours

TFS 2017 Build - Customize the "agent_builddirectory" name

in TFS 2017.2 the agent_builddirectory is a consecutive number. I would like to change it to be the Build Definition Name.
How can I achieve that?
Regards!
No, we cannot customize the “agent_builddirectory” name, unless you reconfigure the agent to change the work folder (create a folder and set the build definition name as the folder name ) before trigger build with the specific build definition.
The alternative way would be create a source folder with the specific build definition name as the folder name on the agent machine.
For example "C:\BuildDefinitionName1" and then add a "Copy Files" task in your build definition to copy the source code from "$(build.sourcesdirectory)" to "C:\BuildDefinitionName1". And then update the settings for other task to run build/test from "C:\BuildDefinitionName1" folder. Make sure to check the "Overwrite" option for "Copy Files" task.
Reference this similar thread: TFS 2015 Build: How to change Agent.BuildDirectory
Most steps of a build execution (e.g. get sources, test assemblies, publish result) are somehow logging their working folder.
By looking at the results of a previously run build you will find out the folder you are looking for.

TFS 2015 builds : Is it possible to use Variables in Repository mappings?

When creating a vNext build on TFS 2015 you can define variables, which are then used in build steps, and can also be used as environment variables in scripts the build runs.
The build I am working on runs scripts that pulls files from mapped locations, so it would be great if I could define a variable and use it in a mapping so that for example, if I update a reference in the project the build is building, I can simply update the variable with the new location and have the repository mappings and scripts all pull correctly from the new location without having to make the change in multiple places.
I have tried doing this by setting up the variable and mapping as follows,
But this generates an error when you try to save the build complaining that there are two '$' characters in the mapping. Is there way to do this or is this not currently possible?
This has been causing me havok for quite a while as well.
For starters, there is a uservoice request for this feature. You can add your votes and input here to get Microsoft to allow this feature: https://visualstudio.uservoice.com/forums/330519-team-services/suggestions/14131002-allow-variables-in-repository-variables-and-trigg
Second, we've developed a workaround that gets us most of the way there. It's not perfect, but it might be useful to you if you're comfortable with the tradeoffs or can work around the deficiencies.
Start by turning off the "Label Sources" option of the build and mapping the Server Path field to you base build. You'll want to add a custom variable to the Build Definition to tell the build instance what TFS location to pull from. For example, we have a base project and then multiple branches from the project, so our source is structured like this
$\Team Project\Project1
$\Team Project\Project1Branch1
$\Team Project\Project1Branch2
$\Team Project\Project1Branch3
and we create a variable named "Branch" that we can set to "Branch1", "Branch2", and so forth.
When we want to build the base project, we leave the Branch variable blank when launching the build. For branch builds, we set it to the name of the branch we want to build.
Then our build steps look like this
Remap Workspace Folder to Branch Folder
Get Files for Specified Branch - We have to do this manually after
remapping our workspace
Compile the Source in the Specified Branch
Publish Build Artifacts from the Specified Branch
Label the Code of the Specified Branch Manually
The Remap task runs the command
tf workfold "$/Team Project/Project1$(Branch)" "$(build.sourcesDirectory)\$(Build.DefinitionName)$(Branch)"
The Manual Get task runs the following command
get /recursive /noprompt "$/Team Project/Project1$(Branch)"
The build uses the Branch variable to point to the correct location of the solution file for the specified branch
$(build.sourcesDirectory)\$(Build.DefinitionName)$(Branch)\SolutionFile.sln
The Publish Artifacts task uses the Branch variable in both the Contents field and the Path field
Example in Contents
**\$(Build.DefinitionName)$(Branch)\bin
The Label Code task uses the following command
tf label "$(build.buildNumber)" "$/Team Project/Project1$(Branch)" /recursive
The downside of this setup is that you don't capture Associated Changes and Work Items to your subsidiary branches as the Server Path field is always set to the main location. This may not be an issue if you always merge from your branches to your main location prior to launching a build meant to go to production. What you can do to compensate for this really depends on your use case.
With some tweaking, you could use this same format to specify full paths as well if you needed to.
It's impossible. Just as the error message mentioned: there are two '$' characters in the mapping. Which means your application's path shouldn't vary from build to build.
Mappings on the Repository page are used to specify source control
folder which contains projects that need to be built in the build
definition. You can set it via clicking the Ellipsis (...) button,
however, you can't include variables in the mapping path.
There is a similar question: Variables in TFS Mappings on Visual Studio Online Team Builds

Using AsConfigured and still be able to get UnitTest results in TFS

So I am running into an issue when I go to build my projects using tfs build controller using the Output location "AsConfigred" it will not detect my unit tests. Let me give a little info on my setup.
TFS 2013 Update 2, Default Process Template
Here is a few screenshots that can hopefully help fill in what I can't in typing. I am copying my build out to a file share on our network so that we can use other utilities use the output. I don't want to use "PerProject" or "SingleFolder" because they mess up the file structure we have configured (These both will run the tests). So i have the files copy to folder names "SingleOutputFolder" which is a child of the DropLocation. I would like to be able to run from the drop folder or run from the bin folder for each of my tests (I don't care which). However it doesn't seem to detect/run ANY of the tests. Any help would be greatly appreciated. Please let me know if you need any additional information.
I have tried using ***test*.dll, Install\SingleFolderOutput**.test.dll, and $(TF_BUILD_DROPLOCATION)\Install\SingleFolderOutput*test*.dll
But I am not sure what variables are available and understand where the scope of its execution is.
Given that you're using Build Output location set to AsConfigured you have to change the default values of the Test sources spec setting to allow build to find the test libraries in the bin folders. Here's an example.
If the full path to the unit test libraries is:
E:\Builds\7\<TFS Team Project>\<Build Definition>\src\<Unit Test Project>\bin\Release\*test*.dll
use
..\src\*UnitTest*\bin\*\*test*.dll;
This question was asked on MSDN forums here.
MSDN Forums Suggested Workaround
The suggested workaround in the accepted answer (as of 8 a.m. on June 20) is to specify the full path to the test projects' binary folders: For example:
C:\Builds\{agentId}\{teamProjectName}\{buildDefinitionName}\src\{solutionName}\{testProjectName}\bin*\Debug\*test*.dll*
which really should have been shown as
{agentWorkingFolder}\src\{relativePathToTestProjectBinariesFolder}\*test*.dll
However this approach is very brittle, for the following reasons:
Any new test projects you add to the solution will not be executed until you add them to the build definition's list of test sources:
It will break under any of the following circumstances:
the build definition is renamed
the working folder in build agent properties is modified
you have multiple build agents, and a different agent than the one you specified in {id} runs the build
Improved Workaround
My workaround mitigates the issues listed in #2 (can't do anything about #1).
In the path specified above, replace the initial part:
{agentWorkingFolder}
with
..
so you have
..\src\{relativePathToTestProjectBinariesFolder}\*test*.dll
This works because the internal working directory is apparently the \binaries\ folder that is a sibling of the \src\ folder. Navigating up to the parent folder (whatever it is named, we don't care) and back in to \src\ before specifying the path to the test projects binaries does the trick.
Note: If you have multiple test projects, you add additional entries, separated with semicolons:
..\src\{relativePathToTestProjectONEBinariesFolder}\*test*.dll;..\src\{relativePathToTestProjectTWOBinariesFolder}\*test*.dll;..\src\{relativePathToTestProjectTHREEBinariesFolder}\*test*.dll;
What I ended up doing was adding a post build event to copy all of the test.dll into the staging location folder in the specific build that is basically equivalent to where it would go on a SingleFolder build and do that on each test project.
if "$(TeamBuildOutDir)" == "" (
echo "Building Interactively not in TFS"
) else (
echo "Building in TFS"
xcopy "$(TargetDir)*.*" "$(TeamBuildBinaries)\" /Y /E /S
)
MSBUILD parameter in the build def that told it to basically drop in the folder that TFS looks for them.
/p:TeamBuildBinaries="$(TF_BUILD_BINARIESDIRECTORY)"
Kept the default Test assembly file specification:
**\*test*.dll
View this link for the information on the variable that I used and what relative path it exists at.
Another solution is to do the reverse.
Leave all of the files in the root so that all of the built in functionality works. There is more than just test execution in there. What about static code analysis, impact analysis..among others. You would have to do something custom for them all.
Instead use a pre-drop powershell script to create your Install arrangement from the root files.
If it is an application then you can use the _ApplicationFolder Nuget package to create an _PublishApplications folder same as you get for web applications.

Incremental build in TFS - How do I update AssemblyInfo.cs version only for projects that have changed?

We have a solution in TFS 2012 that contains several projects. I have set up a Continuous Integration build on our build server and have set Clean Workspace = None. I'm using the TFS Versioning template 2.0 to update the AssemblyFileVersion and AssemblyVersions.
When the build is run, each project has its AssemblyInfo.cs file updated with a new version number even though there have been no changes made to the code in some of the projects. Ideally we want the version to change only if there have been changes to the project.
I was considering building each project separately, but we would prefer to be able to simply build the solution. I have read that Clean Workspace = None should prevent the projects from being updated but it doesn't appear to be happening for me since the timestamp on all the dll's are showing as changed after the build.
I am new to setting up a build process, so I'm hoping there is something simple that I'm doing wrong. Any suggestions would be greatly appreciated.
Update:
After checking the suggested link, it appears that I'm doing two things during build that may be causing the issue: 1) web.config file transforms that take place in an "AfterBuild" step in one of my projects and 2) using the version number increment features in the "TFS Versioning" template without opening up the workflow to see how it is checking for changed files. I'll remove both of these and see what happens.
This is a good question and it is possible. I run powershell scripts that use the TFS API to determine what files have changed
You need to get the changesets and shelvesets also, but once you have these you can get the information you want like this:
function Get-ChangesetChanges()
{
[CmdletBinding()]
param ([Parameter(Mandatory=$true)][string]$Changeset,[Parameter(Mandatory=$true)][string]$TFSServer)
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.VersionControl.Client')
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.TeamFoundation.Client')
$tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($TFSServer)
$vcs = $tfs.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$vcsChanges = $vcs.GetChangeset($changeset).Changes;
$changes = #();
foreach ($change in $vcsChanges)
{
$changes += $change.Item.ServerItem;
}
$changes;
}