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())); }