... Or how to automate some actions in TFS 2010.
I’ll say right away that for TFS 2012, the author promises to quickly release an updated version, however, in my opinion, given that the API has not changed or little has changed, then this small project may well start on the new TFS 2012 RC.
Idea
My last articles (
one ,
two ) tell about setting up process templates for TFS, but these templates are separated from each other, in fact, although they are connected in work by relationships like: Child, Parent, Related To and so on. It would be logical to use this connection, to add interactivity to the whole scheme, so that the elements are really connected, so that they really react to each other's state depending on the type of connection and state. So that you can do some accumulative calculations in the metrics, because all this data is available and can be used in automatic mode, reducing the time of routine actions.
You can come up with a lot of scenarios when automating the change of states in related elements would save time. In the standard scheme, when changing the state, it is possible to change the fields belonging to the same work item, but this is not enough.
')
For example, imagine a situation where a user story has a full set of artifacts and is ready for work, specific tasks have been created to implement this story. In this situation, the story is in the
Ready For Development state, and all tasks are in the
Proposed state. The developer takes the task to work, changes its state to
Active . Next, it should change the state of the history to
WIP (Work In Progress). However, this step can be automated! And automation, in turn, leads to greater order and beauty. Those. as soon as the developer took the task to work, the state of the whole history changed
automatically !
Or another example, for example, it was decided to suspend the work on the whole story, as it was suddenly revealed new circumstances of the work of any component. In the work there are several tasks, some have not started yet, some have been completed. When transferring history to the
Hold status, in a good way, all active tasks must be transferred to the
Hold status. Manually doing this would be somewhat tedious - it can also be automated. Or the opposite situation, when one task is put on
Hold , and the whole story is put in a waiting state.
It would also be useful functionality when all tasks are solved, the status of the history automatically switches to the
Resolved state.
It would also be nice to automatically calculate different metric data from the child elements to the parent elements. For example, the remaining work done. Or if there are various fields for evaluating work for testing and development, then you can automatically calculate the value of the field for the overall work.
Implementation
Yes, as you can already guess, for these purposes, you can use the server add-on for TFS 2010 -
TFS Aggregator . Since this add-on works on the server side, the implementation of various rules will occur very quickly. The very first processing, of course, will take 7-10 seconds, since the connection will be established and cached. The rest of the updates are usually faster than you can upgrade your client.
Installation
TFS Aggregator consists of only two files: a task library and an XML configuration file.
After you download the add-on and unzip it, both files must be transferred to the TFS add-ons directory. It is usually located at: C: \ Program Files \ Microsoft Team Foundation Server 2010 \ Application Tier \ Web Services \ bin \ Plugins.
That's all. TFS keeps track of the specified directory, and when the file is copied, the server loads it into memory.
Customization
All settings are contained in the AggregatorItems.xml file. This file contains information about the connection and all the rules that will be applied in the process.
So, consider the main components of the AggregatorItems.xml file:
<? xml version = "1.0" encoding = "utf-8"?>
The title of the file is not worth touching and changing.
<AggregatorItems tfsServerUrl = "http: // tfs2010dev: 8080 / tfs">
AggregatorItems : main element for configuration, root element.
tfsServerUrl: address to the TFS server.
This line sets the address to the TFS server. Instead of
tfs2010 dev you need to write the address to your server. At the same time there is another nuance: the address must lead to any collection of projects. If your project is not in the default collection, which is called
DefaultCollection , then you must specify the name of the collection. For example, in my case, the project is in the MigrationProject collection, so the line will look like:
<AggregatorItems tfsServerUrl = "http: // violet-tape-tfs: 8080 / tfs / MigrationProject">
The name of the collection can be found in the studio when you choose your project. For example:

<AggregatorItem operationType = "Numeric" operation = "Sum" linkType = "Parent" linkLevel = "2" workItemType = "Task">
AggregatorItem : Indicates a rule for aggregation.
operationType : Determines whether the mathematical operation will be performed or whether it will work with text variables. Currently only two values are available: Numeric or String. Numeric is set by default. If the type is Numeric, then the working fields must be of type double or integer.
operation : Specifies which mathematical operation will be applied to the participating fields. Currently, only addition, subtraction, multiplication, division are supported (Sum, Subtract, Multiply, Divide). The default is to add.
linkType : indicates the type of link is whether the target of the aggregation is the parent or the same element. Respectively possible values: Self, Parent. The default will be Self.
linkLevel : If linkType is specified as Parent, then this parameter indicates how many parents go up. The default value is one.
workItemType : The name of the work item (Task, Bug, etc.) to which the rule will be applied.
<TargetItem name = "Total Estimate" />
TargetItem : Indicates the TFS field to be updated. In a single copy can be in the rule.
name : The name of the field in TFS that is intended for the result of the aggregation.
<SourceItem name = "Estimated Dev Work" />
SourceItem : Indicates a field in TFS that will act as a data source. Can be used several times.
name : The name of the field in the TFS from which the data will be taken.
<Conditions>
Conditions : Define conditions that must be met when an aggregation is triggered. Optional field.
<Condition leftField = "Finish Date" operator = "GreaterThan" rightValue = "$ NOW $" />
Condition : Specifies the condition under which the aggregation will be performed.
leftField : The left operand of an expression. The field must be of the type specified in the Target Work Item. It is specified in the workItemType property.
operator : Comparison operator. Two EqualTo, NotEqualTo, operators are defined for strings. Additional operators are defined for numbers: LessThan, GreaterThan, LessThanOrEqualTo, GreaterThanOrEqualTo. EqualTo will be used by default.
rightValue : The value with which the data from the leftFiled will be compared. Either this property or rightField must be defined. As possible macros the values of $ NOW $ and $ NULL $ are defined.
rightField : The field must be of the type specified in the Target Work Item. Compares with the left operand. Will not be used if rightValue is defined.
<Mappings>
Mappings : provides a list of values for string aggregations.
<Mapping targetValue = "Done" inclusive = "And">
Mapping : represents a single element of a possible aggregation. If the condition succeeds, the result of the mapping will be the entry of the value from the targetValue to the TargetItem for the AggregationItem.
targetValue : The value to be used for the replacement.
Inclusive : This parameter is responsible for whether all (And) or any one (Or) value should be met from the SourceValue set in order for the mapping to work.
<SourceValue> Removed </ SourceValue>
SourceValue : possible values that the mapping must satisfy to trigger.
It should be noted here that when mentioning the field name from the work item, it is necessary to write just the short name, and not with the namespace.
This definition is complete, and we can consider specific examples.
Examples
You can start with an example about switching history to WIP. The example is based on a diagram from recent articles.
<AggregatorItem operationType = "String" linkType = "Parent" linkLevel = "1" workItemType = "Task">
<TargetItem name = "State" />
<SourceItem name = "State" />
<Mappings>
<Mapping targetValue = "WIP" inclusive = "Or">
<SourceValue> Active </ SourceValue>
</ Mapping>
</ Mappings>
</ AggregatorItem>
It indicates that the work will be done with strings, with the parent element, the changes will begin at the Task level. The source of data for analyzing the changes will be the State (
SourceItem ) field of the Task item (
workItemType ), the assignment is also the State field (
TargetItem ), but the parent element (
linkType ). In this case, the parents can be either UserStory, or Bug, or some other element. The mapping section describes that the value should change to
WIP (
targetValue ) if the value in the resource has become
Acitve.It is important to understand that the conditions of the state transition will still be checked by internal TFS tools. It will not be possible to go from one state to another if such a transition is not described in the scheme. You cannot move from one state to another unless the conditions for the transition are not met, such as the filled Description field or the Story Points. Those. it does not overdrive and overwrite workflow conditions. The final state should be achievable from the specified, taking into account all the rules.
Honestly, with this particular transition, I reset the value of the AssignedTo field to NETWORK SERVICE, but with other automated transitions this does not happen. Miracles! I hope that the developers will help me in this problem, and I will tell you what was wrong.
Another example is the transition of a story to the Resloved state when all tasks have been completed.
<AggregatorItem operationType = "String" linkType = "Parent" linkLevel = "1" workItemType = "Task">
<TargetItem name = "State" />
<SourceItem name = "State" />
<Mappings>
<Mapping targetValue = "Resolved" inclusive = "And">
<SourceValue> Resolved </ SourceValue>
<SourceValue> Closed </ SourceValue>
<SourceValue> Abandoned </ SourceValue>
</ Mapping>
</ Mappings>
</ AggregatorItem>
It indicates that the work will be done with strings, with the parent element, the changes will begin at the Task level. The source of data for analyzing the changes will be the State (SourceItem) field of the Task item (workItemType), the assignment is also the State field (TargetItem), but the parent element (linkType). The mapping section describes that the value should change to Resolved (targetValue) if the value in the resource has become
either Resolved, Closed,
or Abandoned.
These examples have been earned by me with a bang, and it is very nice that they are, fewer actions will now have to be performed when working with tasks.
I did not check the following group of examples, but there are no particular doubts about their performance.
The following example automatically calculates the total estimated work of developers and testers. The result is recorded in the Estimated Work field in the very element of the Task type.
<AggregatorItem operationType = "Numeric" operation = "Sum" linkType = "Self" workItemType = "Task">
<TargetItem name = "Estimated Work" />
<SourceItem name = "Estimated Dev Work" />
<SourceItem name = "Estimated Test Work" />
</ AggregatorItem>
More examples on the developers page, but they are all in the same spirit.
In the plans
Plans for developers as great, although the project is done in his spare time. So, in the near future plans to make the possibility of aggregation from parent to descendants. In this situation it will be, for example, easier to change the IterationPath and other things that are inherited / copied from the parent when created.
Consider the option of creating the AggregatorItems file editor.
Also in the plans to make it possible to specify more than one item for workItemType.
Make it possible to use the difference of values in conditions, for example Today - 5 days. The same plan includes the possibility of using arbitrary coefficients in formulas. At the moment this is not possible, since the plugin code will search for fields with the name of the coefficient value.
Find a good way to not re-run the conditions from the AggregatorItems file. Suppose some rule worked successfully, which resulted in changes that trigger the rule again. This time the change is no longer happening and everything is fine. This is certainly not fatal, since the result is still true, but unnecessary actions are straining.
If not earned plugin
You have successfully unpacked everything, installed it in the correct directory, edited the settings file as necessary and did not work ...
Well, below is a small checklist to check if everything is actually done correctly:
- You are using TFS 2010.
- Are all elements mentioned in the aggregation rules containing Parent-Child links?
- You have updated the item that requires the rule to be executed. TFS Aggregation is triggered only when the element has been updated and the rule has been able to determine this and all conditions have worked. In the future, perhaps this behavior will change.
- You updated the AggregatorItems.xml file and set the correct address to your server. In this case, do not forget about the name of the collection of projects.
- You copied both the dll and AggregatorItems.xml file into the plug-in directory for TFS.
- You have specified the correct names of the elements, sources, and data sinks.
- Settings file saved in utf-8 encoding. Notepad ++ calls her "utf-8 without BOM". This in general should not be critical, but nonetheless.
In any case, if nothing works at all, make some simple rules file and try again.
If it does not work in this case, it is recommended that you export the settings for the work items and the AggregatorItems.xml file to the developers at
TFSAggregatorIssues@spamex.com .
Total
I really liked the plugin, I set it up for my needs and now I am happy with the way it works. It remains only to receive information from the developers about the change of the field AssignedTo and everything will be very good.