/// <summary> /// The add work item for current project. /// </summary> /// <param name="projectName"> /// The project name. /// </param> /// <param name="title"> /// The title. /// </param> /// <param name="workItemTypeString"> /// The work item type string. /// </param> /// <returns> /// The <see cref="int"/>. /// </returns> public static int AddWorkItemForCurrentProject(string projectName, string title, string workItemTypeString, string areapath = "", string linkend = "", int linkid = 0, string DocUrl = "") { WorkItemType workItemType = TfsManager.Instance.ItemsStore.Projects[projectName].WorkItemTypes[workItemTypeString]; var wi = new WorkItem(workItemType) { Title = title }; if (areapath != "" && areapath != projectName) { wi.AreaPath = areapath; } var requiredFields = GetRequiredFieldsForWorkItem(wi); var popup = new RequiredFields { DataContext = requiredFields }; if (requiredFields.Count != 0) { //Thread.CurrentThread.CurrentCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone(); //Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern = "dd.MM.yyyy"; popup.Create(null, Icons.AddNewWorkItem); if (popup.IsCancelled && !popup.IsCreated) { return(0); } } if (!SetRequiredFieldsForWorkIetm(requiredFields, wi)) { return(0); } if (linkend != "" && linkid > 0) { if (TfsManager.Instance.ItemsStore.WorkItemLinkTypes.LinkTypeEnds.Contains(linkend)) { WorkItemLinkTypeEnd linkTypeEnd = TfsManager.Instance.ItemsStore.WorkItemLinkTypes.LinkTypeEnds[linkend]; wi.Links.Add(new RelatedLink(linkTypeEnd, linkid)); } } if (DocUrl != "") { wi.Links.Add(new Hyperlink(DocUrl)); } var _save_errors = wi.Validate(); if (_save_errors.Count > 0) { return(0); } wi.Save(); return(wi.Id); }
protected WorkItemLinkTypeEnd CalculateWorkItemLinkTypeEnd(WorkItemStore workItemStore) { WorkItemLinkTypeEnd linkTypeEnd = null; if (WorkItemRelationType == null) { return(null); } if (WorkItemRelationType is string) { string linkTypeEndName = WorkItemRelationType as string; WorkItemLinkTypeEndCollection linkTypeCollection = workItemStore.WorkItemLinkTypes.LinkTypeEnds; if (!linkTypeCollection.Contains(linkTypeEndName)) { throw new InvalidOperationException(string.Format("Work item link type \"{0}\" doesn't exist, cannot create links to connect to parent work item.", linkTypeEndName)); } linkTypeEnd = workItemStore.WorkItemLinkTypes.LinkTypeEnds[linkTypeEndName]; } else if (WorkItemRelationType is WorkItemLinkTypeEnd) { linkTypeEnd = WorkItemRelationType as WorkItemLinkTypeEnd; } else { throw new PSArgumentException("Work item link type only must be a string or WorkItemLinkTypeEnd object."); } return(linkTypeEnd); }
/// <summary> /// Adds a link to the work items with the given ids. /// </summary> /// <param name="ids">The ids.</param> /// <param name="linkTypeEnd">The link type.</param> /// <returns></returns> private bool AddLinks(int[] ids, WorkItemLinkTypeEnd linkTypeEnd) { // Check for OneToMany violations (e.g. more than one parent) if (ids.Length > 1 && linkTypeEnd.IsForwardLink == false && linkTypeEnd.LinkType.IsOneToMany) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.LinkError_OneToManyViolation, linkTypeEnd.Name)); } // remove all links of this link type and only for ids which are going to add var tfsLinks = (from Link l in WorkItem.Links select l).ToArray(); foreach (Link link in tfsLinks) { var workItemLink = link as RelatedLink; if (workItemLink != null) { if (workItemLink.LinkTypeEnd.Id == linkTypeEnd.Id && ids.Contains(workItemLink.RelatedWorkItemId)) { WorkItem.Links.Remove(link); } } } // add new links for this type foreach (var id in ids) { var relatedLink = new RelatedLink(linkTypeEnd, id); WorkItem.Links.Add(relatedLink); } return(true); }
static void Main(string[] args) { int UserStoryID = 53; int TestCaseID = 54; TfsTeamProjectCollection tfs; tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://ictfs2015:8080/tfs/DefaultCollection")); tfs.Authenticate(); var workItemStore = new WorkItemStore(tfs); WorkItem wit = workItemStore.GetWorkItem(UserStoryID); //Set "Tested By" as the link type var linkTypes = workItemStore.WorkItemLinkTypes; WorkItemLinkType testedBy = linkTypes.FirstOrDefault(lt => lt.ForwardEnd.Name == "Tested By"); WorkItemLinkTypeEnd linkTypeEnd = testedBy.ForwardEnd; //Add the link as related link. try { wit.Links.Add(new RelatedLink(linkTypeEnd, TestCaseID)); wit.Save(); Console.WriteLine(string.Format("Linked TestCase {0} to UserStory {1}", TestCaseID, UserStoryID)); } catch (Exception ex) { // ignore "duplicate link" errors if (!ex.Message.StartsWith("TF26181")) { Console.WriteLine("ex: " + ex.Message); } } Console.ReadLine(); }
protected override void ProcessRecordInEH() { WorkItemStore workItemStore = EnsureWorkItemStore(); WorkItemLinkTypeEnd linkTypeEnd = EnsureWorkItemLinkTypeEnd(workItemStore); WorkItem[] workItems = QueryFromWorkItems(workItemStore).ToArray(); if (workItems.Length == 0) { return; } WorkItem toWorkItem = workItemStore.GetWorkItem(RelatedWorkItemId); if (toWorkItem == null) { throw new ArgumentException(string.Format("Invalid to work item id: {0}.", RelatedWorkItemId)); } foreach (var workItem in workItems) { workItem.Links.Add(new RelatedLink(linkTypeEnd, toWorkItem.Id)); WriteObject(workItem); } workItemStore.BatchSave(workItems, SaveFlags.MergeLinks); }
private static void CreateTestRelation(WorkItemStore store, WorkItem workItem, int relationId) { WorkItemLinkTypeEnd hierarchyLinkType = store.WorkItemLinkTypes.LinkTypeEnds["Tests"]; workItem.Links.Add(new WorkItemLink(hierarchyLinkType, relationId)); //workItem.Save(); }
private void CreateLinks(WorkItem workItem, IList <ILink> links) { workItem.Reset(); foreach (Link link in links) { try { WorkItemLinkTypeEnd workItemLinkTypeEnd = m_workItemLinkTypeEndCollection[link.LinkTypeName]; WorkItemLink workItemLink = new WorkItemLink(workItemLinkTypeEnd, link.EndWorkItemTfsId); workItem.WorkItemLinks.Add(workItemLink); workItem.Save(); link.IsExistInTfs = true; } catch (ValidationException valEx) { link.Message = valEx.Message; workItem.Reset(); } catch (TeamFoundationServerException tfsEx) { link.Message = tfsEx.Message; workItem.Reset(); } } }
private WorkItemLinkTypeEnd EnsureWorkItemLinkTypeEnd(WorkItemStore workItemStore) { WorkItemLinkTypeEnd linkTypeEnd = null; if (WorkItemRelationType == null) { throw new ArgumentException("Work item link type must be specified!"); } else if (WorkItemRelationType is string) { string linkTypeEndName = WorkItemRelationType as string; WorkItemLinkTypeEndCollection linkTypeCollection = workItemStore.WorkItemLinkTypes.LinkTypeEnds; if (!linkTypeCollection.Contains(linkTypeEndName)) { throw new InvalidOperationException(string.Format("Work item link type \"{0}\" doesn't exist, cannot create links to connect to parent work item.", linkTypeEndName)); } linkTypeEnd = workItemStore.WorkItemLinkTypes.LinkTypeEnds[linkTypeEndName]; } else if (WorkItemRelationType is WorkItemLinkTypeEnd) { linkTypeEnd = WorkItemRelationType as WorkItemLinkTypeEnd; } return(linkTypeEnd); }
private WorkItemLinkTypeEnd ParseLinkEnd(WiLink link, WorkItem wi) { var props = link.WiType?.Split('-'); var linkType = wi.Project.Store.WorkItemLinkTypes.SingleOrDefault(lt => lt.ReferenceName == props?[0]); if (linkType == null) { Logger.Log(LogLevel.Error, $"'{link.ToString()}' - link type ({props?[0]}) does not exist in project"); return(null); } WorkItemLinkTypeEnd linkEnd = null; if (linkType.IsDirectional) { if (props?.Length > 1) { linkEnd = props[1] == "Forward" ? linkType.ForwardEnd : linkType.ReverseEnd; } else { Logger.Log(LogLevel.Error, $"'{link.ToString()}' - link direction not provided for '{wi.Id}'."); } } else { linkEnd = linkType.ForwardEnd; } return(linkEnd); }
public void SaveLinkedItem(WorkItem parent, WorkItem item, WorkItemLinkTypeEnd linkType) { item.Save(); // Add link to parent item and save it parent.Links.Add(new RelatedLink(linkType, item.Id)); parent.Save(); }
public void Sprint1Plan() { TfsTeamProjectCollection tpc = TfsConnect(); // Load tasks from config file XmlDocument xmlInput = new XmlDocument(); xmlInput.Load(InputFile); XmlNodeList tasks = xmlInput.SelectNodes("//plan/task"); // Get PBI work items WorkItemStore store = new WorkItemStore(tpc); Project project = store.Projects[TeamProject]; string wiql = "SELECT [System.Id] FROM WorkItems " + "WHERE [System.TeamProject] = '" + TeamProject + "' AND [System.WorkItemType] ='Product Backlog Item'"; WorkItemCollection collection = store.Query(wiql); // Loop through each PBI int count = 0; for (int i = 0; i < collection.Count; i++) { WorkItem PBI = collection[i]; // Loop through each Task foreach (XmlNode task in tasks) { WorkItem wi = new WorkItem(project.WorkItemTypes["task"]); wi.Title = task["title"].InnerText; wi.IterationPath = @"Fabrikam\Release 1\Sprint 1"; wi.Fields["Microsoft.VSTS.Scheduling.RemainingWork"].Value = Convert.ToInt32(task["remainingwork"].InnerText); ArrayList ValidationResult = wi.Validate(); if (ValidationResult.Count > 0) { Microsoft.TeamFoundation.WorkItemTracking.Client.Field badField = (Microsoft.TeamFoundation.WorkItemTracking.Client.Field)ValidationResult[0]; Console.WriteLine(); Console.WriteLine(" Invalid \"{0}\" value \"{1}\" ({2})", badField.Name, badField.Value, badField.Status); return; } Console.Write("."); wi.Save(); // Save link to parent PBI WorkItemLinkTypeEnd childLink = store.WorkItemLinkTypes.LinkTypeEnds["Parent"]; wi.WorkItemLinks.Add(new WorkItemLink(childLink, PBI.Id)); wi.Save(); count++; } } // Done Console.WriteLine(string.Format(" ({0} tasks added)", count)); }
public void WorkItemLinkAlreadyExists(int sourceId, WorkItemLinkTypeEnd destLinkType, int destId) { this.logger.Log( LogLevel.Warning, "Work item link '{1}' from #{0} to #{2} already exists", sourceId, destLinkType, destId); }
public void AddingWorkItemLink(int sourceId, WorkItemLinkTypeEnd destLinkType, int destId) { this.logger.Log( LogLevel.Information, "Adding work item link '{1}' from #{0} to #{2}", sourceId, destLinkType, destId); }
private static void CreateTestedByLink(SharedStepsObject sharedStepsObject, int parentId) { WorkItemStore workItemStore = sharedStepsObject.project.Store; Project teamProject = workItemStore.Projects["Schwans Company"]; var linkTypes = workItemStore.WorkItemLinkTypes; WorkItemLinkType testedBy = linkTypes.FirstOrDefault(lt => lt.ForwardEnd.Name == "Tested By"); WorkItemLinkTypeEnd linkTypeEnd = testedBy.ForwardEnd; sharedStepsObject.testedWorkItem.Links.Add(new RelatedLink(linkTypeEnd, sharedStepsObject.id + 1)); var result = CheckValidationResult(sharedStepsObject.testedWorkItem); }
internal static WorkItemLinkTypeEndWrapper GetInstance() { WorkItemLinkTypeEnd real = default(WorkItemLinkTypeEnd); RealInstanceFactory(ref real); var instance = (WorkItemLinkTypeEndWrapper)WorkItemLinkTypeEndWrapper.GetWrapper(real); InstanceFactory(ref instance); if (instance == null) { Assert.Inconclusive("Could not Create Test Instance"); } return(instance); }
/// <summary> /// Link Work Items in TFS /// </summary> /// <param name="source"> /// The source. /// </param> /// <param name="targetWorkItemId"> /// The target Work Item Id. /// </param> /// <param name="linkTypeEndName"> /// The link Type End Name. /// </param> /// <param name="comments"> /// The comments. /// </param> public void LinkWorkItems(WorkItem source, int targetWorkItemId, string linkTypeEndName, string comments) { WorkItem wItem = tfsManager.GetWorkItem(targetWorkItemId); if (wItem != null) { WorkItemLinkTypeEnd linkTypeEnd = tfsManager.GetAllWorkItemLinksTypes().LinkTypeEnds[linkTypeEndName]; var link = new RelatedLink(linkTypeEnd, targetWorkItemId) { Comment = comments }; source.Links.Add(link); source.Save(); } }
private void AddWorkItemRelationLinkToWorkItemsIfNeeded(WorkItemStore workItemStore, WorkItem[] workItems) { WorkItemLinkTypeEnd linkTypeEnd = CalculateWorkItemLinkTypeEnd(workItemStore); WorkItem relatedWorkItem = workItemStore.GetWorkItem(RelatedWorkItemId); if (relatedWorkItem == null) { throw new PSArgumentException(string.Format("Invalid to work item id: {0}.", RelatedWorkItemId)); } foreach (var workItem in workItems) { workItem.Links.Add(new RelatedLink(linkTypeEnd, relatedWorkItem.Id)); } }
public void Link(int parent, int child, String linkType) { try { Console.WriteLine(String.Format("正在关联{0}--{1}", parent, child)); WorkItemLinkTypeEnd linkTypeEnd = ItemStore.WorkItemLinkTypes.LinkTypeEnds[linkType]; Item = ItemStore.GetWorkItem(parent); Item.Links.Add(new RelatedLink(linkTypeEnd, child)); Item.Save(); } catch { Console.WriteLine(String.Format("{0}--{1}关联已存在", parent, child)); } }
private void Autoassign(WorkItemStore workItemStore, WorkItem workItem) { workItem.Fields[DefectField.AreaPath.FieldName()].Value = Config.UserAreaPath; workItem.Fields[DefectField.AssignedTo.FieldName()].Value = workItemStore.UserIdentityName; string path = GetCurrentIterationPath(workItemStore); workItem.Fields[DefectField.IterationPath.FieldName()].Value = path; if (!workItem.Links.Exist(int.Parse(Config.WorkingFeature))) { // Docs Link to w.i. as parent of... // https://docs.microsoft.com/en-us/vsts/work/customize/reference/link-type-element-reference WorkItemLinkTypeEnd linkType = workItemStore.WorkItemLinkTypes.LinkTypeEnds[DefectLinkType.Child.FieldName()]; workItem.Links.Add(new RelatedLink(linkType, int.Parse(Config.WorkingFeature))); } }
private string CalculateWorkItemLinkTypeEndName() { if (WorkItemRelationType == null) { return(null); } if (WorkItemRelationType is string) { return(WorkItemRelationType as string); } else if (WorkItemRelationType is WorkItemLinkTypeEnd) { WorkItemLinkTypeEnd linkTypeEnd = WorkItemRelationType as WorkItemLinkTypeEnd; return(linkTypeEnd.Name); } throw new PSArgumentException("WorkItemRelationType must be either a string or a WorkItemLinkTypeEnd object."); }
public WorkItem CreateNewLinkedWorkItem(WorkItem parent, WorkItemLinkTypeEnd linkType, WorkItemType workItemType, string title, string comment) { WorkItemType wit = TeamProject.WorkItemTypes[workItemType.Name]; // Create the work item. WorkItem workItem = new WorkItem(wit); workItem.Title = title; workItem.Description = comment; workItem.AreaPath = parent.AreaPath; workItem.IterationPath = parent.IterationPath; // Return the newly created work item return(workItem); }
public bool IsVisibleNewLinkedWorkItem(WorkItem item, WorkItemLinkTypeEnd selectedLinkTypeEnd) { bool isStateVisible = false; foreach (ICustomState customState in ConfigurationViewModel.CustomStates) { if (customState.WorkItemStates.Contains(item.State)) { isStateVisible = true; break; } } bool isLinkTypeEndVisible = ConfigurationViewModel.CurrentLinkType == null || ConfigurationViewModel.CurrentLinkType.ForwardEnd == selectedLinkTypeEnd || ConfigurationViewModel.CurrentLinkType.ReverseEnd == selectedLinkTypeEnd; if (isLinkTypeEndVisible && isStateVisible && ConfigurationViewModel.ChildItems.Contains(item.Type.Name)) { TaskboardService.ApplyConfigurationToLink(item, SelectedWorkItem); return(true); } return(false); }
private void CreateRelatedLink(WorkItemData wiSourceL, RelatedLink item, WorkItemData wiTargetL) { RelatedLink rl = (RelatedLink)item; WorkItemData wiSourceR = null; WorkItemData wiTargetR = null; try { wiSourceR = Engine.Source.WorkItems.GetWorkItem(rl.RelatedWorkItemId.ToString()); } catch (Exception ex) { Log.LogError(ex, " [FIND-FAIL] Adding Link of type {0} where wiSourceL={1}, wiTargetL={2} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiTargetL.Id); return; } try { wiTargetR = GetRightHandSideTargetWi(wiSourceL, wiSourceR, wiTargetL); } catch (Exception ex) { Log.LogError(ex, " [FIND-FAIL] Adding Link of type {0} where wiSourceL={1}, wiTargetL={2} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiTargetL.Id); return; } if (wiTargetR != null) { bool IsExisting = false; try { var exist = ( from Link l in wiTargetL.ToWorkItem().Links where l is RelatedLink && ((RelatedLink)l).RelatedWorkItemId.ToString() == wiTargetR.Id && ((RelatedLink)l).LinkTypeEnd.ImmutableName == item.LinkTypeEnd.ImmutableName select(RelatedLink) l).SingleOrDefault(); IsExisting = (exist != null); } catch (Exception ex) { Log.LogError(ex, " [SKIP] Unable to migrate links where wiSourceL={0}, wiSourceR={1}, wiTargetL={2}", ((wiSourceL != null) ? wiSourceL.Id.ToString() : "NotFound"), ((wiSourceR != null) ? wiSourceR.Id.ToString() : "NotFound"), ((wiTargetL != null) ? wiTargetL.Id.ToString() : "NotFound")); return; } if (!IsExisting && !wiTargetR.ToWorkItem().IsAccessDenied) { if (wiSourceR.Id != wiTargetR.Id) { Log.LogInformation(" [CREATE-START] Adding Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id); var client = (TfsWorkItemMigrationClient)Engine.Target.WorkItems; if (!client.Store.WorkItemLinkTypes.LinkTypeEnds.Contains(rl.LinkTypeEnd.ImmutableName)) { Log.LogError($" [SKIP] Unable to migrate Link because type {rl.LinkTypeEnd.ImmutableName} does not exist in the target project."); return; } WorkItemLinkTypeEnd linkTypeEnd = client.Store.WorkItemLinkTypes.LinkTypeEnds[rl.LinkTypeEnd.ImmutableName]; RelatedLink newRl = new RelatedLink(linkTypeEnd, int.Parse(wiTargetR.Id)); if (linkTypeEnd.ImmutableName == "System.LinkTypes.Hierarchy-Forward") { var potentialParentConflictLink = ( // TF201036: You cannot add a Child link between work items xxx and xxx because a work item can have only one Parent link. from Link l in wiTargetR.ToWorkItem().Links where l is RelatedLink && ((RelatedLink)l).LinkTypeEnd.ImmutableName == "System.LinkTypes.Hierarchy-Reverse" select(RelatedLink) l).SingleOrDefault(); if (potentialParentConflictLink != null) { wiTargetR.ToWorkItem().Links.Remove(potentialParentConflictLink); } linkTypeEnd = ((TfsWorkItemMigrationClient)Engine.Target.WorkItems).Store.WorkItemLinkTypes.LinkTypeEnds["System.LinkTypes.Hierarchy-Reverse"]; RelatedLink newLl = new RelatedLink(linkTypeEnd, int.Parse(wiTargetL.Id)); wiTargetR.ToWorkItem().Links.Add(newLl); wiTargetR.ToWorkItem().Fields["System.ChangedBy"].Value = "Migration"; wiTargetR.SaveToAzureDevOps(); } else { if (linkTypeEnd.ImmutableName == "System.LinkTypes.Hierarchy-Reverse") { var potentialParentConflictLink = ( // TF201065: You can not add a Parent link to this work item because a work item can have only one link of this type. from Link l in wiTargetL.ToWorkItem().Links where l is RelatedLink && ((RelatedLink)l).LinkTypeEnd.ImmutableName == "System.LinkTypes.Hierarchy-Reverse" select(RelatedLink) l).SingleOrDefault(); if (potentialParentConflictLink != null) { wiTargetL.ToWorkItem().Links.Remove(potentialParentConflictLink); } } wiTargetL.ToWorkItem().Links.Add(newRl); if (_save) { wiTargetL.ToWorkItem().Fields["System.ChangedBy"].Value = "Migration"; wiTargetL.SaveToAzureDevOps(); } } Log.LogInformation( " [CREATE-SUCCESS] Adding Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id); } else { Log.LogInformation( " [SKIP] Unable to migrate link where Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} as target WI has not been migrated", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id); } } else { if (IsExisting) { Log.LogInformation(" [SKIP] Already Exists a Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id); } if (wiTargetR.ToWorkItem().IsAccessDenied) { Log.LogInformation(" [AccessDenied] The Target work item is inaccessable to create a Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id); } } } else { Log.LogInformation(" [SKIP] Cant find wiTargetR where wiSourceL={0}, wiSourceR={1}, wiTargetL={2}", wiSourceL.Id, wiSourceR.Id, wiTargetL.Id); } }
/// <summary> /// Creates the work items. /// </summary> /// <param name="baseWorkItemIds">The base work item ids.</param> /// <param name="selectedPlanningTemplate">The selected planning template.</param> /// <returns></returns> /// <exception cref="System.ArgumentException"> /// Invalid WorkItemType /// or /// or /// Invalid WorkItemLinkType /// </exception> public WorkItem[] CreateRelatedWorkItems(int[] baseWorkItemIds, PlanningTemplate selectedPlanningTemplate) { TfsTeamProjectCollection projectCollection = this.GetTeamProjectCollection(); WorkItemStore store = projectCollection.GetService <WorkItemStore>(); Dictionary <WorkItemField, String> workItemFieldMatches = new Dictionary <WorkItemField, string>(ConfigurationManager.CurrentConfiguration.WorkItemFieldMatches.Count); // Load default fields from configuration foreach (WorkItemFieldMatch workItemFieldMatch in ConfigurationManager.CurrentConfiguration.WorkItemFieldMatches) { workItemFieldMatches.Add(workItemFieldMatch.Field, workItemFieldMatch.Value); } List <WorkItem> workItemsToSave = new List <WorkItem>(); foreach (int workItemId in baseWorkItemIds) { WorkItem baseWorkItem = store.GetWorkItem(workItemId); Project project = baseWorkItem.Project; foreach (TaskTemplate taskTemplate in selectedPlanningTemplate.TasksToCreateCollection) { // If Task Quantity is zero, ignore it if (taskTemplate.Quantity <= 0) { continue; } #region Get Work Item Type // Check if the Work Item Type exists if (!project.WorkItemTypes.Contains(taskTemplate.WorkItemType)) { throw new ArgumentException("Invalid WorkItemType"); } WorkItemType wiType = project.WorkItemTypes[taskTemplate.WorkItemType]; #endregion // Predefined fields match foreach (KeyValuePair <WorkItemField, String> fields in workItemFieldMatches) { if (!wiType.FieldDefinitions.Contains(workItemFieldMatches[WorkItemField.AssignedTo])) { throw new ArgumentException(String.Format("WorkItem {0} doesn't contain field with name {1}", taskTemplate.WorkItemType, workItemFieldMatches[WorkItemField.AssignedTo])); } } // Get the relation link type if (!store.WorkItemLinkTypes.Contains(taskTemplate.WorkItemLinkType)) { throw new ArgumentException("Invalid WorkItemLinkType"); } WorkItemLinkTypeEnd relationLinkType = store.WorkItemLinkTypes[taskTemplate.WorkItemLinkType].ReverseEnd; foreach (TaskTemplateInstance taskTemplateInstance in taskTemplate.InstancesCollection) { WorkItem newWorkItem = wiType.NewWorkItem(); newWorkItem.AreaId = baseWorkItem.AreaId; newWorkItem.AreaPath = baseWorkItem.AreaPath; newWorkItem.IterationPath = baseWorkItem.IterationPath; // Copy Tags if (!String.IsNullOrWhiteSpace(baseWorkItem.Tags)) { newWorkItem["Tags"] = baseWorkItem.Tags; } newWorkItem.Title = String.Format("{0}{1}{2}", taskTemplate.Prefix, baseWorkItem.Title, taskTemplate.Sufix); // AssignedTo newWorkItem.UpdateField(workItemFieldMatches[WorkItemField.AssignedTo], taskTemplateInstance.AssignedTo); // Original Estimate newWorkItem.UpdateField(workItemFieldMatches[WorkItemField.OriginalEstimate], taskTemplateInstance.EstimatedTime); // Remaining Work newWorkItem.UpdateField(workItemFieldMatches[WorkItemField.RemainingWork], taskTemplateInstance.EstimatedTime); // Custom Properties if (taskTemplate.CustomProperties != null && taskTemplate.CustomProperties.Count > 0) { foreach (TaskTemplateCustomProperty customProperty in taskTemplate.CustomProperties) { newWorkItem.UpdateField(customProperty.Name, customProperty.Value); } } if (taskTemplate.IsCopyDescriptionEnabled) { newWorkItem.Description = baseWorkItem.Description; if (String.IsNullOrWhiteSpace(newWorkItem.Description)) { // Maybe this is a bug if (baseWorkItem.Fields.Contains("Repro Steps")) { newWorkItem.Description = baseWorkItem.Fields["Repro Steps"].Value.ToString(); } } } newWorkItem.Links.Add(new RelatedLink(relationLinkType, baseWorkItem.Id)); workItemsToSave.Add(newWorkItem); } } } var witems = workItemsToSave.ToArray(); store.BatchSave(witems); return(witems); }
/* Set links between workitems */ private void CreateLinks(List <WorkItem> workItemCollection, WorkItemStore sourceStore) { List <int> linkedWorkItemList = new List <int>(); WorkItemCollection targetWorkItemCollection = GetWorkItemCollection(); foreach (WorkItem workItem in workItemCollection) { WorkItemLinkCollection links = workItem.WorkItemLinks; if (links.Count > 0) { int newWorkItemID = (int)itemMap[workItem.Id]; WorkItem newWorkItem = store.GetWorkItem(newWorkItemID); foreach (WorkItemLink link in links) { try { WorkItem targetItem = sourceStore.GetWorkItem(link.TargetId); if (itemMap.ContainsKey(link.TargetId) && targetItem != null) { int targetWorkItemID = 0; if (itemMap.ContainsKey(link.TargetId)) { targetWorkItemID = (int)itemMap[link.TargetId]; } //if the link is not already created(check if target id is not in list) if (!linkedWorkItemList.Contains(link.TargetId)) { try { WorkItemLinkTypeEnd linkTypeEnd = store.WorkItemLinkTypes.LinkTypeEnds[link.LinkTypeEnd.Name]; newWorkItem.Links.Add(new RelatedLink(linkTypeEnd, targetWorkItemID)); ArrayList array = newWorkItem.Validate(); if (array.Count == 0) { newWorkItem.Save(); } else { logger.Info("WorkItem Validation failed at link setup for work item: " + workItem.Id); } } catch (Exception) { logger.Info(String.Format("Error occured when crearting link for work item: {0} target item: {1}", workItem.Id, link.TargetId)); } } } else { logger.Info("Link is not created for work item: " + workItem.Id + " - target item: " + link.TargetId + " does not exist"); } } catch (Exception) { logger.Info("Link is not created for work item: " + workItem.Id + " - target item: " + link.TargetId + " is not in Source TFS or you do not have permission to access"); } } //add the work item to list if the links are processed linkedWorkItemList.Add(workItem.Id); } } }
static partial void RealInstanceFactory(ref WorkItemLinkTypeEnd real, string callerName) { var linkType = WorkItemLinkTypeWrapper_UnitTests.GetRealInstance(); real = linkType.ForwardEnd; }
public static int ChangeLinkTypes(int[] qdata, WorkItemLinkType fromlink, WorkItemLinkType tolink) { int changedlinks = 0; foreach (int itm in qdata) { if (itm == 0) { continue; } WorkItem wi = Utilities.wistore.GetWorkItem(itm); foreach (var link in wi.Links.OfType <RelatedLink>().Where(x => x.LinkTypeEnd.LinkType.ReferenceName == fromlink.ReferenceName).ToList()) { WorkItemLinkTypeEnd linkTypeEnd = Utilities.wistore.WorkItemLinkTypes.LinkTypeEnds[(link.LinkTypeEnd.IsForwardLink ? tolink.ForwardEnd.Name : tolink.ReverseEnd.Name)]; Utilities.OutputCommandString(string.Format("Updated WorkItemID={0}, OriginalLink={1}, NewLink={2}", wi.Id, link.LinkTypeEnd.Name, linkTypeEnd.Name)); if (wi.IsDirty) { try { wi.Save(); } catch (Exception ex) { var result = MessageBox.Show(ex.Message, "Failed to save dirty Work Item #" + wi.Id, MessageBoxButtons.AbortRetryIgnore); Utilities.OutputCommandString(ex.ToString()); if (result == DialogResult.Abort) { return(changedlinks); } else { continue; } } } try { wi.Links.Add(new RelatedLink(linkTypeEnd, link.RelatedWorkItemId)); wi.Save(); changedlinks++; } catch (Exception ex) { var result = MessageBox.Show(ex.Message, "Failed to add new link to Work Item #" + wi.Id, MessageBoxButtons.AbortRetryIgnore); Utilities.OutputCommandString(ex.ToString()); if (result == DialogResult.Abort) { return(changedlinks); } else { continue; } } try { wi.Links.Remove(link); wi.Save(); } catch (Exception ex) { var result = MessageBox.Show(ex.Message, "Failed to remove original link from Work Item #" + wi.Id, MessageBoxButtons.AbortRetryIgnore); Utilities.OutputCommandString(ex.ToString()); if (result == DialogResult.Abort) { return(changedlinks); } else { continue; } } } } return(changedlinks); }
private void CreateRelatedLink(WorkItem wiSourceL, RelatedLink item, WorkItem wiTargetL, WorkItemStoreContext sourceStore, WorkItemStoreContext targetStore) { RelatedLink rl = (RelatedLink)item; WorkItem wiSourceR = null; WorkItem wiTargetR = null; try { wiSourceR = sourceStore.Store.GetWorkItem(rl.RelatedWorkItemId); } catch (Exception ex) { Trace.WriteLine(string.Format(" [FIND-FAIL] Adding Link of type {0} where wiSourceL={1}, wiTargetL={2} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiTargetL.Id)); Trace.TraceError(ex.ToString()); return; } try { wiTargetR = GetRightHandSideTargitWi(wiSourceL, wiSourceR, wiTargetL, targetStore); } catch (Exception ex) { Trace.WriteLine(string.Format(" [FIND-FAIL] Adding Link of type {0} where wiSourceL={1}, wiTargetL={2} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiTargetL.Id)); Trace.TraceError(ex.ToString()); return; } if (wiTargetR != null) { bool IsExisting = false; try { var exist = ( from Link l in wiTargetL.Links where l is RelatedLink && ((RelatedLink)l).RelatedWorkItemId == wiTargetR.Id && ((RelatedLink)l).LinkTypeEnd.ImmutableName == item.LinkTypeEnd.ImmutableName select(RelatedLink) l).SingleOrDefault(); IsExisting = (exist != null); } catch (Exception ex) { Trace.WriteLine(string.Format(" [SKIP] Unable to migrate links where wiSourceL={0}, wiSourceR={1}, wiTargetL={2}", ((wiSourceL != null) ? wiSourceL.Id.ToString() : "NotFound"), ((wiSourceR != null) ? wiSourceR.Id.ToString() : "NotFound"), ((wiTargetL != null) ? wiTargetL.Id.ToString() : "NotFound"))); Trace.TraceError(ex.ToString()); return; } if (!IsExisting && !wiTargetR.IsAccessDenied) { if (wiSourceR.Id != wiTargetR.Id) { Trace.WriteLine( string.Format(" [CREATE-START] Adding Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id)); WorkItemLinkTypeEnd linkTypeEnd = targetStore.Store.WorkItemLinkTypes.LinkTypeEnds[rl.LinkTypeEnd.ImmutableName]; RelatedLink newRl = new RelatedLink(linkTypeEnd, wiTargetR.Id); wiTargetL.Links.Add(newRl); wiTargetL.Save(); Trace.WriteLine( string.Format( " [CREATE-SUCCESS] Adding Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id)); } else { Trace.WriteLine( string.Format( " [SKIP] Unable to migrate link where Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} as target WI has not been migrated", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id)); } } else { if (IsExisting) { Trace.WriteLine(string.Format(" [SKIP] Already Exists a Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id)); } if (wiTargetR.IsAccessDenied) { Trace.WriteLine(string.Format(" [AccessDenied] The Target work item is inaccessable to create a Link of type {0} where wiSourceL={1}, wiSourceR={2}, wiTargetL={3}, wiTargetR={4} ", rl.LinkTypeEnd.ImmutableName, wiSourceL.Id, wiSourceR.Id, wiTargetL.Id, wiTargetR.Id)); } } } else { Trace.WriteLine(string.Format(" [SKIP] Cant find wiTargetR where wiSourceL={0}, wiSourceR={1}, wiTargetL={2}", wiSourceL.Id, wiSourceR.Id, wiTargetL.Id)); } }
public void CreatePBIs() { TfsTeamProjectCollection tpc = TfsConnect(); int count = 0; Hashtable workItems = new Hashtable(); // Validate that it's the right kind of team project WorkItemStore store = new WorkItemStore(tpc); Project project = store.Projects[TeamProject]; if (!project.WorkItemTypes.Contains("Product Backlog Item")) { Console.WriteLine("This team project was not created using the Visual Studio Scrum process template."); return; } // Load work items XmlDocument xmlInput = new XmlDocument(); xmlInput.Load(InputFile); XmlNodeList items = xmlInput.SelectNodes("//backlog/item"); foreach (XmlNode item in items) { Console.Write("."); string WIT = item["type"].InnerText.Trim().ToLower(); string title = item["title"].InnerText; string state; if (item["state"] == null) { state = "approved"; } else { state = item["state"].InnerText.ToLower(); } WorkItem wi = new WorkItem(project.WorkItemTypes[WIT]); wi.Title = title; if (item["description"] != null) { wi.Description = item["description"].InnerText; } else { wi.Description = title; } if (item["reprosteps"] != null) { wi.Fields["Microsoft.VSTS.TCM.ReproSteps"].Value = item["reprosteps"].InnerText; } if (item["acceptancecriteria"] != null) { wi.Fields["Microsoft.VSTS.Common.AcceptanceCriteria"].Value = item["acceptancecriteria"].InnerText; } wi.AreaPath = TeamProject + item["area"].InnerText; if (item["iteration"] != null) { wi.IterationPath = TeamProject + item["iteration"].InnerText; } wi.Fields["System.AssignedTo"].Value = ProductOwner; if (state == "approved" || state == "active") { if (item["businessvalue"] != null && item["businessvalue"].InnerText != "") { wi.Fields["Microsoft.VSTS.Common.BusinessValue"].Value = item["businessvalue"].InnerText; } if (item["effort"] != null && item["effort"].InnerText != "") { wi.Fields["Microsoft.VSTS.Scheduling.Effort"].Value = item["effort"].InnerText; } if (item["order"] != null && item["order"].InnerText != "") { wi.Fields["Microsoft.VSTS.Common.BacklogPriority"].Value = item["order"].InnerText; } } ArrayList ValidationResult = wi.Validate(); if (ValidationResult.Count > 0) { Microsoft.TeamFoundation.WorkItemTracking.Client.Field badField = (Microsoft.TeamFoundation.WorkItemTracking.Client.Field)ValidationResult[0]; Console.WriteLine(); Console.WriteLine(" Invalid \"{0}\" value \"{1}\" ({2})", badField.Name, badField.Value, badField.Status); return; } wi.Save(); count++; workItems.Add(wi.Id, wi.Title.Trim().ToLower()); // linked items? if (item["parent"] != null) { string parent = item["parent"].InnerText.Trim().ToLower(); int parentId = 0; foreach (DictionaryEntry candidate in workItems) { if (candidate.Value.ToString() == parent) { parentId = Convert.ToInt32(candidate.Key); } } if (parentId > 0) { // lookup child link type WorkItemLinkTypeEnd childLink = store.WorkItemLinkTypes.LinkTypeEnds["Parent"]; wi.WorkItemLinks.Add(new WorkItemLink(childLink, parentId)); wi.Save(); } } if (state == "approved") { wi.State = "Approved"; wi.Save(); } else if (state == "active") { wi.State = "Active"; wi.Save(); } else if (state == "committed") { wi.State = "Committed"; wi.Save(); } else if (state == "done") { wi.State = "Done"; wi.Save(); } } // Done Console.WriteLine(string.Format(" ({0} PBIs created)", count)); }
public void CreateSprint1TestPlan() { TfsTeamProjectCollection tpc = TfsConnect(); ITestManagementTeamProject project = tpc.GetService <ITestManagementService>().GetTeamProject(TeamProject); // Create test plan if none exist // // See http://bit.ly/2dup2XY for why we can't delete Test Plans or Suites at this point in time // // If this routine isn't creating the test plan and/or test suites for you, you'll need to manually // delete the Test Plan and Test Suites using witadmin WorkItemStore store = new WorkItemStore(tpc); string wiql = "SELECT [System.Id] FROM WorkItems " + "WHERE [System.TeamProject] = '" + TeamProject + "' AND [System.WorkItemType] ='Test Plan' AND [System.Title] = 'Sprint 1'"; WorkItemCollection workItems = store.Query(wiql); int testPlanCount = workItems.Count; wiql = "SELECT [System.Id] FROM WorkItems " + "WHERE [System.TeamProject] = '" + TeamProject + "' AND [System.WorkItemType] ='Test Suite'"; int testSuiteCount = store.Query(wiql).Count; ITestPlan testPlan; if (testPlanCount == 0) { testPlan = project.TestPlans.Create(); testPlan.Name = "Sprint 1"; testPlan.Iteration = @"Fabrikam\Release 1\Sprint 1"; testPlan.Save(); Console.WriteLine(" . (1 plan created)"); } else { testPlan = project.TestPlans.Find(workItems[0].Id); Console.WriteLine(" . (plan exists)"); } // Create Test Suites if non exist if (testSuiteCount <= 10) // May create duplicate test suites { Console.Write(" Creating sprint 1 test suites "); // suites int count = 0; IStaticTestSuite staticSuite = project.TestSuites.CreateStatic(); staticSuite.Title = "Automated"; testPlan.RootSuite.Entries.Add(staticSuite); testPlan.Save(); Console.Write("."); count++; staticSuite = project.TestSuites.CreateStatic(); staticSuite.Title = "Regression"; testPlan.RootSuite.Entries.Add(staticSuite); testPlan.Save(); Console.Write("."); count++; // Requirement-based suites // Get PBI work items wiql = "SELECT [System.Id] FROM WorkItems " + "WHERE [System.TeamProject] = '" + TeamProject + "' AND [System.WorkItemType] ='Product Backlog Item'"; workItems = store.Query(wiql); for (int i = 0; i < workItems.Count; i++) { WorkItem pbi = workItems[i]; // Link Test Case to PBI int testCaseID = (int)TestCases[pbi.Title.ToLower()]; WorkItemLinkTypeEnd testedByLink = store.WorkItemLinkTypes.LinkTypeEnds["Tested By"]; pbi.WorkItemLinks.Add(new WorkItemLink(testedByLink, testCaseID)); pbi.Save(); // Create Requirement-based test suite IRequirementTestSuite reqSuite = project.TestSuites.CreateRequirement(pbi); reqSuite.Title = pbi.Title; testPlan.RootSuite.Entries.Add(reqSuite); testPlan.Save(); Console.Write("."); count++; } // Query-based suites IDynamicTestSuite querySuite = project.TestSuites.CreateDynamic(); querySuite.Title = "UI Tests"; querySuite.Query = project.CreateTestQuery(@"SELECT [System.Id],[System.WorkItemType],[System.Title],[Microsoft.VSTS.Common.Priority],[System.AssignedTo],[System.AreaPath] FROM WorkItems WHERE [System.TeamProject] = @project AND [System.WorkItemType] IN GROUP 'Microsoft.TestCaseCategory' AND [System.AreaPath] UNDER 'Fabrikam' AND [System.IterationPath] UNDER 'Fabrikam\Release 1\Sprint 1' AND [System.Title] CONTAINS 'ui'"); testPlan.RootSuite.Entries.Add(querySuite); testPlan.Save(); Console.Write("."); count++; querySuite = project.TestSuites.CreateDynamic(); querySuite.Title = "Bug Existence Tests"; querySuite.Query = project.CreateTestQuery(@"SELECT [System.Id],[System.WorkItemType],[System.Title],[Microsoft.VSTS.Common.Priority],[System.AssignedTo],[System.AreaPath] FROM WorkItems WHERE [System.TeamProject] = @project AND [System.WorkItemType] IN GROUP 'Microsoft.TestCaseCategory' AND [System.AreaPath] UNDER 'Fabrikam' AND [System.IterationPath] UNDER 'Fabrikam\Release 1\Sprint 1' AND [System.Title] CONTAINS 'bug'"); testPlan.RootSuite.Entries.Add(querySuite); testPlan.Save(); Console.Write("."); count++; Console.WriteLine(string.Format(" ({0} suites created)", count)); } }