TFS 2010 - merge changesets - tfs

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"
//
...
}
}
}
}

Related

Extract TFS 2012 build unit test results

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()));
}
}

Programmatically delete a TFS branch

I want to programmatically delete a branch in TFS that was create automatically.
There is an existing method "ICommonStructureService.DeleteBranches" that should do the work.
My problem is that the method requires a parameter "string[] nodeUris" that specifies the branch to delete using a "vstfs://... " URI and I just don't know how to get that for my branch.
What I need is something like:
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri <myCollectionUrl>));
var cssService = projectCollection.GetService<ICommonStructureService3>();
var project = cssService.GetProjectFromName(<myProjectName>);
But how can I get the Branch Uri from there?
Meanwhile I found a solution. For deleting the branches I am using
versionControl.Destroy(new ItemSpec(myBranchPath, RecursionType.Full), VersionSpec.Latest, null, DestroyFlags.KeepHistory);
This does exactly what I needed.
versionControl is of type VersionControlServer and must be initialized using the Team Collection
Deleting a branch in version control is like deleting any other version control item. You will need to pend a delete with Workspace.PendDelete on the Item.
The method you reference is wholly unrelated to version control, it's part of the TFS common structure service, which controls the "areas and iterations" that TFS work items can be assigned to.
In short, there's no way to perform any sort of version control operations against the common structure service. You delete a branch by creating a Workspace against a VersionControlServer, pending a delete and then checking in your pending changes.
I agree to Edward Thomson about using Destroy command. So I followed on advice from him and came up with following,
public void DeleteBranch(string path)
{
var vcs = GetVersionControlServer();
var itemSpec = new ItemSpec(path, RecursionType.Full);
var itemSpecs = new[] {itemSpec};
var workSpace = GetOrCreateWorkSpace(vcs);
try
{
workSpace.Map(path, #"c:\Temp\tfs");
var request = new GetRequest(itemSpec, VersionSpec.Latest);
workSpace.Get(request, GetOptions.GetAll | GetOptions.Overwrite);
workSpace.PendDelete(path, RecursionType.Full);
var pendingchanges = workSpace.GetPendingChanges(itemSpecs);
workSpace.CheckIn(pendingchanges, "Deleting The Branch");
}
finally
{
if (workSpace != null)
{
workSpace.Delete();
}
}
}
If there is a neat way to do the same than I am looking forward to it. This is bit slow as it does too many things,
Creates Temp Workspace
Gets All changes to that
Performs Delete to whole change set
checks it in
Cleans up the workspace

How to merge TFS change sets programmatically?

I know how to merge a change set in TFS 2010 using the command line command "tf merge".
Is there a way I can do this in C# with code. I want to merge specific change sets only (cherry pick), one at a time.
This is roughly how you would do it if you were working with the 2010 or 2012 TFS object models. Let me know if you have any questions.
// Get a reference to yourTeam Foundation Server.
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://<yourserver>:8080/tfs/<yourcollection> "));
// Get a reference to Version Control.
VersionControlServer versionControl = tpc.GetService<VersionControlServer>();
Workspace workspace = versionControl.GetWorkspace("<local path to your workspace>");
string sourceBranch = "$/<sourceBranch>";
string targetBranch = "$/<targetBranch>";
VersionSpec changesetToMerge = new ChangesetVersionSpec(<your changeset here>);
// actually pend the merge
workspace.Merge(sourceBranch, targetBranch, changesetToMerge, changesetToMerge);
// check in the merge
workspace.CheckIn(workspace.GetPendingChanges(), "your comment");

Find changesets with associated work items using a command-line utility

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:

How can I copy a TFS 2010 Build Definition?

Is there any way to copy a build definition? I work in a mainline source control methodology which utilizes many different branches that live for very short periods (ie. a few days to a week). I'd really like to copy a build template and just change the solution to build. Is there any way to do this?
You can download the new TFS 2010 power tools. It has the option to clone a build definition.
See http://msmvps.com/blogs/molausson/archive/2010/10/21/clone-a-build-definition.aspx for an example
Note: Be aware that the Clone only works when you did NOT pop out the Build window.
You can write an add-in to do it. Here's the code to copy an existing build definition:
static IBuildDefinition CloneBuildDefinition(IBuildDefinition buildDefinition)
{
var buildDefinitionClone = buildDefinition.BuildServer.CreateBuildDefinition(
buildDefinition.TeamProject);
buildDefinitionClone.BuildController = buildDefinition.BuildController;
buildDefinitionClone.ContinuousIntegrationType = buildDefinition.ContinuousIntegrationType;
buildDefinitionClone.ContinuousIntegrationQuietPeriod = buildDefinition.ContinuousIntegrationQuietPeriod;
buildDefinitionClone.DefaultDropLocation = buildDefinition.DefaultDropLocation;
buildDefinitionClone.Description = buildDefinition.Description;
buildDefinitionClone.Enabled = buildDefinition.Enabled;
buildDefinitionClone.Name = String.Format("Copy of {0}", buildDefinition.Name);
buildDefinitionClone.Process = buildDefinition.Process;
buildDefinitionClone.ProcessParameters = buildDefinition.ProcessParameters;
foreach (var schedule in buildDefinition.Schedules)
{
var newSchedule = buildDefinitionClone.AddSchedule();
newSchedule.DaysToBuild = schedule.DaysToBuild;
newSchedule.StartTime = schedule.StartTime;
newSchedule.TimeZone = schedule.TimeZone;
}
foreach (var mapping in buildDefinition.Workspace.Mappings)
{
buildDefinitionClone.Workspace.AddMapping(
mapping.ServerItem, mapping.LocalItem, mapping.MappingType, mapping.Depth);
}
buildDefinitionClone.RetentionPolicyList.Clear();
foreach (var policy in buildDefinition.RetentionPolicyList)
{
buildDefinitionClone.AddRetentionPolicy(
policy.BuildReason, policy.BuildStatus, policy.NumberToKeep, policy.DeleteOptions);
}
return buildDefinitionClone;
}
The following tool (VS Addin) will satisfy your requirement>
Community TFS Build Manager
http://visualstudiogallery.msdn.microsoft.com/16bafc63-0f20-4cc3-8b67-4e25d150102c
I just had a need to copy build definitions, and found Jim's answer above to be helpful. However, being new to the TFS API, I needed help connecting to the server and getting the existing build definition through code. These two links helped fill in the gaps:
http://msdn.microsoft.com/en-us/library/bb286958.aspx
http://geekswithblogs.net/jakob/archive/2010/04/26/creating-a-build-definition-using-the-tfs-2010-api.aspx
You can right click the build definition and select 'clone build definition' to copy the definition file. You can then edit it from there.
Here is the soltion if you want to move the Build definition from one Team Project to other Team project.
public void MoveBuild(string fromTeamProject, string toTeamProject, string buildName, string newBuildName)
{
var _server = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new
Uri("http://Mytfs:8080/defaultcollection"));
IBuildServer _buildServer = _server.GetService<IBuildServer>();
var buildDetails = _buildServer.QueryBuildDefinitions(fromTeamProject);
foreach (var fromBuild in buildDetails)
{
if (fromBuild.Name != buildName) continue;
var newBuildDefinition = _buildServer.CreateBuildDefinition(toTeamProject);
newBuildDefinition.Name = !string.IsNullOrEmpty(newBuildName) ? newBuildName : fromBuild.Name;
newBuildDefinition.BuildController = fromBuild.BuildController;
// This finds the template to use
foreach (var mapping in fromBuild.Workspace.Mappings)
{
newBuildDefinition.Workspace.AddMapping(
mapping.ServerItem, mapping.LocalItem, mapping.MappingType, mapping.Depth);
}
newBuildDefinition.DefaultDropLocation = fromBuild.DefaultDropLocation;
newBuildDefinition.Description = fromBuild.Description;
// buildDefinition.Workspace.AddMapping(build.Workspace.);
newBuildDefinition.Process = _buildServer.QueryProcessTemplates(fromBuild)[2];
newBuildDefinition.ProcessParameters = fromBuild.ProcessParameters;
newBuildDefinition.Enabled = false;
newBuildDefinition.Save();
}//end of for each loop
}
From your message it is not clear which template is your build definition using (default, upgrade or lab management). If I understand correctly you would like to easily set up a build definition which builds the same solution but from a different branch.
One thing that you could try instead of copying the definition is to edit it. When the branch dies, rename the build definition (might help with reporting), change the workspace mapping of the build and you should be done.
Thanks, Ladislau

Resources