TFS Label Inconsistency - tfs

I've been working with Team Foundation Server 2012 to get a Continuous Integration build for a data warehouse project working. In doing so I noticed that the labeling and building from a label wasn't yielding the results that I was expecting. In researching the problem I was able to replicate the issue using only the command line arguments provided by Team Foundation Servers Command Line tools. That helped me to eliminate anything in the build definition that may have been affecting the build.
So this is my problem:
I have a build that is building 2 different projects in a single build. It basically has two *.SLN files associated with it. I applied a label to 2 assets, one in each project. I can then execute the command to view which assets have the label. When doing this I get the expected result. However, when I execute the command to get the assets associated with this label it only pulls 1 of the two files. I've verified that I can pull both files, by removing one of the projects. This is the setup that I have with the build definition, work space and label
TFS Paths: $/Dev/Project1
$/Dev/Project2
Workspace Mapping
Project1: C:/SourceControl/Project1
Project2: C:/SourceControl/Project2
DeploymentFolder
Project1: //DevServer/SSIS/Project1
Project2: //DevServer/SSIS/Project2
Executed Commands:
Apply Label: tf label TestLabel $/DEV/Project1/PackageA.dtsx
tf label TestLabel $/DEV/Project2/PackageA.dtsx
Review Label: tf labels /format:Detailed LTestLabel
Get From Label:
tf get /r /version:LTestLabel
After executing the tf get command I get the following results
Deployment folder: //DevServer/SSIS/Project1 contains the file PackageA.dtsx
Deployment folder: //DevServer/SSIS/Project2 contains 0 Files.
It appears that there is a filter or restriction on pulling assets in different projects with the same label. I would expect that if I apply a label to any asset in TFS, then pull the labels, it should allow me to retrieve all assets with that applied label. Has anyone heard or experienced this? Any help provided would be appreciated.

You don't specify what (local) folder you're in when you execute the get: since you don't specify a folder to get, it implies the current one, equivalent to:
tf get /recursive /version:Llabelname .
If you want to get both, specify a directory containing both, for example:
tf get /recursive /version:Llabelname $/
This, of course, assumes that both the files in your label are mapped.

Related

How can I get the numbers of folders in _work folder in agent?

I want to get the number inside the _work folder of an on-premise TFS agent.
For example:
From C:/agent/_work/1 get the 1.
Is there a variable to get the 1 part?
You can use a small PowerShell script to extract the number and set a new variable for the sequences steps:
$folderPath = "$env:Agent_BuildDirectory"
$folderNumber = $folderPath.Split('\')[$folderPath.Split('\').Count - 1]
Write-Host "##vso[task.setvariable variable=folderNumber]$folderNumber"
Now you can use the variable $(folderNumber) in the sequences tasks.
There is no reason for you to parse this information out. The current working folder for a given build or release is accessible in the variable $(Agent.BuildDirectory).
If you are trying to reference the working folder of a different build, then you are doing something wrong with your build process, and there are a number of different, valid solutions to that problem.
Check out the different variable values and ways to customize them if needed. Note the Agent.DeploymentGroupId is is not something you would change.
Release variables and debugging
Agent.DeploymentGroupId
The ID of the deployment group the agent is registered with. This is available only in deployment group jobs.
Example: 1
Agent.WorkFolder
The working directory for this agent, where subfolders are created for every build or release. Same as Agent.RootDirectory and System.WorkFolder.
Example: C:\agent_work

Is it possible to compare files using Plastic SCM Command Line 'cm diff' function?

I'd like to compare two files at particular changesets to see if they are identical or not.
Something like:
>> cm diff rev:Folder\MyFile.py#cs:5 rev:Folder\MyFile.py#cs:10
<< True
I'm getting an error (can't find revision of file I specify) and I think I might not be using diff as it's intended. I've worked around my confusion by using getfile on the particular file and changesets I'm comparing and using a python library file compare.
Thanks.
The Plastic SCM default diff tool will open a GUI showing you the file differences.
But you can manually configure a different one (eg. diff.exe) manually editing the "/home/user/.plastic/client.conf" or using the Plastic SCM GUI:
<DiffToolData>
<FileType>enTextFile</FileType>
<FileExtensions>*</FileExtensions>
<Tools>
<string>diff.exe #sourcefile #destinationfile</string>
</Tools>
</DiffToolData>
This way, you can run diffs through the command line and based on the output, determine if the files are identical or not.
You can use cm patch command
reference : https://blog.plasticscm.com/2018/11/unified-diff-of-branch.html

How to start vNext TFS 2015 build revision at a specific number

I am using the vNext build system of TFS 2015.
I currently have the my builds versioning in the traditional format. Major.Minor-rev.RevisionNumber. So, if I have a build for Major 1, Minor 12, the build version would look like 1.12-rev.1 when I start. I would like to know if it is possible to have the build version start at a number other than one, say 55. Such that the build version would look like 1.12-rev.55, and then increment by one as usual after that.
Actually, it is possible to effect this in a vNext build without hacking the database.
There are 2 steps.
First, you will need to implement a powershell build step (as the first step of the build) with the following inline script:
#Set the BuildNumberOffset. (Change this to the difference between the TFS build number,
#and the number that your build needs.)
$BuildNumberOffset = 543
#Don't change
$BuildNumberParts = $($env:BUILD_BUILDNUMBER) -split '\.'
$TFSRevision = [int]$BuildNumberParts[$BuildNumberParts.Length-1]
$BuildNumberParts[$BuildNumberParts.Length-1] = ($TFSRevision + $BuildNumberOffset).ToString()
$BuildNumber = [string]::Join(".", $BuildNumberParts)
Write-Host "##vso[build.updatebuildnumber]$BuildNumber"
Second, on the Label format field of the repository tab set the label format to "$(Build.BuildNumber)" instead of "$(Build.DefinitionName)$(rev:.r)". This is important so that your label will be the same as your updated build number.
There is a way to do this. It isn't pretty, but it works.
Assuming you have a build number format of something like $(Major).$(Minor)-rev$(rev:.r)
To do this queue up a build which will get the number 1.12-rev.1. Then go to the TFS database and into a table called tbl_Build. Find that last build you did and change the value in the BuildNumberRevision column to 54.
The next build that fires off will now be 1.12-rev.55
Unfortunately, it's impossible.
Every build definition has a build number format field where you can use some macros to dictate what the resulting build number should look like. In this format we are using $(Rev:.rr) Its start by one.
What is $(Rev:.rr)?
To ensure that every completed build has a unique name. When a build
is completed, if nothing else in the build number has changed, the Rev
integer value is incremented by one.
Source:MSDN
Moreover, if you want to generating a custom build number without increment.
Here is a blog with detailed procedures:Generate custom build numbers in TFS Build vNext
Couldn't we just manually set this in the format for one build i.e:
$(Major).$(Minor)-rev$(rev:.54)
and then afterwards revert back to:
$(Major).$(Minor)-rev$(rev:.r)
Not tried it, but if it works it'll save hacking around in the database.
You can do this easily, but only if you are using a Git repository in conjunction with a tool called GitVersion
It is a wonderful tool that I always use with my git repos. For your use-case: When you have version 1.2.3 and you want to jump to version 1.2.55, you just add a git tag 'v1.2.55' and it will start the versioning from there. GitVersion is a lot more complicated and does a lot more, but that is one of the features. You don't have to mess with special PowerShell scripts or anything, it instead reads your git repo history and git tags overrides the calculated versioning. There is already a TFS/VSTS/Azure Devops extension called GitVersion that works great from the same developer.
The Answer of #Steve Sims works still with TFS 2017 vNext. Thanks a lot!
I had only to do the first step "to add the script as an inline powershell script in my build." Thanks to #PainElemental
With this "Build number format" in the Options-Tab it works:
$(BuildDefinitionName)_1.2.0$(rev:.r)
I didn't label my sources with the build, so I don't checked:
Second, on the Label format field of the repository tab set the label
format to "$(Build.BuildNumber)" instead of
"$(Build.DefinitionName)$(rev:.r)". This is important so that your
label will be the same as your updated build number.
I think, you can edit the Label Format on the "Advanced" GetSources Options. (usually hidden).
This was also very painful for us, migrating from a existing CI system with it's own build numbering, we needed build numbers to increment from a specific value. Hacking databases wasn't allowed in the organisation, offsets seemed a cludge.
In the end, we used an AutoIt script to start and stop builds and delete the build result using the WebUI and left it running. Not nice, but it did the job.
Needs tweaking for screen resolutions and such, timings also perhaps. Use AutoIt Window Info to find the button locations, make sure browser is fullscreen (not windowed) Run it for a few cycles to ensure it robust before setting the loop larger.
#include <AutoItConstants.au3>
;Increment TFS build count (Chrome browser buttons locations). Start from build result page.
For $i = 1 To 15 Step 1
ConsoleWrite ( "Loop " & $i & " of 5" & #CRLF )
Sleep(200)
MouseClick($MOUSE_CLICK_PRIMARY, 1800, 200, 2)
Sleep(500)
MouseClick($MOUSE_CLICK_PRIMARY, 1150, 881, 2)
Sleep(2000)
MouseClick($MOUSE_CLICK_PRIMARY, 1800, 200, 2)
Sleep(500)
MouseClick($MOUSE_CLICK_PRIMARY, 1055, 165, 2)
Sleep(10000)
Next
TFS/Devops is a really immature CI system, and it's not a patch on what we were running. Unfortunately corporate policy said we move to TFS, as nobody ever got fired for buying Microsoft products (but plenty of people should have got fired for buying them/forcing them where they don't belong).

Include branch name in post build event on Team Build

I would like to perform the following steps in the TFS build process:
do post build event that will copy some files from my compiled projects to another predefined directory, I'd like that directory path to include the branch name.
I'd like to be able to refer to the branch name inside my xaml workflow template as well.
The first one is rather simple. When you're using the new TFS 2013 build server and process template, you can simply add a post-build powershell script in the Build Definition Configuration, check in the script and run it during the build.
The second one is dependent on whether you're using TFVC or Git, in the first case, use the VersionControlServer class to query the BranchObjects, then check which one is the root for your working folder. Be aware though, that in TFVC multiple branches can be referenced in one workspace, so there may be multiple answers to this query, depending on which file you use the find the branchroot. A custom CodeActivity would do the trick, similar to this check in a custom checkin policy.
The code will be similar to:
IBuildDetail buildDetail = context.GetExtension<IBuildDetail>();
var workspace = buildDetail.BuildDefinition.Workspace;
var versionControlServer = buildDetail.BuildServer.TeamProjectCollection.GetService<VersionControlServer>();
var branches = versionControlServer.QueryRootBranchObjects(RecursionType.Full);
var referencedBranches = listOfFilePaths.GroupBy(
file =>
branches.SingleOrDefault(
branch => file.ServerItem.StartsWith(branch.Properties.RootItem.Item)
)
).Where(group => group.Key != null);
To get a list of all items in yo workspace, you can use Workspace.GetItems.
In case you're using Git, you have a few options as well. The simplest is to invoke the command line:
git symbolic-ref --short HEAD
or dive into LibGit2Sharp and use it to find the branch name based on the current working folder from a custom activity.
If you want to include this in an MsBuild task, this may well be possible as well. It goes a bit far for this answer to completely outline the steps required, but it's not that hard once you know what to do.
Create a custom MsBuild task that invokes the same snippet of code above, though instead of getting access to the workspace through BuildDetail.BuildDefinition.Workspace, but through the WorkStation class:
Workstation workstation = Workstation.Current;
WorkspaceInfo info = workstation.GetLocalWorkspaceInfo(path);
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(info.ServerUri);
Workspace workspace = info.GetWorkspace(collection);
VersionControlServer versionControlServer = collection.GetService<VersionControlServer>();
Once the task has been created, you can create a custom .targets file that hooks into the MsBuild process by overriding certain variables or copying data when the build is finished. You can hook into multiple Targets and define whether you need to do something before or after them.
You can either <import> these into each of your projects, or you can place it in the ImportAfter or ImportBefore folder of your MsBuild version to make it load globally. You can find the folder here:
C:\Program Files (x86)\MSBuild\{MsBuild Version}\Microsoft.Common.Targets\ImportAfter

TFS Build Template Nested Arguments

Is it possible to nest TFS build template arguments in one another?
Example (Set via build definition ui):
$(ToolsRoot) = E:\BuildTools
$(MSPECTools) = $(ToolsRoot)\MSpec\
Alternatively, is it possible to use environmental variables.
I have tried both, and neither seemed to work.
I need to find a way of setting the build root dynamically, as it differs on our various build servers.
I suppose you have implemented a topology like the this:
So, you need to control the root for each Agent.If you open the TFS Admin Console > Build configuration in Build Machine #1 you 'll see the Build Controller & Agents A.1 & A.2.If you open TFS Admin Console > Build configuration in Build Machine #2 you 'll see Agents A.3, A.4, A.5 & A.6.
For any given build Agent, if you click on "Properties" you 'll see the "Working Directory" entry, which typically is set to something like $(SystemDrive)\Builds\$(BuildAgentId)\. On runtime this is transformed into something like C:\Builds\55.
For any given build, in the build definition area "Workspaces" this "Working Directory" equals the entry $(SourceDir).
Suppose you have set in Agent A.1 a working directory "C:\A.1\Build" & in Agent A.2 "C:\A.2\Build". In order to get what you need, you have to set in the build definition a mapping to $(SourceDir)\Template

Resources