OK... I think I found a solution to this although it's clunky and truth be told I'm not exactly sure how it works. But here goes - maybe it will point someone in the right direction.
var associatedWorkItems = new List<WorkItem>();
//Passed in from the build workflow (this variable is available under the 'Run On Agent' sequence as 'associatedChangesets'
IList<Changeset> associatedChangesets = context.GetValue(BuildAssociatedChangesets);
if (associatedChangesets.Count > 0)
{
var projectCollection =
new TfsTeamProjectCollection(new Uri("http://localhost:8080/tfs/DefaultCollection"));
VersionControlServer versionControlServer = projectCollection.GetService<VersionControlServer>();
foreach (var changeset in associatedChangesets)
{
//In order to view the individual changes, load the changeset directly from the VCS.
Changeset localChangeset = versionControlServer.GetChangeset(changeset.ChangesetId);
foreach (Change change in localChangeset.Changes)
{
//Find out what was merged in.
ChangesetMerge[] mergedChangesets = versionControlServer.QueryMerges(
null,
null,
change.Item.ServerItem,
new ChangesetVersionSpec(localChangeset.ChangesetId),
new ChangesetVersionSpec(localChangeset.ChangesetId),
null,
RecursionType.Full);
//Extract work item information from changesets being identified as merged.
foreach (var changesetMerge in mergedChangesets)
{
Changeset actualChange = versionControlServer.GetChangeset(changesetMerge.SourceVersion);
foreach (WorkItem item in actualChange.WorkItems)
{
if (!associatedWorkItems.Exists(w => w.Id == item.Id))
{
associatedWorkItems.Add(item);
}
}
}
}
}
}
Don't ask me exactly how QueryMerges
works but all I'm doing here it saying show me what what merged as a part of a changeset checked in. You'll notice that the parameters ChangesetVersionSpec
are the same - this means we're just looking at merges from this one changeset.
You'll get back an array of ChangesetMerge
objects from QueryMerges()
. In the ChangesetMerge
class there is a property called SourceVersion
- this is the ChangesetId
of the original changeset merged in. Once we've got that we can use the VersionControlServer.GetChangeset()
method to load the individual set and extract the WorkItem
. This is then added to a list of WorkItems
which can be manipulated in any way you want (in my case an email). I also used the .Exists()
check to make sure the same WorkItem
doesn't get recorded twice.
Note that even though you have the collection associatedChangesets
from the build workflow, for some reason (for me at least), the Changes[]
property inside associatedChangesets
was never populated (hence loading each individual changeset using the VersionControlServer.GetChangeset()
method as this seems to actually populate all the fields we need.
Like I say, 1. this is a clunky solution (lots of looping - some of which is probably unecessary), 2. I don't fully understand how this works although it seems to produce the required results - I came to this conclusion by doing a lot testing and debugging) and finally - it's the best I could come up with based on the woeful documentation provided by Microsoft.
Hope it helps someone!