diff --git a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs index 049c217efb..5faa30dbd2 100644 --- a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs +++ b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs @@ -377,6 +377,7 @@ namespace Tgstation.Server.Host.Components.Chat /// public Func> QueueDeploymentMessage( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, @@ -407,6 +408,7 @@ namespace Tgstation.Server.Host.Components.Chat { var callback = await provider.SendUpdateMessage( revisionInformation, + previousRevisionInformation, engineVersion, estimatedCompletionTime, gitHubOwner, diff --git a/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs index 8a0aa33fe4..669f21b305 100644 --- a/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs +++ b/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs @@ -61,6 +61,7 @@ namespace Tgstation.Server.Host.Components.Chat /// Send the message for a deployment to configured deployment channels. /// /// The of the deployment. + /// The optional of the previous deployment. /// The of the deployment. /// The optional the deployment is expected to be completed at. /// The repository GitHub owner, if any. @@ -69,6 +70,7 @@ namespace Tgstation.Server.Host.Components.Chat /// A to call to update the message at the deployment's conclusion. Parameters: Error message if any, DreamMaker output if any. Returns an to call to mark the deployment as active/inactive. Parameter: If the deployment is being activated or inactivated. Func> QueueDeploymentMessage( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, Api.Models.EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs index 7012a94baf..f76ee34517 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs @@ -303,6 +303,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// public override async ValueTask>>> SendUpdateMessage( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, @@ -316,7 +317,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers localCommitPushed |= revisionInformation.CommitSha == revisionInformation.OriginCommitSha; - var fields = BuildUpdateEmbedFields(revisionInformation, engineVersion, gitHubOwner, gitHubRepo, localCommitPushed); + var fields = BuildUpdateEmbedFields(revisionInformation, previousRevisionInformation, engineVersion, gitHubOwner, gitHubRepo, localCommitPushed); Optional author = new EmbedAuthor(assemblyInformationProvider.VersionPrefix) { Url = "https://github.com/tgstation/tgstation-server", @@ -900,6 +901,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// Create a of s for a discord update embed. /// /// The of the deployment. + /// The optional of the previous deployment. /// The of the deployment. /// The repository GitHub owner, if any. /// The repository GitHub name, if any. @@ -907,6 +909,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// A new of s to use. List BuildUpdateEmbedFields( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, string? gitHubOwner, string? gitHubRepo, @@ -936,6 +939,31 @@ namespace Tgstation.Server.Host.Components.Chat.Providers if (gitHubOwner == null || gitHubRepo == null) return fields; + var previousTestMerges = (IEnumerable?)previousRevisionInformation?.ActiveTestMerges ?? Enumerable.Empty(); + var currentTestMerges = (IEnumerable?)revisionInformation.ActiveTestMerges ?? Enumerable.Empty(); + + // determine what TMs were changed and how + var addedTestMerges = currentTestMerges + .Select(x => x.TestMerge) + .Where(x => !previousTestMerges + .Any(y => y.TestMerge.Number == x.Number)) + .ToList(); + var removedTestMerges = previousTestMerges + .Select(x => x.TestMerge) + .Where(x => !currentTestMerges + .Any(y => y.TestMerge.Number == x.Number)) + .ToList(); + var updatedTestMerges = currentTestMerges + .Select(x => x.TestMerge) + .Where(x => previousTestMerges + .Any(y => y.TestMerge.Number == x.Number && y.TestMerge.TargetCommitSha != x.TargetCommitSha)) + .ToList(); + var unchangedTestMerges = currentTestMerges + .Select(x => x.TestMerge) + .Where(x => previousTestMerges + .Any(y => y.TestMerge.Number == x.Number && y.TestMerge.TargetCommitSha == x.TargetCommitSha)) + .ToList(); + fields.Add( new EmbedField( "Local Commit", @@ -952,13 +980,33 @@ namespace Tgstation.Server.Host.Components.Chat.Providers : revisionOriginSha[..7], true)); - fields.AddRange((revisionInformation.ActiveTestMerges ?? Enumerable.Empty()) - .Select(x => x.TestMerge) + fields.AddRange(addedTestMerges + .Select(x => new EmbedField( + $"#{x.Number} (Added)", + $"[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $"{Environment.NewLine}_**{x.Comment}**_")}", + false))); + + fields.AddRange(updatedTestMerges + .Select(x => new EmbedField( + $"#{x.Number} (Updated)", + $"[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $"{Environment.NewLine}_**{x.Comment}**_")}", + false))); + + fields.AddRange(unchangedTestMerges .Select(x => new EmbedField( $"#{x.Number}", $"[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $"{Environment.NewLine}_**{x.Comment}**_")}", false))); + if (removedTestMerges.Count != 0) + fields.Add( + new EmbedField( + "Removed:", + String.Join( + Environment.NewLine, + removedTestMerges + .Select(x => $"- #{x.Number} [{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_")))); + return fields; } diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs index 845892d9e0..0e32e3dbf6 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs @@ -84,6 +84,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// Send the message for a deployment. /// /// The of the deployment. + /// The of the previous deployment if any. /// The of the deployment. /// The optional the deployment is expected to be completed at. /// The repository GitHub owner, if any. @@ -94,6 +95,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// A resulting in a to call to update the message at the deployment's conclusion. Parameters: Error message if any, DreamMaker output if any. Returns another callback which should be called to mark the deployment as active. ValueTask>>> SendUpdateMessage( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, Api.Models.EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs index d449320bc7..560390201d 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs @@ -17,6 +17,7 @@ using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.IO; using Tgstation.Server.Host.Jobs; +using Tgstation.Server.Host.Models; using Tgstation.Server.Host.System; using Tgstation.Server.Host.Utils; @@ -217,6 +218,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// public override async ValueTask>>> SendUpdateMessage( Models.RevisionInformation revisionInformation, + Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, @@ -228,6 +230,9 @@ namespace Tgstation.Server.Host.Components.Chat.Providers ArgumentNullException.ThrowIfNull(revisionInformation); ArgumentNullException.ThrowIfNull(engineVersion); + var previousTestMerges = (IEnumerable?)previousRevisionInformation?.ActiveTestMerges ?? Enumerable.Empty(); + var currentTestMerges = (IEnumerable?)revisionInformation.ActiveTestMerges ?? Enumerable.Empty(); + var commitInsert = revisionInformation.CommitSha![..7]; string remoteCommitInsert; if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha) @@ -238,21 +243,35 @@ namespace Tgstation.Server.Host.Components.Chat.Providers else remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha![..7]); - var testmergeInsert = (revisionInformation.ActiveTestMerges?.Count ?? 0) == 0 + var testmergeInsert = !currentTestMerges.Any() ? String.Empty : String.Format( CultureInfo.InvariantCulture, " (Test Merges: {0})", String.Join( ", ", - revisionInformation - .ActiveTestMerges! + currentTestMerges .Select(x => x.TestMerge) .Select(x => { - var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.TargetCommitSha![..7]); - if (x.Comment != null) - result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment); + var status = string.Empty; + if (!previousTestMerges.Any(y => y.TestMerge.Number == x.Number)) + status = "Added"; + else if (previousTestMerges.Any(y => y.TestMerge.Number == x.Number && y.TestMerge.TargetCommitSha != x.TargetCommitSha)) + status = "Updated"; + + var result = $"#{x.Number} at {x.TargetCommitSha![..7]}"; + + if (!string.IsNullOrEmpty(x.Comment)) + { + if (!string.IsNullOrEmpty(status)) + result += $" ({status} - {x.Comment})"; + else + result += $" ({x.Comment})"; + } + else if (!string.IsNullOrEmpty(status)) + result += $" ({status})"; + return result; }))); diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs index 6be6b71521..e1f58b8288 100644 --- a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs +++ b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs @@ -199,6 +199,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers /// public abstract ValueTask>>> SendUpdateMessage( RevisionInformation revisionInformation, + RevisionInformation? previousRevisionInformation, Api.Models.EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs index 9ffab92802..6f8b05c9d2 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs @@ -336,13 +336,17 @@ namespace Tgstation.Server.Host.Components.Deployment } }); - var likelyPushedTestMergeCommit = - repositorySettings!.PushTestMergeCommits!.Value - && repositorySettings.AccessToken != null - && repositorySettings.AccessUser != null; + Models.CompileJob? oldCompileJob; using (repo) + { + var likelyPushedTestMergeCommit = + repositorySettings!.PushTestMergeCommits!.Value + && repositorySettings.AccessToken != null + && repositorySettings.AccessUser != null; + oldCompileJob = await compileJobConsumer.LatestCompileJob(); compileJob = await Compile( job, + oldCompileJob, revInfo!, dreamMakerSettings!, ddSettings!, @@ -352,8 +356,8 @@ namespace Tgstation.Server.Host.Components.Deployment averageSpan, likelyPushedTestMergeCommit, cancellationToken); + } - var activeCompileJob = await compileJobConsumer.LatestCompileJob(); try { await databaseContextFactory.UseContext( @@ -402,7 +406,7 @@ namespace Tgstation.Server.Host.Components.Deployment var commentsTask = remoteDeploymentManager!.PostDeploymentComments( compileJob, - activeCompileJob?.RevisionInformation, + oldCompileJob?.RevisionInformation, repositorySettings, repoOwner, repoName, @@ -479,6 +483,7 @@ namespace Tgstation.Server.Host.Components.Deployment /// Run the compile implementation. /// /// The currently running . + /// The optional of the previous deployment. /// The . /// The . /// The . @@ -491,6 +496,7 @@ namespace Tgstation.Server.Host.Components.Deployment /// A resulting in the completed . async ValueTask Compile( Models.Job job, + Models.CompileJob? oldCompileJob, Models.RevisionInformation revisionInformation, Api.Models.Internal.DreamMakerSettings dreamMakerSettings, DreamDaemonLaunchParameters launchParameters, @@ -512,6 +518,7 @@ namespace Tgstation.Server.Host.Components.Deployment using var engineLock = await engineManager.UseExecutables(null, null, cancellationToken); currentChatCallback = chatManager.QueueDeploymentMessage( revisionInformation, + oldCompileJob?.RevisionInformation, engineLock.Version, DateTimeOffset.UtcNow + estimatedDuration, repository.RemoteRepositoryOwner, diff --git a/src/Tgstation.Server.Host/Components/Deployment/Remote/BaseRemoteDeploymentManager.cs b/src/Tgstation.Server.Host/Components/Deployment/Remote/BaseRemoteDeploymentManager.cs index 0f8c86732f..0bcf10579b 100644 --- a/src/Tgstation.Server.Host/Components/Deployment/Remote/BaseRemoteDeploymentManager.cs +++ b/src/Tgstation.Server.Host/Components/Deployment/Remote/BaseRemoteDeploymentManager.cs @@ -66,36 +66,28 @@ namespace Tgstation.Server.Host.Components.Deployment.Remote if (repositorySettings.AccessToken == null) return; - var deployedRevisionInformation = compileJob.RevisionInformation; - if ((previousRevisionInformation != null && previousRevisionInformation.CommitSha == deployedRevisionInformation.CommitSha) + var revisionInformation = compileJob.RevisionInformation; + if ((previousRevisionInformation != null && previousRevisionInformation.CommitSha == revisionInformation.CommitSha) || !repositorySettings.PostTestMergeComment!.Value) return; - previousRevisionInformation ??= new RevisionInformation(); - previousRevisionInformation.ActiveTestMerges ??= new List(); + var previousTestMerges = (IEnumerable?)previousRevisionInformation?.ActiveTestMerges ?? Enumerable.Empty(); + var currentTestMerges = (IEnumerable?)revisionInformation.ActiveTestMerges ?? Enumerable.Empty(); - deployedRevisionInformation.ActiveTestMerges ??= new List(); - - // added prs - var addedTestMerges = deployedRevisionInformation - .ActiveTestMerges + // determine what TMs were changed and how + var addedTestMerges = currentTestMerges .Select(x => x.TestMerge) - .Where(x => !previousRevisionInformation - .ActiveTestMerges + .Where(x => !previousTestMerges .Any(y => y.TestMerge.Number == x.Number)) .ToList(); - var removedTestMerges = previousRevisionInformation - .ActiveTestMerges + var removedTestMerges = previousTestMerges .Select(x => x.TestMerge) - .Where(x => !deployedRevisionInformation - .ActiveTestMerges + .Where(x => !currentTestMerges .Any(y => y.TestMerge.Number == x.Number)) .ToList(); - var updatedTestMerges = deployedRevisionInformation - .ActiveTestMerges + var updatedTestMerges = currentTestMerges .Select(x => x.TestMerge) - .Where(x => previousRevisionInformation - .ActiveTestMerges + .Where(x => previousTestMerges .Any(y => y.TestMerge.Number == x.Number)) .ToList(); diff --git a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs index 04fe1b542c..20328014d6 100644 --- a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs +++ b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs @@ -105,6 +105,7 @@ namespace Tgstation.Server.Tests.Live public override ValueTask>>> SendUpdateMessage( RevisionInformation revisionInformation, + RevisionInformation previousRevisionInformation, Api.Models.EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string gitHubOwner,