private bool ProcessPullRequestStatusAndGetShouldWait( GitClient client, PullRequestStatus pullRequestStatus, string pullRequestNumber, string sha) { var pullRequestLink = client.GetPullRequestLink(pullRequestNumber); switch (pullRequestStatus) { case PullRequestStatus.InProcess: Console.WriteLine($"Pull request {pullRequestLink} is in process, waiting."); return(true); case PullRequestStatus.CanBeMerged: client.Merge(pullRequestNumber, sha); Console.WriteLine($"Pull request {pullRequestLink} merged."); return(false); case PullRequestStatus.Merged: // Видимо мы замержили его руками, всё ок return(false); default: throw new InvalidOperationException( $"Can't merge pull request {pullRequestLink} with status {pullRequestStatus}"); } }
public async Task <PullRequestStatus> Status(PullRequest pullRequest, string projectKey) { string requestUrl = UrlBuilder.FormatRestApiUrl(PULL_REQUEST_MERGEABLE, null, projectKey, pullRequest.FromRef.Repository.Slug, pullRequest.Id); PullRequestStatus pr = await _httpWorker.GetAsync <PullRequestStatus>(requestUrl).ConfigureAwait(false); return(pr); }
public void Should_Return_Correct_Value(PullRequestStatus state, AzureDevOpsPullRequestState expectedResult) { // Given // When var result = state.ToAzureDevOpsPullRequestState(); // Then result.ShouldBe(expectedResult); }
public void Should_Throw_If_Invalid_Value_Is_Passed(PullRequestStatus state) { // Given // When var result = Record.Exception(() => state.ToAzureDevOpsPullRequestState()); // Then result.IsArgumentOutOfRangeException("state"); }
public async Task UpdateStatus( string organisation, int pullRequestId, PullRequestStatus status) { var table = await _azureStorage.GetTable(PullRequestsTable); var entity = new DynamicTableEntity(organisation.ToLowerInvariant(), pullRequestId.ToString()) { ETag = "*", Properties = { { "Status", new EntityProperty(status.ToString()) } } }; var mergeOperation = TableOperation.Merge(entity); await table.ExecuteAsync(mergeOperation); }
private DateTime GetPullRequestWatermark(TeamProjectReference project, PullRequestStatus status) { // Default by going back to 1 month if no data has been ingested for this repo DateTime mostRecentDate = DateTime.UtcNow.AddMonths(-1); // Get latest ingested date for pull request from pull request watermark table using VssDbContext context = new VssDbContext(logger, this.sqlConnectionString); VssPullRequestWatermarkEntity latestWatermark = context.VssPullRequestWatermarkEntities.Where(v => v.ProjectId == project.Id && v.PullRequestStatus == status.ToString()).FirstOrDefault(); if (latestWatermark != null) { mostRecentDate = latestWatermark.RowUpdatedDate; } return(mostRecentDate); }
private void UpdatePullRequestWatermark(PullRequestStatus status, TeamProjectReference project) { VssPullRequestWatermarkEntity vssPullRequestWatermarkEntity = new VssPullRequestWatermarkEntity { RowUpdatedDate = Helper.UtcNow, Organization = this.vssClient.OrganizationName, ProjectId = project.Id, ProjectName = project.Name, PullRequestStatus = status.ToString(), }; this.logger.LogInformation("Start ingesting pull request data..."); using VssDbContext context = new VssDbContext(logger, this.sqlConnectionString); int ingestedResult = context.BulkInsertOrUpdate(new List <VssPullRequestWatermarkEntity> { vssPullRequestWatermarkEntity }); this.logger.LogInformation($"Done ingesting {ingestedResult} records"); }
/// <summary> /// Converts a <see cref="PullRequestStatus"/> to a <see cref="TfsPullRequestState"/>. /// </summary> /// <param name="state">State to convert.</param> /// <returns>Converted state.</returns> public static TfsPullRequestState ToTfsPullRequestState(this PullRequestStatus state) { switch (state) { case PullRequestStatus.NotSet: return(TfsPullRequestState.NotSet); case PullRequestStatus.Active: return(TfsPullRequestState.Active); case PullRequestStatus.Abandoned: return(TfsPullRequestState.Abandoned); case PullRequestStatus.Completed: return(TfsPullRequestState.Completed); default: throw new ArgumentOutOfRangeException(nameof(state)); } }
private void RetrieveAndIngestPullRequest(TeamProjectReference project, PullRequestStatus status) { // Query for most recent date from watermark table first DateTime mostRecentDate = this.GetPullRequestWatermark(project, status); // Retrieve pull requests from Azure DevOps IEnumerable <List <GitPullRequest> > pullRequestLists = this.vssClient.GitClient.GetPullRequestsWithRetry(project.Name, mostRecentDate, status); // For each list ingest pull requests retrieved from Azure DevOps foreach (List <GitPullRequest> pullRequestList in pullRequestLists) { this.IngestPullRequests(pullRequestList, project); } // Update watermark once data is successfully ingested so next time it doesn't repeat // Note: If there is an issue before getting to update, data ingestion will have to run again // Note: Since we are going back one month ingesting data again if watermark is unable to update // Note: shouldn't be much of a problem and likely not happen too often this.UpdatePullRequestWatermark(status, project); }
public int UpdatePullRequest(string[] args) { if (args.Length < 4) { Console.Error.WriteLine("usage: {0} <url> Git.UpdatePullRequest <repositoryId> <pullRequestId> <status> <lastMergeSourceCommitId>", Program.ProgramName); return(1); } Guid repositoryId = new Guid(args[0]); int pullRequestId = int.Parse(args[1]); PullRequestStatus status = (PullRequestStatus)Enum.Parse(typeof(PullRequestStatus), args[2]); string lastMergeSourceCommitId = args[3]; Task.Run(async() => { await Client.Git.UpdatePullRequest(repositoryId, pullRequestId, status, lastMergeSourceCommitId); }).Wait(); return(0); }
private static PullRequestState ConvertToTrackerState(PullRequestStatus status) { PullRequestState trackerState = PullRequestState.Open; switch (status) { case PullRequestStatus.NotSet: case PullRequestStatus.Active: trackerState = PullRequestState.Open; break; case PullRequestStatus.Abandoned: case PullRequestStatus.Completed: trackerState = PullRequestState.Closed; break; case PullRequestStatus.All: trackerState = PullRequestState.All; break; } return(trackerState); }
/// <summary> /// Query all pull requests from today until min creation date where min creation date is in the past (inclusive) /// </summary> public IEnumerable <List <GitPullRequest> > GetPullRequestsWithRetry(string projectName, DateTime minDate, PullRequestStatus status) { if (minDate > Helper.UtcNow) { throw new ArgumentException("minDate must be less than today's date, all in UTC"); } List <GitPullRequest> currentSetOfPullRequests = new List <GitPullRequest>(); int skip = 0; int top = 100; GitPullRequestSearchCriteria searchCriteria = new GitPullRequestSearchCriteria { Status = status, }; do { this.logger.LogInformation($"Retrieving {status} pull requests for project {projectName} from {minDate} to {Helper.UtcNow}"); // The last pull request is the where we want to check before stopping if (status == PullRequestStatus.Completed && currentSetOfPullRequests.Count > 0 && currentSetOfPullRequests.Last().ClosedDate < minDate) { this.logger.LogInformation($"No more pull requests found before {minDate}"); break; } else if (status == PullRequestStatus.Active && currentSetOfPullRequests.Count > 0 && currentSetOfPullRequests.Last().CreationDate < minDate) { this.logger.LogInformation($"No more pull requests found before {minDate}"); break; } else if (status == PullRequestStatus.Abandoned && currentSetOfPullRequests.Count > 0 && currentSetOfPullRequests.Last().ClosedDate < minDate) { this.logger.LogInformation($"No more pull requests found before {minDate}"); break; } // Get pull requests from VSTS currentSetOfPullRequests = RetryHelper.SleepAndRetry(this.retryAfter, this.logger, async() => { try { return(await this.GetPullRequestsByProjectAsync(projectName, searchCriteria, skip: skip, top: top)); } catch (VssServiceException ex) { // VSTS service fails to access a repo once in a while. It looks like an exception that we // don't have control over so we'll catch it and move on. // Sample exception: Microsoft.VisualStudio.Services.Common.VssServiceException: TF401019: The Git // repository with name or identifier C50B9441-B35B-4F42-BDA9-9A01386B968F does not exist or you // do not have permissions for the operation you are attempting. if (ex.Message.Contains("TF401019")) { Console.WriteLine($"Warning: Ignore this error due to external VSTS service. {ex}"); } } return(currentSetOfPullRequests); }).Result; // VSO returns a chunk each time, filter out the ones that meet minDate requirements if (status == PullRequestStatus.Completed || status == PullRequestStatus.Abandoned) { currentSetOfPullRequests = currentSetOfPullRequests.Where(v => v.ClosedDate > minDate).ToList(); } else if (status == PullRequestStatus.Active) { currentSetOfPullRequests = currentSetOfPullRequests.Where(v => v.CreationDate > minDate).ToList(); } // Return a batch of requests at a time this.logger.LogInformation($"Retrieved {currentSetOfPullRequests.Count} pull requests"); yield return(currentSetOfPullRequests); // Next set skip = skip + top; }while (currentSetOfPullRequests.Count > 0); }
/// <summary> /// Updates the pull request data, abandoning or completing it. /// </summary> /// <param name="repositoryId">The repository</param> /// <param name="pullRequestId">The pull request to update</param> /// <param name="status">The new status</param> /// <param name="lastMergeSourceCommitId">The last merge source commit ID (to confirm)</param> /// <returns>The updated pull request</returns> public async Task<PullRequest> UpdatePullRequest(Guid repositoryId, int pullRequestId, PullRequestStatus status, string lastMergeSourceCommitId) { Assert.NotNull(lastMergeSourceCommitId, "lastMergeSourceCommitId"); var request = new TfsRestRequest("/_apis/git/repositories/{RepositoryId}/pullRequests/{PullRequestId}", new HttpMethod("PATCH")); request.AddUrlSegment("RepositoryId", repositoryId.ToString()); request.AddUrlSegment("PullRequestId", pullRequestId.ToString()); request.AddBody(new { status = status.ToString().ToLower(), lastMergeSourceCommit = new { commitId = lastMergeSourceCommitId } }); return await Executor.Execute<PullRequest>(request); }
public static Uri PullRequestsUri(PullRequestStatus status, int skip) { return(MakeUri(PullRequests, Settings.Default.SourceTfsRepositoryName, status.ToString(), skip)); }
static async Task Main(string[] args) { var result = new List <PullRequestStatus>(); var client = new GitHubClient(new ProductHeaderValue("NsBoardReport")); client.Credentials = new Credentials(""); var orgName = "dotnet"; var repoName = "standard"; var teamByMember = new Dictionary <string, string>(); var teamNames = new List <string>(); var teams = await client.Organization.Team.GetAll(orgName); foreach (var team in teams) { if (team.Name.StartsWith("nsboard-", StringComparison.OrdinalIgnoreCase)) { teamNames.Add(team.Name); var members = await client.Organization.Team.GetAllMembers(team.Id); foreach (var member in members) { teamByMember.Add(member.Login, team.Name); } } } var pullRequests = await client.PullRequest.GetAllForRepository(orgName, repoName); foreach (var pr in pullRequests) { var issue = await client.Issue.Get(orgName, repoName, pr.Number); if (!HasLabel(issue, "netstandard-api")) { continue; } var teamStatus = new Dictionary <string, PullRequestReviewState>(); var reviews = await client.PullRequest.Review.GetAll(orgName, repoName, pr.Number); foreach (var review in reviews) { if (teamByMember.TryGetValue(review.User.Login, out var teamName)) { teamStatus[teamName] = review.State.Value; } } var teamStatusList = new List <PullRequestReviewState>(teamNames.Count); foreach (var team in teamNames) { if (teamStatus.TryGetValue(team, out var status)) { teamStatusList.Add(status); } else { teamStatusList.Add(PullRequestReviewState.Pending); } } var prStatus = new PullRequestStatus(pr.Number, pr.Title, pr.Url, teamStatusList.ToArray()); result.Add(prStatus); } using (var writer = new StreamWriter(@"P:\results.csv")) { writer.Write("ID;Title;Url;"); foreach (var team in teamNames) { writer.Write(team); writer.Write(";"); } writer.WriteLine(); foreach (var prStatus in result) { writer.Write(prStatus.Number); writer.Write(";"); writer.Write(prStatus.Title); writer.Write(";"); writer.Write(prStatus.Url); writer.Write(";"); foreach (var state in prStatus.BoardStatus) { writer.Write(state); writer.Write(";"); } writer.WriteLine(); } } }
public PullRequestQuery Status(PullRequestStatus status) { return(AddParameter("statusId[]", status.Id)); }