From e56933bd54aec55a53ef1cfa3d27dba0ed6a6625 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 5 Oct 2018 16:06:43 -0400 Subject: [PATCH 1/4] Adds test merge deployment commenting --- .../Components/Instance.cs | 107 +++++++++++++++++- .../Components/InstanceFactory.cs | 11 +- 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index 254fb1eb57..a22ef066e3 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -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 /// readonly IEventConsumer eventConsumer; + /// + /// The for the + /// + readonly IGitHubClientFactory gitHubClientFactory; + /// /// The for the /// @@ -94,8 +101,9 @@ namespace Tgstation.Server.Host.Components /// The value of /// The value of /// The value of + /// The value of /// The value of - 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 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 logger) { this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager)); @@ -159,6 +167,9 @@ namespace Tgstation.Server.Host.Components if (ddSettings == default) throw new JobException("Missing DreamDaemonSettings in DB!"); + Task repositorySettingsTask = null; + string repoOwner = null; + string repoName = null; CompileJob compileJob; RevisionInformation revInfo; using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false)) @@ -166,8 +177,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 +222,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(); + + 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); + } + } + } } /// diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index 0823f16db8..7d087d1c08 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -98,6 +98,11 @@ namespace Tgstation.Server.Host.Components /// readonly INetworkPromptReaper networkPromptReaper; + /// + /// The for the + /// + readonly IGitHubClientFactory gitHubClientFactory; + /// /// Construct an /// @@ -117,7 +122,8 @@ namespace Tgstation.Server.Host.Components /// The value of /// The value of /// The value of - 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) + /// The value of + 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)); } /// @@ -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()); - return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, loggerFactory.CreateLogger()); + return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, gitHubClientFactory, loggerFactory.CreateLogger()); } catch { From ce39e8da66c2739e992e1a3110b68d60c03c1d14 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 5 Oct 2018 16:43:46 -0400 Subject: [PATCH 2/4] Prevent synchronization issues from failing repo jobs --- .../Components/Repository/Repository.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs index 6608fcd753..d9d0daaa8d 100644 --- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs +++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs @@ -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); } From bf122128b3efb7ab6da93b54078fa53d0aa23a86 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 5 Oct 2018 16:44:59 -0400 Subject: [PATCH 3/4] Fix instances not assigning their gitHubClientFactory --- src/Tgstation.Server.Host/Components/Instance.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tgstation.Server.Host/Components/Instance.cs b/src/Tgstation.Server.Host/Components/Instance.cs index a22ef066e3..18a50f6143 100644 --- a/src/Tgstation.Server.Host/Components/Instance.cs +++ b/src/Tgstation.Server.Host/Components/Instance.cs @@ -117,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)); } From f6ba6a8f449e0921b706c4bba085be6b8b7a354d Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 5 Oct 2018 17:01:28 -0400 Subject: [PATCH 4/4] Fix logging typo --- src/Tgstation.Server.Host/Core/Process.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Core/Process.cs b/src/Tgstation.Server.Host/Core/Process.cs index 10e9712d39..813ea77519 100644 --- a/src/Tgstation.Server.Host/Core/Process.cs +++ b/src/Tgstation.Server.Host/Core/Process.cs @@ -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); } ///