tgstation-server 6.8.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
BaseRemoteDeploymentManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Linq;
5using System.Threading;
6using System.Threading.Tasks;
7
8using Microsoft.Extensions.Logging;
9
13
15{
20 {
24 protected Api.Models.Instance Metadata { get; }
25
29 protected ILogger<BaseRemoteDeploymentManager> Logger { get; }
30
34 readonly ConcurrentDictionary<long, Action<bool>> activationCallbacks;
35
43 ILogger<BaseRemoteDeploymentManager> logger,
44 Api.Models.Instance metadata,
45 ConcurrentDictionary<long, Action<bool>> activationCallbacks)
46 {
47 Logger = logger ?? throw new ArgumentNullException(nameof(logger));
48 Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
49 this.activationCallbacks = activationCallbacks ?? throw new ArgumentNullException(nameof(activationCallbacks));
50 }
51
53 public async ValueTask PostDeploymentComments(
54 CompileJob compileJob,
55 RevisionInformation? previousRevisionInformation,
56 RepositorySettings repositorySettings,
57 string? repoOwner,
58 string? repoName,
59 CancellationToken cancellationToken)
60 {
61 ArgumentNullException.ThrowIfNull(compileJob);
62 ArgumentNullException.ThrowIfNull(repositorySettings);
63 ArgumentNullException.ThrowIfNull(repoOwner);
64 ArgumentNullException.ThrowIfNull(repoName);
65
66 if (repositorySettings.AccessToken == null)
67 return;
68
69 var deployedRevisionInformation = compileJob.RevisionInformation;
70 if ((previousRevisionInformation != null && previousRevisionInformation.CommitSha == deployedRevisionInformation.CommitSha)
71 || !repositorySettings.PostTestMergeComment!.Value)
72 return;
73
74 previousRevisionInformation ??= new RevisionInformation();
75 previousRevisionInformation.ActiveTestMerges ??= new List<RevInfoTestMerge>();
76
77 deployedRevisionInformation.ActiveTestMerges ??= new List<RevInfoTestMerge>();
78
79 // added prs
80 var addedTestMerges = deployedRevisionInformation
81 .ActiveTestMerges
82 .Select(x => x.TestMerge)
83 .Where(x => !previousRevisionInformation
84 .ActiveTestMerges
85 .Any(y => y.TestMerge.Number == x.Number))
86 .ToList();
87 var removedTestMerges = previousRevisionInformation
89 .Select(x => x.TestMerge)
90 .Where(x => !deployedRevisionInformation
91 .ActiveTestMerges
92 .Any(y => y.TestMerge.Number == x.Number))
93 .ToList();
94 var updatedTestMerges = deployedRevisionInformation
95 .ActiveTestMerges
96 .Select(x => x.TestMerge)
97 .Where(x => previousRevisionInformation
98 .ActiveTestMerges
99 .Any(y => y.TestMerge.Number == x.Number))
100 .ToList();
101
102 if (addedTestMerges.Count == 0 && removedTestMerges.Count == 0 && updatedTestMerges.Count == 0)
103 return;
104
105 Logger.LogTrace(
106 "Commenting on {addedCount} added, {removedCount} removed, and {updatedCount} updated test merge sources...",
107 addedTestMerges.Count,
108 removedTestMerges.Count,
109 updatedTestMerges.Count);
110
111 var tasks = new List<ValueTask>(addedTestMerges.Count + updatedTestMerges.Count + removedTestMerges.Count);
112 foreach (var addedTestMerge in addedTestMerges)
113 {
114 var addCommentTask = CommentOnTestMergeSource(
115 repositorySettings,
116 repoOwner,
117 repoName,
119 repositorySettings,
120 compileJob,
121 addedTestMerge,
122 repoOwner,
123 repoName,
124 false),
125 addedTestMerge.Number,
126 cancellationToken);
127 tasks.Add(addCommentTask);
128 }
129
130 foreach (var removedTestMerge in removedTestMerges)
131 {
132 var removeCommentTask = CommentOnTestMergeSource(
133 repositorySettings,
134 repoOwner,
135 repoName,
136 "#### Test Merge Removed",
137 removedTestMerge.Number,
138 cancellationToken);
139 tasks.Add(removeCommentTask);
140 }
141
142 foreach (var updatedTestMerge in updatedTestMerges)
143 {
144 var updateCommentTask = CommentOnTestMergeSource(
145 repositorySettings,
146 repoOwner,
147 repoName,
149 repositorySettings,
150 compileJob,
151 updatedTestMerge,
152 repoOwner,
153 repoName,
154 true),
155 updatedTestMerge.Number,
156 cancellationToken);
157 tasks.Add(updateCommentTask);
158 }
159
160 if (tasks.Count > 0)
161 await ValueTaskExtensions.WhenAll(tasks);
162 }
163
165 public ValueTask ApplyDeployment(CompileJob compileJob, CancellationToken cancellationToken)
166 {
167 ArgumentNullException.ThrowIfNull(compileJob);
168
169 if (activationCallbacks.TryGetValue(compileJob.Require(x => x.Id), out var activationCallback))
170 activationCallback(true);
171
172 return ApplyDeploymentImpl(compileJob, cancellationToken);
173 }
174
176 public abstract ValueTask FailDeployment(CompileJob compileJob, string errorMessage, CancellationToken cancellationToken);
177
179 public ValueTask MarkInactive(CompileJob compileJob, CancellationToken cancellationToken)
180 {
181 ArgumentNullException.ThrowIfNull(compileJob);
182
183 if (activationCallbacks.TryRemove(compileJob.Require(x => x.Id), out var activationCallback))
184 activationCallback(false);
185
186 return MarkInactiveImpl(compileJob, cancellationToken);
187 }
188
190 public abstract ValueTask<IReadOnlyCollection<TestMerge>> RemoveMergedTestMerges(
191 IRepository repository,
192 RepositorySettings repositorySettings,
193 RevisionInformation revisionInformation,
194 CancellationToken cancellationToken);
195
197 public ValueTask StageDeployment(CompileJob compileJob, Action<bool>? activationCallback, CancellationToken cancellationToken)
198 {
199 ArgumentNullException.ThrowIfNull(compileJob);
200
201 var compileJobId = compileJob.Require(x => x.Id);
202 if (activationCallback != null && !activationCallbacks.TryAdd(compileJobId, activationCallback))
203 Logger.LogError("activationCallbacks conflicted on CompileJob #{id}!", compileJobId);
204
205 return StageDeploymentImpl(compileJob, cancellationToken);
206 }
207
209 public abstract ValueTask StartDeployment(
210 Api.Models.Internal.IGitRemoteInformation remoteInformation,
211 CompileJob compileJob,
212 CancellationToken cancellationToken);
213
220 protected abstract ValueTask StageDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken);
221
228 protected abstract ValueTask ApplyDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken);
229
236 protected abstract ValueTask MarkInactiveImpl(CompileJob compileJob, CancellationToken cancellationToken);
237
248 protected abstract string FormatTestMerge(
249 RepositorySettings repositorySettings,
250 CompileJob compileJob,
251 TestMerge testMerge,
252 string remoteRepositoryOwner,
253 string remoteRepositoryName,
254 bool updated);
255
266 protected abstract ValueTask CommentOnTestMergeSource(
267 RepositorySettings repositorySettings,
268 string remoteRepositoryOwner,
269 string remoteRepositoryName,
270 string comment,
271 int testMergeNumber,
272 CancellationToken cancellationToken);
273 }
274}
Metadata about a server instance.
Definition: Instance.cs:9
string? AccessToken
The token/password to access the git repository with.
bool? PostTestMergeComment
If test merging should create a comment. Requires AccessToken to be set to function.
Extension methods for the ValueTask and ValueTask<TResult> classes.
static async ValueTask WhenAll(IEnumerable< ValueTask > tasks)
Fully await a given list of tasks .
Api.Models.Instance Metadata
The Api.Models.Instance for the BaseRemoteDeploymentManager.
abstract ValueTask StartDeployment(Api.Models.Internal.IGitRemoteInformation remoteInformation, CompileJob compileJob, CancellationToken cancellationToken)
Start a deployment for a given compileJob . A ValueTask representing the running operation.
ValueTask StageDeployment(CompileJob compileJob, Action< bool >? activationCallback, CancellationToken cancellationToken)
Stage a given compileJob 's deployment. A ValueTask representing the running operation.
abstract string FormatTestMerge(RepositorySettings repositorySettings, CompileJob compileJob, TestMerge testMerge, string remoteRepositoryOwner, string remoteRepositoryName, bool updated)
Formats a comment for a given testMerge .
ValueTask MarkInactive(CompileJob compileJob, CancellationToken cancellationToken)
Mark the deplotment for a given compileJob as inactive. A Task representing the running operation.
abstract ValueTask CommentOnTestMergeSource(RepositorySettings repositorySettings, string remoteRepositoryOwner, string remoteRepositoryName, string comment, int testMergeNumber, CancellationToken cancellationToken)
Create a comment of a given testMergeNumber 's source.
abstract ValueTask MarkInactiveImpl(CompileJob compileJob, CancellationToken cancellationToken)
Implementation of MarkInactive(CompileJob, CancellationToken).
readonly ConcurrentDictionary< long, Action< bool > > activationCallbacks
A map of CompileJob Api.Models.EntityId.Ids to activation callback Action<T1>s.
BaseRemoteDeploymentManager(ILogger< BaseRemoteDeploymentManager > logger, Api.Models.Instance metadata, ConcurrentDictionary< long, Action< bool > > activationCallbacks)
Initializes a new instance of the BaseRemoteDeploymentManager class.
abstract ValueTask ApplyDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken)
Implementation of ApplyDeployment(CompileJob, CancellationToken).
abstract ValueTask StageDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken)
Implementation of StageDeployment(CompileJob, Action<bool>, CancellationToken).
async ValueTask PostDeploymentComments(CompileJob compileJob, RevisionInformation? previousRevisionInformation, RepositorySettings repositorySettings, string? repoOwner, string? repoName, CancellationToken cancellationToken)
Post deployment comments to the test merge ticket. A ValueTask representing the running operation.
ValueTask ApplyDeployment(CompileJob compileJob, CancellationToken cancellationToken)
Stage a given compileJob 's deployment. A ValueTask representing the running operation.
abstract ValueTask< IReadOnlyCollection< TestMerge > > RemoveMergedTestMerges(IRepository repository, RepositorySettings repositorySettings, RevisionInformation revisionInformation, CancellationToken cancellationToken)
Get the updated list of TestMerges for an origin merge. A ValueTask<TResult> resulting in the IReadOn...
abstract ValueTask FailDeployment(CompileJob compileJob, string errorMessage, CancellationToken cancellationToken)
Fail a deployment for a given compileJob . A ValueTask representing the running operation.
ILogger< BaseRemoteDeploymentManager > Logger
The ILogger for the BaseRemoteDeploymentManager.
RevisionInformation RevisionInformation
See CompileJobResponse.RevisionInformation.
Definition: CompileJob.cs:27
ICollection< RevInfoTestMerge >? ActiveTestMerges
See Api.Models.RevisionInformation.ActiveTestMerges.
Represents an on-disk git repository.
Definition: IRepository.cs:14