public async Task <IEnumerable <int> > SearchPullRequestsAsync(string repoUri, string pullRequestBranch, PrStatus status, string keyword = null, string author = null) { return(await _gitClient.SearchPullRequestsAsync(repoUri, pullRequestBranch, status, keyword, author)); }
public async Task SynchronizeInProgressPRAsync() { Subscription subscription = await Context.Subscriptions.FindAsync(SubscriptionId); if (subscription == null) { await Reminders.TryUnregisterReminderAsync(PullRequestCheck); await StateManager.TryRemoveStateAsync(PullRequest); return; } ConditionalValue <InProgressPullRequest> maybePr = await StateManager.TryGetStateAsync <InProgressPullRequest>(PullRequest); if (maybePr.HasValue) { InProgressPullRequest pr = maybePr.Value; long installationId = await Context.GetInstallationId(subscription.TargetRepository); IRemote darc = await DarcFactory.CreateAsync(pr.Url, installationId); MergePolicy policy = subscription.PolicyObject.MergePolicy; PrStatus status = await darc.GetPullRequestStatusAsync(pr.Url); switch (status) { case PrStatus.Open: switch (policy) { case MergePolicy.Never: return; case MergePolicy.BuildSucceeded: case MergePolicy.UnitTestPassed: // for now both of these cases are the same if (await ShouldMergePrAsync(darc, pr.Url, policy)) { await darc.MergePullRequestAsync(pr.Url); goto merged; } return; default: Logger.LogError("Unknown merge policy '{policy}'", policy); return; } case PrStatus.Merged: merged: subscription.LastAppliedBuildId = pr.BuildId; await Context.SaveChangesAsync(); goto case PrStatus.Closed; case PrStatus.Closed: await StateManager.RemoveStateAsync(PullRequest); break; default: Logger.LogError("Unknown pr status '{status}'", status); return; } } await Reminders.TryUnregisterReminderAsync(PullRequestCheck); }
public async Task <IEnumerable <int> > SearchPullRequestsAsync(string repoUri, string pullRequestBranch, PrStatus status, string keyword = null, string author = null) { string repoName = SetApiUriAndGetRepoName(repoUri); StringBuilder query = new StringBuilder(); AzureDevOpsPrStatus prStatus; switch (status) { case PrStatus.Open: prStatus = AzureDevOpsPrStatus.Active; break; case PrStatus.Closed: prStatus = AzureDevOpsPrStatus.Abandoned; break; case PrStatus.Merged: prStatus = AzureDevOpsPrStatus.Completed; break; default: prStatus = AzureDevOpsPrStatus.None; break; } query.Append($"searchCriteria.sourceRefName=refs/heads/{pullRequestBranch}&searchCriteria.status={prStatus.ToString().ToLower()}"); if (!string.IsNullOrEmpty(keyword)) { _logger.LogInformation("A keyword was provided but Azure DevOps doesn't support searching for PRs based on keywords and it won't be used..."); } if (!string.IsNullOrEmpty(author)) { query.Append($"&searchCriteria.creatorId={author}"); } HttpResponseMessage response = await this.ExecuteGitCommand(HttpMethod.Get, $"repositories/{repoName}/pullrequests?{query.ToString()}", _logger); JObject content = JObject.Parse(await response.Content.ReadAsStringAsync()); JArray values = JArray.Parse(content["value"].ToString()); IEnumerable <int> prs = values.Select(r => r["pullRequestId"].ToObject <int>()); return(prs); }
public Task <IEnumerable <int> > SearchPullRequestsAsync(string repoUri, string pullRequestBranch, PrStatus status, string keyword = null, string author = null) { throw new NotImplementedException(); }
public async Task Test( MergePolicy mergePolicy, PrStatus prStatus, bool existingPrHasChecks, bool existingPrPassedChecks) { Channel channel = CreateChannel(); Build oldBuild = CreateOldBuild(); Build build = CreateNewBuild(); var buildChannels = new[] { new BuildChannel { Build = oldBuild, Channel = channel }, new BuildChannel { Build = build, Channel = channel } }; Subscription subscription = CreateSubscription(mergePolicy); subscription.Channel = channel; var repoInstallation = new RepoInstallation { Repository = subscription.TargetRepository, InstallationId = 1 }; Asset asset = build.Assets[0]; await Context.RepoInstallations.AddAsync(repoInstallation); await Context.Subscriptions.AddAsync(subscription); await Context.BuildChannels.AddRangeAsync(buildChannels); await Context.SaveChangesAsync(); var actorId = new ActorId(subscription.Id); var existingPr = "https://repo.pr/existing"; var pr = "https://repo.pr/new"; bool shouldMergeExistingPr = prStatus == PrStatus.Open && mergePolicy == MergePolicy.BuildSucceeded && existingPrHasChecks && existingPrPassedChecks; void SetupCreatePr() { Darc.Setup( d => d.CreatePullRequestAsync( subscription.TargetRepository, subscription.TargetBranch, build.Commit, It.IsAny <IList <AssetData> >(), null, null, null)) .ReturnsAsync( ( string repo, string branch, string commit, IList <AssetData> assets, string baseBranch, string title, string description) => { assets.Should().BeEquivalentTo(new AssetData { Name = asset.Name, Version = asset.Version }); return(pr); }); } void SetupUpdatePr() { Darc.Setup( r => r.UpdatePullRequestAsync( existingPr, build.Commit, subscription.TargetBranch, It.IsAny <IList <AssetData> >(), null, null)) .ReturnsAsync( ( string url, string commit, string branch, IList <AssetData> assets, string title, string description) => { return(url); }); } void SetupExistingPr() { StateManager.Data[SubscriptionActor.PullRequest] = new InProgressPullRequest { BuildId = oldBuild.Id, Url = existingPr }; Darc.Setup(r => r.GetPullRequestStatusAsync(existingPr)).ReturnsAsync(prStatus); if (mergePolicy == MergePolicy.BuildSucceeded && prStatus == PrStatus.Open) { if (existingPrHasChecks) { Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)) .ReturnsAsync( new List <Check> { new Check( existingPrPassedChecks ? CheckStatus.Succeeded : CheckStatus.Failed, "check", "https://check.stuff/1") }); } else { Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>()); } } if (shouldMergeExistingPr) { Darc.Setup(r => r.MergePullRequestAsync(existingPr, null, null, null, null)) .Returns(Task.CompletedTask); } } switch (prStatus) { case PrStatus.None: SetupCreatePr(); break; case PrStatus.Open: SetupExistingPr(); if (shouldMergeExistingPr) { SetupCreatePr(); } else { SetupUpdatePr(); } break; case PrStatus.Merged: SetupExistingPr(); SetupCreatePr(); break; case PrStatus.Closed: SetupExistingPr(); SetupCreatePr(); break; } var actor = ActivatorUtilities.CreateInstance <SubscriptionActor>(Scope.ServiceProvider, actorId); await actor.UpdateAsync(build.Id); if (shouldMergeExistingPr || prStatus == PrStatus.Merged) { subscription.LastAppliedBuildId.Should().Be(oldBuild.Id); } else { subscription.LastAppliedBuildId.Should().Be(null); } StateManager.Data.Should() .BeEquivalentTo( new Dictionary <string, object> { [SubscriptionActor.PullRequest] = new InProgressPullRequest { BuildId = build.Id, Url = prStatus == PrStatus.Open && !shouldMergeExistingPr ? existingPr : pr } }); Reminders.Data.Should() .BeEquivalentTo( new Dictionary <string, MockReminderManager.Reminder> { [SubscriptionActor.PullRequestCheck] = new MockReminderManager.Reminder( SubscriptionActor.PullRequestCheck, Array.Empty <byte>(), TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)) }); }
public async Task SynchronizeInProgressPRAsync( PrStatus prStatus, bool existingPrHasChecks, bool existingPrPassedChecks) { Channel channel = CreateChannel(); Build oldBuild = CreateOldBuild(); Build build = CreateNewBuild(); var buildChannels = new[] { new BuildChannel { Build = oldBuild, Channel = channel }, new BuildChannel { Build = build, Channel = channel } }; Subscription subscription = CreateSubscription(MergePolicy.BuildSucceeded); subscription.Channel = channel; var repoInstallation = new RepoInstallation { Repository = subscription.TargetRepository, InstallationId = 1 }; await Context.RepoInstallations.AddAsync(repoInstallation); await Context.Subscriptions.AddAsync(subscription); await Context.BuildChannels.AddRangeAsync(buildChannels); await Context.SaveChangesAsync(); var existingPr = "https://repo.pr/existing"; var actorId = new ActorId(subscription.Id); StateManager.Data[SubscriptionActor.PullRequest] = new InProgressPullRequest { BuildId = oldBuild.Id, Url = existingPr }; Darc.Setup(d => d.GetPullRequestStatusAsync(existingPr)).ReturnsAsync(prStatus); if (prStatus == PrStatus.Open) { if (existingPrHasChecks) { Darc.Setup(d => d.GetPullRequestChecksAsync(existingPr)) .ReturnsAsync( new List <Check> { new Check( existingPrPassedChecks ? CheckStatus.Succeeded : CheckStatus.Failed, "check", "https://check.stuff/1") }); } else { Darc.Setup(d => d.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>()); } if (existingPrHasChecks && existingPrPassedChecks) { Darc.Setup(d => d.MergePullRequestAsync(existingPr, null, null, null, null)) .Returns(Task.CompletedTask); } } var actor = ActivatorUtilities.CreateInstance <SubscriptionActor>(Scope.ServiceProvider, actorId); await actor.ReceiveReminderAsync( SubscriptionActor.PullRequestCheck, Array.Empty <byte>(), TimeSpan.Zero, TimeSpan.FromMinutes(5)); switch (prStatus) { case PrStatus.Merged: subscription.LastAppliedBuildId.Should().Be(oldBuild.Id); goto case PrStatus.Closed; case PrStatus.Closed: Reminders.Data.Should().BeEmpty(); StateManager.Data.Should().BeEmpty(); break; } }