As the title suggests, I am looking for a command-line utility (like tf.exe) that will show me the work items that are associated with a list of changesets. Please no GUI stuff, and especially no command-line utilities that pop up GUI stuff.
I might be persuaded to use a PowerShell cmdlet, but only under duress. Preferably a good old-fashioned .exe.
With the following snippet you obtain a list of work items that are associated with Changeset '1111'.Depending on how you retrieve your Changeset(s), I suppose this can be adapted accordingly to fit your needs:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace GetWorkItems
{
class Program
{
static void Main(string[] args)
{
TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://myserver:8080/collection"));
VersionControlServer vcs = tpc.GetService(typeof(VersionControlServer)) as VersionControlServer;
Changeset myChangeset = vcs.GetChangeset(1111);
WorkItem[] workItems = myChangeset.WorkItems;
foreach (var workItem in workItems)
{
Console.WriteLine(workItem.Id);
}
}
}
}
You can do this with the tf program.
tf changeset /collection:[url] [changeset#] /noprompt
The /noprompt flag prevents the gui from popping up, but you'll have to write something to parse the output. Here's what the output looks like:
Changeset: 58
User: Alex
Date: Saturday, December 10, 2011 00:11:41
Comment:
Fixed bug # 1
Items:
edit $/netlib/Main/src/NetLib/Samples/Program.cs
Work Items:
ID Type State Assigned To Title
-- ---- -------- ----------- -----------------------
1 Bug Resolved Alex Bug1
Check-in Notes:
Code Reviewer:
Performance Reviewer:
Security Reviewer:
Related
Does anyone know of a way to quickly get at the unit test results of a build in TFS2012?
Currently I have to find the build in visual studio and collapse the various other nodes in the summary as shown in the screenshot below. Then I have to expand each set of results to get at the failures. I just want a list of all failed tests.
I'd be happy to use SQL, SQL Reporting services or even a text file from the build.
Thanks
You can use TFS API to get the test result. Check the code snippet below:
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("http://tfsserver:8080/tfs/collectionname"));
tfs.EnsureAuthenticated();
IBuildServer tfsBuildServer = tfs.GetService<IBuildServer>();
IBuildDefinition buildDef = tfsBuildServer.GetBuildDefinition("teamproject", "project");
var BuildUri = buildDef.LastBuildUri;
ITestManagementService testManagement = (ITestManagementService)tfs.GetService(typeof(ITestManagementService));
ITestManagementTeamProject testManagementTeamProject = testManagement.GetTeamProject("teamproject");
IEnumerable<ITestRun> testRuns = testManagementTeamProject.TestRuns.ByBuild(BuildUri);
foreach (ITestRun testRun in testRuns)
{
foreach (ITestCaseResult result in testRun.QueryResults())
{
Console.WriteLine(string.Format("TestCaseID:{0}", result.TestCaseTitle.ToString()));
Console.WriteLine(string.Format("TestCaseOutcome:{0}", result.Outcome.ToString()));
}
}
I would like produce a list of merge candidates between two branches that includes the changeset comments in a format that I can copy paste in an email.
I know I can do this tf command:
tf merge /candidate $/Branch1 $/Branch2
Which returns something this:
Changeset Author Date
--------- -------------------------------- ----------
22282 developer1 08/09/2012
22354 developer2 08/14/2012
22361 developer2 08/14/2012
22365 developer2 08/14/2012
22381 developer3 08/15/2012
However, I'd like to get the comments as well. The Merge Wizard does something similar when doing a "Selected changesets" merge. Here is an example:
I was thinking that I might be able to combine tf merge /candidate in some way with this command:
tf changeset /noprompt 12345
Which outputs something like this:
Changeset: 12345
User: developer1
Date: Thursday, August 09, 2012 5:20:01 PM
Comment:
Completed various things
Items:
merge, edit $/Branch1/BreakFreely.asmx.vb
merge, edit $/Branch1/FreelyBroken.vb
Work Items:
ID Type State Assigned To Title
----- ------------------- ----- ------------ -----------------------------------------------------------------------------
21406 Sprint Backlog Task Done JoDeveloper1 Fix various things
Check-in Notes:
Code Reviewer:
Complete Lyblind
In short, my desired outcome is something like this:
Changeset Author Date Comment
--------- -------------------------------- ---------- --------------------------
22282 developer1 08/09/2012 Fixed random stuff
22354 developer2 08/14/2012 Fixed specific stuff
What do you think?
In case you 're willing to utilize the TFS-SDK and write your own console app, this should be quite straightforward.The following could serve as a jump-start:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace MergeCandidates
{
class Program
{
static void Main()
{
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFSURI"));
var versionControl = teamProjectCollection.GetService<VersionControlServer>();
var mergeCandidates =
versionControl.GetMergeCandidates(#"$/FromPath",
#"$/ToPath", RecursionType.Full);
foreach (var mergeCandidate in mergeCandidates)
{
Console.WriteLine(string.Format("{0} {1} {2} {3}",
mergeCandidate.Changeset.ChangesetId,
mergeCandidate.Changeset.Owner,
mergeCandidate.Changeset.CreationDate,
mergeCandidate.Changeset.Comment));
}
}
}
}
In TFS 2010, the scenario is to merge the selected changesets via tf command line.
Suppose there were 20 changesets which is to be merged from branch to main folder. I am using the tf command line to merge all the 20 changesets.
If there is a conflict in any of the changeset, email should be triggered to the person who checked-in the changesets.
Is there is anyway to send an email to the person who checkin the changeset?
I think your only resort is to write an application that will take as input the sourceBranch and the targetBranch & will try to programmatically merge the latest of the one to the other. Then it 'll query for conflicts, find the Changeset they belong to and finally send the email to the Changeset owner.
The following bases heavily on the work by Eugene Zakhareyev found here:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace DetectConflicts
{
class Program
{
static void Main()
{
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFS:8080/tfs/{Collection}"));
var versionControl = teamProjectCollection.GetService<VersionControlServer>();
const string sourceBranch = "$/PathToFROMBranch";
const string targetBranch = "$/PathToTOBranch";
Workspace myWorkspace = versionControl.GetWorkspace("WorkspaceName", "{DOMAIN}\\YourName");
GetStatus getStatus = myWorkspace.Merge(sourceBranch,
targetBranch,
null,
null,
LockLevel.None,
RecursionType.Full,
MergeOptions.None);
Conflict[] conflicts = myWorkspace.QueryConflicts(new[] {targetBranch}, true);
foreach (var conflict in conflicts)
{
string owner = versionControl.GetChangeset(conflict.TheirVersion).Owner;
//
//send an email to "owner"
//
...
}
}
}
}
I am currently setting up a Team Foundation Server 2010 and I found a very strange behavior when performing a build:
The situation explained:
We have 2 Branches
Development
Main
All developers check in code into the Development branch only. Once per day, the build manager merges some changesets over to the Main branch. On the Development brach, a continuous build at each check in is running. On the Main branch, once per day (in the night) a build is triggered.
Now suppose that the changesets 1-100 are being merged into the Main brach at 5pm, giving changeset 101 as the merge operation. Some developers check in changesets 102-106 after 5 o'clock into the Development branch. Now at 11pm the daily build is automatically triggered and runs on the Main branch. The last changeset of the Main branch is changeset 101. However, the Build details shows changeset 106:
I could imagine that this behavior is intended, because if you check out changeset 106 on the Main branch, you will in fact get the content of changeset 101. But it would be much more readable if this Build summary showed the correct number.
Question 1: Is there a way of manipulating the ouput of the SourceGetVersion information? Maybe through the Build Process Template?
The second scenario, where the TFS behaves strange is even worse:
When queuing a new build, there is the option of entering the "Get Version" Parameter, as shown in the following picture:
If I now click on "queue", the build is triggered and AGAIN the build detail outputs the changeset 106 although I specifically set it to get changeset 76.
Question 2: Is this a bug? Is there a hotfix or something to fix this? Or is there any option flag that has to be set?
I hope someone knows more about this. I don't really believe that this is a bug, because it is such a vital functionality that other people must have encountered it before.
Thanks for any help!!
Christian
EDIT 1
The folder structure of the Team Project is:
$ProjectName
BuildProcessTemplates
Documentation
SourceCode
Development <-- this is a branch
3rdParty
Source
Main <-- this is a branch
3rdParty
Source
The build only pulls the Main branch and everything below it.
EDIT 2
Here is a picture of the Workspace tab in the build definition:
Finally I found out what is going on:
Basically The changeset that can be seen in my picture 1 is always the latest changeset of the entire Team Project Collection. It is the property "SourceGetVersion" on the object "BuildDetails" of type "IBuildDetails".
I think this is a bug which can be worked around:
If you change the BuildDetails.SourceGetVersion (which is a string) to some other value, then the build summary will show the updated string. Furthermore, it is then saved correctly to the collection database.
What I have done in order to add the correct changeset number is I have created a custom build activity that takes the branch which should be build as input parameter. It outputs the correct changeset. The activity finds out the correct changeset by connecting to the TFS and downloading the History. Then it looks at all the items in the history and outputs the largest changeset number. Here is the code of that activity:
using System.Activities;
using System.Collections;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Build.Client;
namespace SourceGetVersionActivity
{
[BuildActivity(HostEnvironmentOption.All)]
public sealed class SourceGetVersionActivity : CodeActivity<string>
{
// Define an activity input argument of type string
public InArgument<string> Branch { get; set; }
// If your activity returns a value, derive from CodeActivity<TResult>
// and return the value from the Execute method.
protected override string Execute(CodeActivityContext context)
{
// Obtain the runtime value of the Text input argument
string branch = context.GetValue(this.Branch);
ICredentials account = new NetworkCredential("Useranme", "password", "domain");
// connect / authenticate with tfs
TeamFoundationServer tfs = new TeamFoundationServer("http://tfs:8080/tfs/CollectionName", account);
tfs.Authenticate();
// get the version control service
VersionControlServer versionControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
IEnumerable changesets = versionControl.QueryHistory(branch, VersionSpec.Latest, 0, RecursionType.Full,
null, null, null, int.MaxValue, false, false, false, false);
int maxVersion = 0;
foreach (Changeset c in changesets)
{
if (c.ChangesetId > maxVersion)
{
maxVersion = c.ChangesetId;
}
}
return string.Concat('C', maxVersion.ToString());
}
}
}
I call this activity as soon as possible (after the GetBuild activity).
Basically in the BuildProcessTemplate I have added an Argument (string) "Branch" which needs to be filled with a string that points to the top folder that is being build. The custom activity takes that as input and outputs a string which is the correct changeset id. The BuildDetail.SourceGetVersion property will then be overriden by the correct changeset id.
I find it really strange that no-one else seems to have encountered this problem. I could not find any person on the internet with the same problem. Anyway, I hope this answer helps someone else in the future as well.
EDIT - Writing the above code directly in Workflow Foundation:
To get the correct changeset using more compact code and avoiding custom activites, it is also possible to use Workflow Foundation directly. Below is the "code" (doing exactly what is done in above C# code):
(1) The GetTeamProjectCollection activity gets the current collection. I am saving it inside the TeamProjectCollection variable (see bottom of the picture). Important: The variable needs to be defined inside this sequence, if you define it in outer scope, an error will occur: "Unable to serialize type 'Microsoft.TeamFoundation.Client.TfsTeamProjectCollection'. Verify that the type is public and either has a default constructor or an instance descriptor."
(2) Foreach "changeset" in "TeamProjectCollection.GetService(Of VersionControlServer).QueryHistory(Branch, VersionSpec.Latest, 0, RecursionType.Full, Nothing, Nothing, Nothing, Integer.MaxValue, False, False, False).Cast(Of Changeset)()"
The TypeArgument of the Foreach loop is "Microsoft.TeamFoundation.VersionControl.Client.Changeset".
This expression gets the version control object from the collection, calls it "QueryHistory" method which returns an IEnumerable with all changesets.
(3) So we are iterating over all changesets and looking at the ChangesetId. Then saving the maximum ChangesetId to the variable "maxId".
(4) At the end, BuildDetails.SourceGetVersion = "C" + maxId.ToString(). The "C" indicates, that the version is a changeset.
I hope someone finds this piece of "Code" useful!
Christian
We'd like to generate build notes with the following format:
1) Associated ChangeSets:
2) - ChangeSet 45241, by Joe: "Patching fix for foobar"
3) 'Foo.cs' integrated from dev v. 22 to qa v. 7
4) 'Bar.cs' integrated from dev v. 9 to qa v. 3
So far, we have a custom build step that accomplishes 1) and 2). It looks at the information produced by the 'AssociatedChangesetsAndWorkItems' TFS Build Activity. Here is the code:
protected override bool Execute(CodeActivityContext context)
{
StreamWriter sw = new StreamWriter(Path.Combine(BuildNotesPath.Get(context),"build-notes.txt"));
sw.WriteLine("Associated ChangSets:");
foreach (Changeset changeset in BuildAssociatedChangesets.Get(context))
{
sw.WriteLine(string.Format("ChangeSet {0}, by {1}: {2}", changeset.ChangesetId, changeset.Committer, changeset.Comment));
foreach (Change change in changeset.Changes)
{
foreach (MergeSource source in change.MergeSources)
sw.WriteLine(string.Format("\'t{0}': integrated from dev v. {1} to qa v. {2}", source.ServerItem, source.VersionFrom, source.VersionTo));
}
}
sw.Flush();
sw.Dispose();
return true;
}
The problem we're having is that the 'MergeSources' field is always an empty list. What do we have to do to get that field populated?
Take a look at MergeWorkItemsEventHandler.MergeWorkItems and .GetMergeHistory along with the Extensions.PendingMerges method in the TFS 2010 Merge Work Items Event Handler for an example of getting merge sources.
Jakob Enh deserves the credit for this answer. :)