/// <summary> /// Retrieves issues within the specified Jira sprint. /// </summary> /// <returns>List of sprint issues.</returns> private async Task <JiraSeachResults> GetUnclosedSprintIssuesAsync() { JiraSeachResults results = new JiraSeachResults { Results = new List <JiraIssue>() }; int batchSize = JIRA_PAGE_RESULTS_REST_LIMIT; int start = 0; // Loops through batches of the REST results. while (batchSize >= JIRA_PAGE_RESULTS_REST_LIMIT) { // Prepares the resource path of the GET request retrieving the existing issues string resourcePath = String.Format(JQL_FILTER_PATH, SprintId, JIRA_PAGE_RESULTS_REST_LIMIT, start, FIELDS_IDS); string responseContent; try { // Gets the JSON content from the GET request. responseContent = await Connector.GetRequestAsync(resourcePath); } catch (NullReferenceException ex) { Writer.WriteLine("Exception: Retrieving of the JIRA issues failed ({0}).", ex.Message); return(null); } catch (AtlassianGetRequestException ex) { Writer.WriteLine("Exception: Retrieving of the JIRA issues failed ({0}: {1} - {2}).", ex.Message, ex.StatusCode, ex.ReasonPhrase); Writer.WriteLine(ex.ResponseContent); return(null); } // Deserializes the request data into an object. JiraSeachResults batchResults = JsonConvert.DeserializeObject <JiraSeachResults>(responseContent); // Checks whether another result page was found. if (batchResults.Results.Count > 0) { results.Results.AddRange(batchResults.Results); results.Count += batchResults.Results.Count; } start += batchResults.Results.Count; batchSize = batchResults.Results.Count; } // Returns the parent page's child pages. return(results); }
/// <summary> /// Fills in the set Jira sprint issues according to the defined rules. /// </summary> public async Task PrioritizeBacklogAsync() { // Retrieves the issues in the sprint asynchroniously. Task <JiraSeachResults> getBacklogIssues = GetUnclosedSprintIssuesAsync(); // Awaits for retrieving the sprint issues. JiraSeachResults backlogIssues = await getBacklogIssues; if (backlogIssues == null) { Writer.WriteLine($"There are no issues in sprint {SprintId}."); MailSender.SendMail(EmailFrom, EmailTo, EmailFromPassword, "CTC prioritization feels kinda weird", $"The tool hasn't found any issue in the given sprint (ID: {SprintId}). Is this really the sprint you want to prioritize?"); return; } Writer.WriteLine($"There are {backlogIssues.Count} issues to prioritize in sprint {SprintId}."); Writer.WriteLine(); // Gets a non-duplicated list of epics HashSet <string> epicKeys = new HashSet <string>(); foreach (JiraIssue issue in backlogIssues.Results) { if (issue.Fields.Epic != null && issue.Fields.Epic.StartsWith("CTC-")) { epicKeys.Add(issue.Fields.Epic); } } // Retrieves the issues' epics asynchronously. var epicIssues = epicKeys.Select(epic => GetEpic(epic)).ToList(); // Waits for the tasks creating pages and count their successfulness. JiraIssue[] epics = await Task.WhenAll(epicIssues); // Prioritizes the issues asynchronously. var prioritizedIssues = backlogIssues.Results.Select(issue => ProcessIssueAsync(issue, issue.Fields.Epic != null && issue.Fields.Epic.StartsWith("CTC-") ? epics.Where(epic => epic.Key == issue.Fields.Epic).FirstOrDefault() : null)).ToList(); // Waits for the tasks creating pages and count their successfulness. Tuple <int, string>[] prioritizedResults = await Task.WhenAll(prioritizedIssues); /* * // For debugging async-await * List<String> prioritizedIssues = new List<string>(); * foreach (JiraIssue issue in backlogIssues.Results) * { * prioritizedIssues.Add(await ProcessIssueAsync(issue)); * } * string[] prioritizedResults = prioritizedIssues.ToArray(); */ // Write out the final results. int failedIssueNumber = prioritizedResults.Where(x => x.Item1 == 0).Count(); Writer.WriteLine(); Writer.WriteLine("------------------------"); Writer.WriteLine("FINAL RESULTS"); Writer.WriteLine($"Number of all issues: {backlogIssues.Count}"); Writer.WriteLine(); Writer.WriteLine($"Number of updated issues: {prioritizedResults.Where(x => x.Item1 == 1).Count()}"); Writer.WriteLine($"Number of issues that didn't need to be updated: {prioritizedResults.Where(x => x.Item1 == 2).Count()}"); Writer.WriteLine($"Number of issues whose update failed: {failedIssueNumber}"); // If there were any failures, they are listed and a notification email is sent. if (failedIssueNumber > 0) { StringBuilder failedIssues = new StringBuilder(); foreach (Tuple <int, string> t in prioritizedResults) { if (t.Item1 == 0) { failedIssues.AppendLine(t.Item2); failedIssues.AppendLine(); } } Writer.WriteLine(""); Writer.WriteLine("Issues whose update failed:"); Writer.WriteLine(failedIssues.ToString()); MailSender.SendMail(EmailFrom, EmailTo, EmailFromPassword, "CTC prioritization ended with errors", $"Prioritization ended with the following errors in updates: {failedIssues.ToString()}"); } }