private async Task SynchronizeInstallationRepositoriesAsync(long installationId) { string token = await GitHubTokenProvider.GetTokenForInstallation(installationId); IReadOnlyList <Repository> gitHubRepos = await GetAllInstallationRepositories(token); HashSet <string> toRemove = (await Context.RepoInstallations.Where(ri => ri.InstallationId == installationId) .Select(ri => ri.Repository) .ToListAsync()) .ToHashSet(StringComparer.OrdinalIgnoreCase); foreach (Repository repo in gitHubRepos) { toRemove.Remove(repo.HtmlUrl); RepoInstallation existing = await Context.RepoInstallations.FindAsync(repo.HtmlUrl); if (existing == null) { Context.RepoInstallations.Add( new RepoInstallation { Repository = repo.HtmlUrl, InstallationId = installationId }); } else { existing.InstallationId = installationId; } } foreach (string repository in toRemove) { Context.RepoInstallations.Remove(await Context.RepoInstallations.FindAsync(repository)); } await Context.SaveChangesAsync(); }
public async Task Test( bool mergeOnPassedChecks, PrStatus prStatus, bool existingPrHasChecks, bool existingPrPassedChecks) { const string prCommentId = "5"; 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(mergeOnPassedChecks ? new MergePolicyDefinition { Name = "AllChecksSuccessful" } : null); 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 && mergeOnPassedChecks && existingPrHasChecks && existingPrPassedChecks; void SetupCreatePr() { Darc.Setup( d => d.CreatePullRequestAsync( subscription.TargetRepository, subscription.TargetBranch, build.Commit, It.IsAny <IList <AssetData> >(), null, It.IsAny <string>(), It.IsAny <string>())) .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> >(), It.IsAny <string>(), It.IsAny <string>())) .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 (mergeOnPassedChecks && prStatus == PrStatus.Open) { if (existingPrHasChecks) { Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)) .ReturnsAsync( new List <Check> { new Check( existingPrPassedChecks ? CheckState.Success : CheckState.Failure, "check", "https://check.stuff/1") }); } else { Darc.Setup(r => r.GetPullRequestChecksAsync(existingPr)).ReturnsAsync(new List <Check>()); } } if (prStatus == PrStatus.Open) { Darc.Setup(d => d.CreatePullRequestCommentAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(prCommentId); } if (shouldMergeExistingPr) { Darc.Setup(r => r.MergePullRequestAsync(existingPr, 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, StatusCommentId = prStatus == PrStatus.Open && !shouldMergeExistingPr ? prCommentId : null } }); 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(new MergePolicyDefinition { Name = "AllChecksSuccessful", }); 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 ? CheckState.Success : CheckState.Failure, "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)) .Returns(Task.CompletedTask); } Darc.Setup(d => d.CreatePullRequestCommentAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync("5"); } 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; } }
public async Task NeedsUpdateSubscription() { var channel = new Channel { Name = "channel", Classification = "class" }; var oldBuild = new Build { Branch = "source.branch", Repository = "source.repo", BuildNumber = "old.build.number", Commit = "oldSha", DateProduced = DateTimeOffset.UtcNow.AddDays(-2) }; var location = "https://source.feed/index.json"; var build = new Build { Branch = "source.branch", Repository = "source.repo", BuildNumber = "build.number", Commit = "sha", DateProduced = DateTimeOffset.UtcNow, Assets = new List <Asset> { new Asset { Name = "source.asset", Version = "1.0.1", Locations = new List <AssetLocation> { new AssetLocation { Location = location, Type = LocationType.NugetFeed } } } } }; var buildChannel = new BuildChannel { Build = build, Channel = channel }; var subscription = new Subscription { Channel = channel, SourceRepository = "source.repo", TargetRepository = "target.repo", TargetBranch = "target.branch", PolicyObject = new SubscriptionPolicy { MergePolicy = MergePolicy.Never, UpdateFrequency = UpdateFrequency.EveryDay }, LastAppliedBuild = oldBuild }; var repoInstallation = new RepoInstallation { Repository = "target.repo", InstallationId = 1 }; await Context.RepoInstallations.AddAsync(repoInstallation); await Context.Subscriptions.AddAsync(subscription); await Context.BuildChannels.AddAsync(buildChannel); await Context.SaveChangesAsync(); SubscriptionActor.Setup(a => a.UpdateAsync(build.Id)).Returns(Task.CompletedTask); var updater = ActivatorUtilities.CreateInstance <DependencyUpdater>(Scope.ServiceProvider); await updater.CheckSubscriptionsAsync(CancellationToken.None); }
public async Task EveryBuildSubscriptionNotEnabled() { var channel = new Channel { Name = "channel", Classification = "class" }; var build = new Build { Branch = "source.branch", Repository = "source.repo", BuildNumber = "build.number", Commit = "sha", DateProduced = DateTimeOffset.UtcNow.AddDays(-1) }; var location = "https://repo.feed/index.json"; var newAsset = new Asset { Name = "source.asset", Version = "1.0.1", Locations = new List <AssetLocation> { new AssetLocation { Location = location, Type = LocationType.NugetFeed } } }; var newBuild = new Build { Branch = "source.branch", Repository = "source.repo", BuildNumber = "build.number.2", Commit = "sha2", DateProduced = DateTimeOffset.UtcNow, Assets = new List <Asset> { newAsset } }; var buildChannels = new[] { new BuildChannel { Build = build, Channel = channel }, new BuildChannel { Build = newBuild, Channel = channel } }; var subscription = new Subscription { Channel = channel, SourceRepository = "source.repo", TargetRepository = "target.repo", TargetBranch = "target.branch", Enabled = false, PolicyObject = new SubscriptionPolicy { MergePolicies = null, UpdateFrequency = UpdateFrequency.EveryBuild }, LastAppliedBuild = build }; var repoInstallation = new RepoInstallation { Repository = "target.repo", InstallationId = 1 }; await Context.BuildChannels.AddRangeAsync(buildChannels); await Context.Subscriptions.AddAsync(subscription); await Context.RepoInstallations.AddAsync(repoInstallation); await Context.SaveChangesAsync(); SubscriptionActor.Verify(a => a.UpdateAsync(build.Id), Times.Never()); var updater = ActivatorUtilities.CreateInstance <DependencyUpdater>(Scope.ServiceProvider); await updater.UpdateDependenciesAsync(newBuild.Id, channel.Id); }