Merge pull request #768 from tgstation/686-TestMergeCommentary

Adds test merge deployment GitHub comments
This commit is contained in:
Jordan Brown
2018-10-05 18:43:42 -04:00
committed by GitHub
4 changed files with 124 additions and 6 deletions
@@ -1,7 +1,9 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Octokit;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -60,6 +62,11 @@ namespace Tgstation.Server.Host.Components
/// </summary>
readonly IEventConsumer eventConsumer;
/// <summary>
/// The <see cref="IGitHubClientFactory"/> for the <see cref="Instance"/>
/// </summary>
readonly IGitHubClientFactory gitHubClientFactory;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="Instance"/>
/// </summary>
@@ -94,8 +101,9 @@ namespace Tgstation.Server.Host.Components
/// <param name="dmbFactory">The value of <see cref="dmbFactory"/></param>
/// <param name="jobManager">The value of <see cref="jobManager"/></param>
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/></param>
/// <param name="logger">The value of <see cref="logger"/></param>
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, ILogger<Instance> logger)
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger<Instance> logger)
{
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
@@ -109,6 +117,7 @@ namespace Tgstation.Server.Host.Components
this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
@@ -159,6 +168,9 @@ namespace Tgstation.Server.Host.Components
if (ddSettings == default)
throw new JobException("Missing DreamDaemonSettings in DB!");
Task<RepositorySettings> repositorySettingsTask = null;
string repoOwner = null;
string repoName = null;
CompileJob compileJob;
RevisionInformation revInfo;
using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
@@ -166,8 +178,19 @@ namespace Tgstation.Server.Host.Components
if (repo == null)
throw new JobException("Missing Repository!");
if (repo.IsGitHubRepository)
{
repoOwner = repo.GitHubOwner;
repoName = repo.GitHubRepoName;
repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).Select(x => new RepositorySettings
{
AccessToken = x.AccessToken,
ShowTestMergeCommitters = x.ShowTestMergeCommitters
}).FirstOrDefaultAsync(cancellationToken);
}
var repoSha = repo.Head;
revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha && x.Instance.Id == metadata.Id).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).FirstOrDefaultAsync().ConfigureAwait(false);
revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha && x.Instance.Id == metadata.Id).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy).FirstOrDefaultAsync().ConfigureAwait(false);
if (revInfo == default)
{
@@ -200,8 +223,87 @@ namespace Tgstation.Server.Host.Components
compileJob.Job = job;
databaseContext.CompileJobs.Add(compileJob); //will be saved by job context
job.PostComplete = ct => CompileJobConsumer.LoadCompileJob(compileJob, ct);
if (repositorySettingsTask != null)
{
var repositorySettings = await repositorySettingsTask.ConfigureAwait(false);
if (repositorySettings == default)
throw new JobException("Missing repository settings!");
if (repositorySettings.AccessToken != null)
{
//potential for commenting on a test merge change
var outgoingCompileJob = LatestCompileJob();
if(outgoingCompileJob != null && outgoingCompileJob.RevisionInformation.CommitSha != compileJob.RevisionInformation.CommitSha)
{
var gitHubClient = gitHubClientFactory.CreateClient(repositorySettings.AccessToken);
async Task CommentOnPR(int prNumber, string comment)
{
try
{
await gitHubClient.Issue.Comment.Create(repoOwner, repoName, prNumber, comment).ConfigureAwait(false);
}
catch (ApiException e)
{
logger.LogWarning("Error posting GitHub comment! Exception: {0}", e);
}
}
var tasks = new List<Task>();
string FormatTestMerge(TestMerge testMerge, bool updated) => String.Format(CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}",
Environment.NewLine,
repositorySettings.ShowTestMergeCommitters.Value ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty,
testMerge.PullRequestRevision,
testMerge.Comment != null ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Comment{0}{1}", Environment.NewLine, testMerge.Comment) : String.Empty,
updated ? "Updated" : "Deployed",
metadata.Name,
compileJob.RevisionInformation.OriginCommitSha,
compileJob.RevisionInformation.CommitSha
);
//added prs
foreach (var I in compileJob
.RevisionInformation
.ActiveTestMerges
.Select(x => x.TestMerge)
.Where(x => !outgoingCompileJob
.RevisionInformation
.ActiveTestMerges
.Any(y => y.TestMerge.Number == x.Number)))
tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, false)));
//removed prs
foreach (var I in outgoingCompileJob
.RevisionInformation
.ActiveTestMerges
.Select(x => x.TestMerge)
.Where(x => !compileJob
.RevisionInformation
.ActiveTestMerges
.Any(y => y.TestMerge.Number == x.Number)))
tasks.Add(CommentOnPR(I.Number.Value, "#### Test Merge Removed"));
//updated prs
foreach(var I in compileJob
.RevisionInformation
.ActiveTestMerges
.Select(x => x.TestMerge)
.Where(x => outgoingCompileJob
.RevisionInformation
.ActiveTestMerges
.Any(y => y.TestMerge.Number == x.Number)))
tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, true)));
if (tasks.Any())
await Task.WhenAll(tasks).ConfigureAwait(false);
}
}
}
}
/// <summary>
@@ -98,6 +98,11 @@ namespace Tgstation.Server.Host.Components
/// </summary>
readonly INetworkPromptReaper networkPromptReaper;
/// <summary>
/// The <see cref="IGitHubClientFactory"/> for the <see cref="InstanceFactory"/>
/// </summary>
readonly IGitHubClientFactory gitHubClientFactory;
/// <summary>
/// Construct an <see cref="InstanceFactory"/>
/// </summary>
@@ -117,7 +122,8 @@ namespace Tgstation.Server.Host.Components
/// <param name="jobManager">The value of <see cref="jobManager"/></param>
/// <param name="credentialsProvider">The value of <see cref="credentialsProvider"/></param>
/// <param name="networkPromptReaper">The value of <see cref="networkPromptReaper"/></param>
public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IChatFactory chatFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IWatchdogFactory watchdogFactory, IJobManager jobManager, ICredentialsProvider credentialsProvider, INetworkPromptReaper networkPromptReaper)
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/></param>
public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IChatFactory chatFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IWatchdogFactory watchdogFactory, IJobManager jobManager, ICredentialsProvider credentialsProvider, INetworkPromptReaper networkPromptReaper, IGitHubClientFactory gitHubClientFactory)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
@@ -135,6 +141,7 @@ namespace Tgstation.Server.Host.Components
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
}
/// <inheritdoc />
@@ -174,7 +181,7 @@ namespace Tgstation.Server.Host.Components
{
var dreamMaker = new DreamMaker(byond, gameIoManager, configuration, sessionControllerFactory, dmbFactory, application, eventConsumer, chat, processExecutor, watchdog, loggerFactory.CreateLogger<DreamMaker>());
return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, loggerFactory.CreateLogger<Instance>());
return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, gitHubClientFactory, loggerFactory.CreateLogger<Instance>());
}
catch
{
@@ -381,6 +381,10 @@ namespace Tgstation.Server.Host.Components.Repository
{
cancellationToken.ThrowIfCancellationRequested();
}
catch(LibGit2SharpException e)
{
logger.LogWarning("Unable to push to temporary branch! Exception: {0}", e);
}
}
finally
{
@@ -581,6 +585,11 @@ namespace Tgstation.Server.Host.Components.Repository
cancellationToken.ThrowIfCancellationRequested();
throw new InvalidOperationException("Caught UserCancelledException without cancellationToken triggering", e);
}
catch (LibGit2SharpException e)
{
logger.LogWarning("Unable to make synchronization push! Exception: {0}", e);
return false;
}
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
}
+1 -1
View File
@@ -56,7 +56,7 @@ namespace Tgstation.Server.Host.Core
catch (InvalidOperationException) { }
}, default, TaskCreationOptions.LongRunning, TaskScheduler.Current);
logger.LogTrace("Created proces ID: {0}", Id);
logger.LogTrace("Created process ID: {0}", Id);
}
/// <inheritdoc />