public static IEnumerable <Issue> SearchForGitHubIssues(this GitHubClient s_gitHub, SearchIssuesRequest issueQuery) { List <Issue> totalIssues = new List <Issue>(); int totalPages = -1, currentPage = 0; do { currentPage++; issueQuery.Page = currentPage; SearchIssuesResult searchresults = null; searchresults = s_gitHub.Search.SearchIssues(issueQuery).Result; foreach (var item in searchresults.Items) { totalIssues.Add(item); Colorizer.WriteLine($"Found issue '[Cyan!{item.HtmlUrl}]' in GitHub."); Colorizer.WriteLine($" Labels: '[Green!{string.Join(",", item.Labels.Select(x => x.Name).OrderBy(s => s))}]'."); } // if this is the first call, setup the totalpages stuff if (totalPages == -1) { totalPages = (searchresults.TotalCount / 100) + 1; } } while (totalPages > currentPage); return(totalIssues); }
private async Task <Issue> GetExistingIssueAsync(IGitHubClient client, GrafanaNotification notification) { string id = GetUniqueIdentifier(notification); var searchedLabels = new List <string> { NotificationIdLabel }; searchedLabels.AddRange(_githubOptions.Value.EnvironmentLabels.OrEmpty()); string automationId = string.Format(BodyLabelTextFormat, id); var request = new SearchIssuesRequest(automationId) { Labels = searchedLabels, Order = SortDirection.Descending, SortField = IssueSearchSort.Created, Type = IssueTypeQualifier.Issue, In = new[] { IssueInQualifier.Body }, State = ItemState.Open, }; SearchIssuesResult issues = await client.Search.SearchIssues(request); return(issues.Items.FirstOrDefault()); }
/// <summary> /// Loops through paginated search results to get all issues /// </summary> /// <param name="searchIssuesRequest">A SearchIssuesRequest object representing the GitHub issue search</param> /// <returns>All the issues in the given search</returns> public async Task <List <Issue> > GetAllIssuesFromSearchAsync(SearchIssuesRequest searchIssuesRequest) { SearchIssuesResult searchIssuesResult = await _githubClient.Search.SearchIssues(searchIssuesRequest); List <Issue> issues = new List <Issue>(); issues.AddRange(searchIssuesResult.Items); // Loop through the pagination starting at page 2 since we've already done page 1 above for (int page = 2; issues.Count < searchIssuesResult.TotalCount; page++) { try { searchIssuesRequest.Page = page; searchIssuesResult = await _githubClient.Search.SearchIssues(searchIssuesRequest); issues.AddRange(searchIssuesResult.Items); } catch (Exception e) { Utilities.WriteWarning($"An exception occurred while attempting to paginate through the GitHub issues search API.", Log); Utilities.WriteWarning($"Attempting to access page {page} of search; currently read {issues.Count} of {searchIssuesResult.TotalCount}'", Log); Utilities.WriteWarning($"Exception: ${e.Message}", Log); break; } } return(issues); }
private async Task <Issue> GetCorrespondingIssueAsync(int workItemId) { var searchIssuesRequest = new SearchIssuesRequest(term: TextUtilities.GetFormattedWorkItemId(workItemId)) { Type = IssueTypeQualifier.Issue, In = new[] { IssueInQualifier.Body }, }; searchIssuesRequest.Repos.Add(owner: repoOwner, name: repo); SearchIssuesResult searchIssuesResult = await search.SearchIssues(searchIssuesRequest); int searchResultCount = searchIssuesResult.Items.Count; if (searchResultCount == 0) { throw new WorkItemIdentificationException(string.Format(Resources.NoIssueFoundInGitHubRepoWithWorkItemIdX, workItemId)); } if (searchResultCount > 1) { throw new WorkItemIdentificationException(string.Format(Resources.MultipleIssuesFoundInGitHubRepoWithWorkItemIdX, workItemId)); } return(searchIssuesResult.Items[0]); }
private async Task <Issue> GetExistingIssueAsync(IGitHubClient client, GrafanaNotification notification) { string id = GetUniqueIdentifier(notification); var searchedLabels = new List <string> { NotificationIdLabel }; searchedLabels.AddRange(_githubOptions.Value.EnvironmentLabels.OrEmpty()); string automationId = string.Format(BodyLabelTextFormat, id); var request = new SearchIssuesRequest(automationId) { // We need to manually quote the label here, because of // https://github.com/octokit/octokit.net/issues/2044 Labels = searchedLabels.Select(label => '"' + label + '"'), Order = SortDirection.Descending, SortField = IssueSearchSort.Created, Type = IssueTypeQualifier.Issue, In = new[] { IssueInQualifier.Body }, State = ItemState.Open, }; SearchIssuesResult issues = await client.Search.SearchIssues(request); return(issues.Items.FirstOrDefault()); }
public static IEnumerable <Issue> SearchForGitHubIssues(this GitHubClient s_gitHub, SearchIssuesRequest issueQuery) { List <Issue> totalIssues = new List <Issue>(); int totalPages = -1, currentPage = 0; do { currentPage++; issueQuery.Page = currentPage; SearchIssuesResult searchresults = null; searchresults = s_gitHub.Search.SearchIssues(issueQuery).Result; foreach (Issue item in searchresults.Items) { totalIssues.Add(item); } // if this is the first call, setup the totalpages stuff if (totalPages == -1) { totalPages = (searchresults.TotalCount / 100) + 1; } } while (totalPages > currentPage); return(totalIssues); }
public IReadOnlyList <Issue> GetAllEffortRelatedIssues(string searchTerm, string involvedPerson) { var relevantIssuesRequest = new SearchIssuesRequest(searchTerm) { Involves = involvedPerson, Type = IssueTypeQualifier.Issue, In = new[] { IssueInQualifier.Comment }, }; SearchIssuesResult potentialEffortIssues = searchClient.SearchIssues(relevantIssuesRequest).GetAwaiter().GetResult(); return(potentialEffortIssues.Items); }
private async Task <IReadOnlyList <int> > GetWorkItemIdsByLabel(string label) { var result = new List <int>(); // Search for all issues marked with CodePlex migration labels sorted in ascending fashion by creation date. var searchIssuesRequest = new SearchIssuesRequest { Type = IssueTypeQualifier.Issue, Labels = new[] { label }, Order = SortDirection.Ascending, SortField = IssueSearchSort.Created, Page = 1, }; searchIssuesRequest.Repos.Add(owner: repoOwner, name: repo); int resultCount = 0; SearchIssuesResult searchIssuesResult = await search.SearchIssues(searchIssuesRequest); int totalResultCount = searchIssuesResult.TotalCount; // Extract CodePlex work item ID from issue body, migration state from from assigned labels. while (searchIssuesResult.Items.Count > 0) { foreach (Issue issue in searchIssuesResult.Items) { try { int codePlexWorkItemId = TextUtilities.GetCodePlexWorkItemId(issue.Body); result.Add(codePlexWorkItemId); } catch (Exception ex) { throw new WorkItemIdentificationException( string.Format(Resources.ErrorExtractingCodePlexWorkItemIdFromGitHubIssue, issue.Number, ex.Message), ex); } } resultCount += searchIssuesResult.Items.Count; if (resultCount >= totalResultCount) { break; } searchIssuesRequest.Page += 1; searchIssuesResult = await search.SearchIssues(searchIssuesRequest); } return(result); }
private async Task RequestAsync() { SearchIssuesRequest request = new SearchIssuesRequest(); request.Repos.Add("angular/angular"); request.Created = new DateRange(DateTime.Now.Subtract(TimeSpan.FromDays(7)), SearchQualifierOperator.GreaterThan); request.SortField = IssueSearchSort.Created; request.Order = SortDirection.Descending; searchResults = await client.Search.SearchIssues(request); LastUpdate = DateTime.Now; }
public static async Task <IEnumerable <Models.Objects.Issue> > ListIssuesAsync(this GitHubClient s_gitHub, RepositoryInfo repo, SearchIssuesRequest issueQuery) { TimeLimiter rateLimiter = TimeLimiter.GetFromMaxCountByInterval(1, TimeSpan.FromSeconds(1)); List <Models.Objects.Issue> issuesFound = new List <Models.Objects.Issue>(); int totalPages = -1, currentPage = 0; issueQuery.Repos.Add(repo.Owner, repo.Name); do { currentPage++; issueQuery.Page = currentPage; SearchIssuesResult searchresults = null; // make sure the rate limit is met await rateLimiter; searchresults = await s_gitHub.Search.SearchIssues(issueQuery); Colorizer.WriteLine("Found [Yellow!{0}] issues in [Magenta!{1}].", searchresults.TotalCount, $"{repo.Owner}\\{repo.Name}"); foreach (Issue item in searchresults.Items) { Models.Objects.Issue issueFound = new Models.Objects.Issue(item) { // set the repo on the item RepositoryName = repo.Name, OrganizationName = repo.Owner }; issuesFound.Add(issueFound); } // if this is the first call, setup the totalpages stuff if (totalPages == -1) { totalPages = (searchresults.TotalCount / 100) + 1; } Colorizer.WriteLine("Retrieved [Yellow!{0}]/[Yellow!{1}] issues.", issuesFound.Count, searchresults.TotalCount); } while (totalPages > currentPage); return(issuesFound); }
private static async Task IssueExamples(GitHubClient client) { Issue issue = await client.Issue.Get("octokit", "octokit.net", 1); Console.WriteLine($"Issue.Get: Id={issue.Id}, Title={issue.Title}"); SearchIssuesResult result = await client.Search.SearchIssues( new SearchIssuesRequest("bug") { In = new IssueInQualifier[] { IssueInQualifier.Title }, Repos = new RepositoryCollection { "octokit/octokit.net" } }); Console.WriteLine($"Search.SearchIssues (Simple Search): TotalCount={result.TotalCount}"); await IssueAllFieldsExample(client); }
private async Task <IReadOnlyList <PullRequestEntry> > GetMergedPullRequestsBetween2Refs(string owner, string repository, string fromRef, string toRef, int batchSize) { // Get commits for the from/to range this.logger.LogInformation($"Get commits from {owner}/{repository} in specified range ({fromRef} - {toRef})"); GitHubCommit fromCommit = await this.GitHubClient.Repository.Commit.Get(owner, repository, fromRef).ConfigureAwait(false); GitHubCommit toCommit = await this.GitHubClient.Repository.Commit.Get(owner, repository, toRef).ConfigureAwait(false); // Offset minimum date to ensure commit from last tag is not included. DateTime from = fromCommit.Commit.Committer.Date.UtcDateTime.AddMinutes(1); DateTime to = toCommit.Commit.Committer.Date.UtcDateTime; var fromOffset = new DateTimeOffset(from); var toOffset = new DateTimeOffset(to); // First load the Pull Requests for the date range of our commits this.logger.LogInformation($"Find Pull Requests merged in this date range {from.ToLocalTime()} - {to.ToLocalTime()}"); var pullRequestRequest = new PullRequestRequest { State = ItemStateFilter.Closed, }; // It's faster than using "PullRequest.GetAllForRepository" to do a search issues query and query each PR // individually. Search results max at 100 items so we request in batches. List <PullRequest> mergedPullRequests = new List <PullRequest>(); DateTimeOffset tempFromOffset = fromOffset; while (true) { var prRequest = new SearchIssuesRequest() { Type = IssueTypeQualifier.PullRequest, Closed = new DateRange(tempFromOffset, toOffset), State = ItemState.Closed, Repos = new RepositoryCollection { $"{owner}/{repository}" } }; SearchIssuesResult issues = await this.GitHubClient .Search .SearchIssues(prRequest) .ConfigureAwait(false); if (issues.Items?.Count == 0) { break; } // The returned issues do not actually contain the PR information we require so we grab each one. foreach (Issue issue in issues.Items) { PullRequest pr = await this.GitHubClient .PullRequest .Get(owner, repository, issue.Number) .ConfigureAwait(false); if (pr?.Merged != true) { continue; } // Update the date to get the latest for subsequest queries. if (tempFromOffset < pr.MergedAt.Value) { tempFromOffset = pr.MergedAt.Value; } mergedPullRequests.Add(pr); } if (issues.Items.Count == issues.TotalCount) { break; } } this.logger.LogInformation($"Found {mergedPullRequests.Count} Pull Requests merged in this date range"); this.logger.LogInformation("Getting details for each Pull Request"); // Now load details about the PullRequests using parallel async tasks var result = new List <PullRequestEntry>(); for (int i = 0; i < mergedPullRequests.Count; i += batchSize) { IEnumerable <PullRequest> batchPullRequests = mergedPullRequests .Skip(i) .Take(batchSize); List <Task <PullRequestEntry> > tasks = batchPullRequests.Select(async pull => { // Load the commits. IReadOnlyList <PullRequestCommit> pullRequestCommits = await this.GitHubClient .PullRequest .Commits(owner, repository, pull.Number) .ConfigureAwait(false); // Need to load commits individually to get the full author details. // Using ToList runs the queries in parallel. List <Task <GitHubCommit> > pullRequestFullCommitsTask = pullRequestCommits .Select(async x => await this.GitHubClient .Repository.Commit.Get(owner, repository, x.Sha) .ConfigureAwait(false)) .ToList(); GitHubCommit[] pullRequestFullCommits = await Task.WhenAll(pullRequestFullCommitsTask).ConfigureAwait(false); // Extract the distinct users who have commits in the PR IEnumerable <Author> contributorUsers = pullRequestFullCommits .Where(x => x.Author != null && x.Author.Id != 0) .Select(x => x.Author) .DistinctBy(x => x.Login); // Gather everything into a CachedPullRequest object return(new PullRequestEntry() { PullRequest = pull, Commits = pullRequestCommits, Contributors = contributorUsers.ToList(), Labels = pull.Labels.Select(x => x.Name).ToList() }); }).ToList(); // Collect the results result.AddRange(await Task.WhenAll(tasks).ConfigureAwait(false)); this.logger.LogInformation($"Loaded {result.Count} Pull Requests"); } return(result); }
private static async Task IssueAllFieldsExample(GitHubClient client) { var fromDate = new DateTime(2018, 3, 17); var toDate = new DateTime(2019, 3, 17); int fromNumber = 1; int toNumber = 10; string branch = "master"; string excludedBranch = "other"; string excludedLabel = "wth"; string excludedMilestone = "Nothing Done"; string excludedUser = "******"; string label = "up-for-grabs"; string milestone = "API Cleanup"; string repository = "octokit/octokit.net"; string term = "bug"; string user = "******"; var request = new SearchIssuesRequest(term) { Archived = true, Assignee = user, Author = user, Base = branch, Closed = new DateRange(fromDate, toDate), Commenter = user, Comments = new Range(fromNumber, toNumber), Created = new DateRange(fromDate, SearchQualifierOperator.GreaterThan), Exclusions = new SearchIssuesRequestExclusions { Assignee = excludedUser, Author = excludedUser, Base = excludedBranch, Commenter = excludedUser, Head = branch, Involves = excludedUser, Labels = new string[] { excludedLabel }, Language = Language.Ada, Mentions = excludedUser, Milestone = excludedMilestone, State = ItemState.Open, Status = CommitState.Error }, Head = branch, In = new IssueInQualifier[] { IssueInQualifier.Title }, Involves = user, Is = new IssueIsQualifier[] { IssueIsQualifier.Public }, Labels = new string[] { label }, Language = Language.CSharp, Mentions = user, Merged = new DateRange(toDate, SearchQualifierOperator.LessThan), Milestone = milestone, No = IssueNoMetadataQualifier.Assignee, Order = SortDirection.Descending, Repos = new RepositoryCollection() { repository }, SortField = IssueSearchSort.Created, State = ItemState.Closed, Status = CommitState.Success, Type = IssueTypeQualifier.Issue, Updated = new DateRange(toDate, SearchQualifierOperator.LessThanOrEqualTo), User = user }; SearchIssuesResult result = await client.Search.SearchIssues(request); Console.WriteLine($"Search.SearchIssues (All Fields): TotalCount={result.TotalCount}"); }
public CreateIssueCommentResponse CreateIssueComment(SearchIssuesResult issue, string body) { return(Request(new CreateIssueCommentRequest(_repo, issue.Number, body))); }
public ErrorReportResultUpdated(SearchIssuesResult issue, CreateIssueCommentResponse comment) : base(issue.Number, comment.HtmlUrl) { }