IResultFromExtension <WorkItemLink[]> TryConvertWorkItemLinks(string[] workItemIds, string?releaseNotePrefix, string baseUrl) { systemLog.InfoFormat("Getting work items {0} from Jira", string.Join(", ", workItemIds)); var response = jira.Value.GetIssues(workItemIds.ToArray()).GetAwaiter().GetResult(); if (response is IFailureResult failureResult) { return(FailureWithLog(failureResult.Errors)); } var issues = ((ISuccessResult <JiraIssue[]>)response).Value; if (issues.Length == 0) { systemLog.InfoFormat("No work items returned from Jira"); return(ResultFromExtension <WorkItemLink[]> .Success(Array.Empty <WorkItemLink>())); } var issueMap = issues.ToDictionary(x => x.Key, StringComparer.OrdinalIgnoreCase); var workItemsNotFound = workItemIds.Where(x => !issueMap.ContainsKey(x)).ToArray(); if (workItemsNotFound.Length > 0) { systemLog.Warn($"Parsed work item ids {string.Join(", ", workItemsNotFound)} from commit messages but could not locate them in Jira"); } return(ResultFromExtension <WorkItemLink[]> .Success( workItemIds .Where(workItemId => issueMap.ContainsKey(workItemId)) .Select( workItemId => { var issue = issueMap[workItemId]; return new WorkItemLink { Id = issue.Key, Description = GetReleaseNote(issueMap[workItemId], releaseNotePrefix), LinkUrl = baseUrl + "/browse/" + workItemId, Source = JiraConfigurationStore.CommentParser }; }) .Where(i => i != null) // ReSharper disable once RedundantEnumerableCastCall .Cast <WorkItemLink>() // cast back from `WorkItemLink?` type to keep the compiler happy .ToArray())); }
public async Task <IResultFromExtension <JiraIssue[]> > GetIssues(string[] workItemIds) { var workItemQuery = $"id in ({string.Join(", ", workItemIds.Select(x => x.ToUpper()))})"; // WARNING: while the Jira API documentation says that validateQuery values of true/false are deprecated, // that is only valid for Jira Cloud. Jira Server only supports true/false var content = JsonConvert.SerializeObject( new { jql = workItemQuery, fields = new[] { "summary", "comment" }, maxResults = 10000, validateQuery = "false" }); string errorMessage; try { using var response = await httpClient.PostAsync($"{baseUrl}/{baseApiUri}/search", new StringContent (content, Encoding.UTF8, "application/json")); if (response.IsSuccessStatusCode) { var result = await GetResult <JiraSearchResult>(response); if (result == null) { systemLog.Info("Jira Work Item data not found in response body"); return(ResultFromExtension <JiraIssue[]> .Failed("Jira Work Item data not found in response body")); } systemLog.Info($"Retrieved Jira Work Item data for work item ids {string.Join(", ", result.Issues.Select(wi => wi.Key))}"); return(ResultFromExtension <JiraIssue[]> .Success(result.Issues)); } if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden) { systemLog.Info("Authentication failure, check the Jira access token is valid and has permissions to read work items"); return(ResultFromExtension <JiraIssue[]> .Failed("Authentication failure, check the Jira access token is valid and has permissions to read work items")); } var errorResult = await GetResult <JiraErrorResult>(response); errorMessage = $"Failed to retrieve Jira issues from {baseUrl}. Response Code: {response.StatusCode}{(errorResult?.ErrorMessages.Any() == true ? $" (Errors: {string.Join(", ", errorResult.ErrorMessages)})" : "")}"; } catch (HttpRequestException e) { errorMessage = $"Failed to retrieve Jira issues '{string.Join(", ", workItemIds)}' from {baseUrl}. (Reason: {e.Message})"; } catch (TaskCanceledException e) { errorMessage = $"Failed to retrieve Jira issues '{string.Join(", ", workItemIds)}' from {baseUrl}. (Reason: {e.Message})"; } systemLog.Warn(errorMessage); return(ResultFromExtension <JiraIssue[]> .Failed(errorMessage)); }