public static string ToRealName(this WorkItemType workItem) { switch (workItem) { case WorkItemType.PBI: return("Product%20Backlog%20Item"); case WorkItemType.Task: return("Task"); default: return(workItem.ToString()); } }
public static WorkItem CreateWorkItem(IEnumerable <WorkItem> workItems, int number, WorkItemType type, ApplicationUser creator, ApplicationUser executor, WorkItemState state = WorkItemState.New) { return(new WorkItem { Id = workItems.Count(x => x.Type == type) + 1 + (int)Math.Pow(10, (int)type), Type = type, Name = type.ToString() + number, //Creator = creator, CreatorId = creator.Id, //Executor = executor, ExecutorId = executor?.Id, State = state }); }
public void QuickCreate(WorkItemType type) { var item = new WorkItem(); item.Fields["System.Title"] = "Bug with snapshot"; item.Fields["System.AssignedTo"] = "Ashirvad Sahu"; item.Rev = 1; //create attachment byte[] content = GetBytesFromFile(@"C:\Users\Ashirvad\Desktop\thX4SG17TP.jpg"); var fileRef = _workItemClient.UploadAttachment(null, null, "test.jpg", content).Result; // add attachment to the bug item.Relations.Add(new WorkItemRelation() { Url = fileRef.Url, Rel= "AttachedFile", Attributes = new RelationAttributes() { Comment = "this is a weird bug"} }); item = _workItemClient.CreateWorkItem(VSOConfig.projectName, type.ToString(), item).Result; }
/// <summary> /// Use this to use the predefined work item types. /// </summary> /// <param name="workItemType"></param> /// <param name="title"></param> /// <returns></returns> public static TrackerService.WorkItem CreateWorkItem(WorkItemType workItemType, string title) { return(API.CreateWorkItem(workItemType.ToString(), title)); }
/// <summary> /// Check if a WorkItem of the given Type and with the same hash already exists on VSTS/TFS /// </summary> /// <param name="exceptionHash">The MD5 hash of the exception to report</param> /// <param name="workItemType">The WorkItem Type (Bug or Task)</param> /// <param name="account">Account info for VSTS/TFS</param> /// <returns></returns> public static async Task<WorkItemData> GetExistentWorkItemId(string exceptionHash, WorkItemType workItemType, Account account) { //Pattern: //POST https://{account}.visualstudio.com/defaultcollection/_apis/wit/wiql?api-version={version} var wiqlRequestUrl = $"{account.Url}/{account.CollectionName}/_apis/wit/wiql?{_apiVersion}"; var workItemQueryPOSTData = new WorkItemWIQLRequest() { Query = $"Select [System.Id] From WorkItems Where [System.WorkItemType] = '{workItemType.ToString()}' AND [State] <> 'Done' AND [State] <> 'Removed' " + $"AND [System.TeamProject] = '{account.ProjectName}' AND [Microsoft.VSTS.Build.FoundIn] = '{exceptionHash}'" }; using (var handler = new HttpClientHandler()) { if (!account.IsVSTS) //is TFS, requires NTLM handler.Credentials = new System.Net.NetworkCredential(account.Username, account.Password); using (var client = new HttpClient(handler)) { if (account.IsVSTS) client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //Set alternate credentials string credentials = $"{account.Username}:{account.Password}"; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Converters.StringToAsciiConverter.StringToAscii(credentials))); try { var responseBody = await HttpOperationsHelper.PostAsync(client, wiqlRequestUrl, workItemQueryPOSTData); var responseBodyObj = JsonConvert.DeserializeObject<dynamic>(responseBody); var workItems = (JArray)responseBodyObj.workItems; if (workItems.HasValues) { //Retrieve bug data var id = workItems.First.Value<int>("id"); //Pattern: //GET https://{account}.visualstudio.com/defaultcollection/_apis/wit/WorkItems?id={id}&api-version=1.0 var dataRequestUrl = $"{account.Url}/{account.CollectionName}/_apis/wit/WorkItems?id={id}&{_apiVersion}"; responseBody = await HttpOperationsHelper.GetAsync(client, dataRequestUrl); var workItemData = JsonConvert.DeserializeObject<WorkItemData>(responseBody); //Retrieve bug history //Pattern: //GET https://{account}.visualstudio.com/defaultcollection/_apis/wit/WorkItems/{id}/history var historyRequestUrl = $"{account.Url}/{account.CollectionName}/_apis/wit/WorkItems/{id}/history"; responseBody = await HttpOperationsHelper.GetAsync(client, historyRequestUrl); responseBodyObj = JsonConvert.DeserializeObject<dynamic>(responseBody); var historyItems = (JArray)responseBodyObj.value; if (historyItems.HasValues) workItemData.History = historyItems.ToObject<List<History>>(); return workItemData; } } catch (Exception ex) { int i = 1; } return null; } } }
/// <summary> /// Create a new Work Item with the given values /// </summary> /// <param name="workItemType">The WorkItem Type (Bug or Task)</param> /// <param name="ex">The exception to report</param> /// <param name="account">Account info for VSTS/TFS</param> /// <param name="message">Optional message to be added to the WorkItem</param> /// <param name="tags">Optional tags (list separated by comma) to be added to the WorkItem</param> /// <returns></returns> public static async Task<BugGuardianResponse> CreateNewWorkItem(WorkItemType workItemType, Exception ex, Account account, string message, IEnumerable<string> tags) { //Pattern: //PATCH https://{account}.visualstudio.com/defaultcollection/{project}/_apis/wit/workitems/${workitemtypename}?api-version={version} //See https://www.visualstudio.com/integrate/api/wit/fields for the fields explanation var createRequestUrl = $"{account.Url}/{account.CollectionName}/{account.ProjectName}/_apis/wit/workitems/${workItemType.ToString()}?{_apiVersion}"; var workItemCreatePATCHData = new List<APIRequest>(); //Title: Exception Name workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = TitleField, Value = ExceptionsHelper.BuildExceptionTitle(ex) }); //Tags workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = TagsField, Value = DefaultTags + (tags != null ? string.Join(";", tags) : String.Empty) }); if (workItemType == WorkItemType.Bug) { //BUG //Repro Steps: Stack Trace workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = ReproStepsField, Value = ExceptionsHelper.BuildExceptionString(ex, message) // Include custom message, if any }); //System Info workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = SystemInfoField, Value = SystemInfoHelper.BuildSystemInfoString() }); } else { //TASK //Description: Stack Trace + System info workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = workItemType == WorkItemType.Bug ? ReproStepsField : DescriptionField, Value = $"{ExceptionsHelper.BuildExceptionString(ex, message)}<br /><hr /><br />{SystemInfoHelper.BuildSystemInfoString()}" // Include custom message, if any }); } //FoundIn: Hash of stack trace workItemCreatePATCHData.Add( new WorkItemCreateRequest() { Operation = WITOperationType.add, Path = FoundInField, Value = ExceptionsHelper.BuildExceptionHash(ex) }); using (var handler = new HttpClientHandler()) { if (!account.IsVSTS) //is TFS, requires NTLM handler.Credentials = new System.Net.NetworkCredential(account.Username, account.Password); using (var client = new HttpClient(handler)) { if (account.IsVSTS) client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //Set alternate credentials string credentials = $"{account.Username}:{account.Password}"; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Converters.StringToAsciiConverter.StringToAscii(credentials))); try { var responseBody = await HttpOperationsHelper.PatchAsync(client, createRequestUrl, workItemCreatePATCHData); return new BugGuardianResponse() { Success = true, Response = responseBody }; } catch (Exception internalException) { return new BugGuardianResponse() { Success = false, Response = "An error occured. See the Exception.", Exception = internalException }; } } } }