tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
GitLabRemoteDeploymentManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Globalization;
5using System.Linq;
6using System.Threading;
7using System.Threading.Tasks;
8
9using GitLabApiClient;
10using GitLabApiClient.Models.MergeRequests.Responses;
11using GitLabApiClient.Models.Notes.Requests;
12using Microsoft.Extensions.Logging;
13
16
18{
23 {
31 ILogger<GitLabRemoteDeploymentManager> logger,
32 Api.Models.Instance metadata,
33 ConcurrentDictionary<long, Action<bool>> activationCallbacks)
34 : base(logger, metadata, activationCallbacks)
35 {
36 }
37
39 public override async ValueTask<IReadOnlyCollection<TestMerge>> RemoveMergedTestMerges(
40 IRepository repository,
41 RepositorySettings repositorySettings,
42 RevisionInformation revisionInformation,
43 CancellationToken cancellationToken)
44 {
45 ArgumentNullException.ThrowIfNull(repository);
46 ArgumentNullException.ThrowIfNull(repositorySettings);
47 ArgumentNullException.ThrowIfNull(revisionInformation);
48
49 if ((revisionInformation.ActiveTestMerges?.Count > 0) != true)
50 {
51 Logger.LogTrace("No test merges to remove.");
52 return Array.Empty<TestMerge>();
53 }
54
55 var client = repositorySettings.AccessToken != null
56 ? new GitLabClient(GitLabRemoteFeatures.GitLabUrl, repositorySettings.AccessToken)
57 : new GitLabClient(GitLabRemoteFeatures.GitLabUrl);
58
59 var tasks = revisionInformation
61 .Select(x => client
62 .MergeRequests
63 .GetAsync(
64 $"{repository.RemoteRepositoryOwner}/{repository.RemoteRepositoryName}",
65 x.TestMerge.Number)
66 .WaitAsync(cancellationToken));
67 try
68 {
69 await Task.WhenAll(tasks);
70 }
71 catch (Exception ex) when (ex is not OperationCanceledException)
72 {
73 Logger.LogWarning(ex, "Merge requests update check failed!");
74 }
75
76 var newList = revisionInformation.ActiveTestMerges.Select(x => x.TestMerge).ToList();
77
78 MergeRequest? lastMerged = null;
79 async ValueTask CheckRemoveMR(Task<MergeRequest> task)
80 {
81 var mergeRequest = await task;
82 if (mergeRequest.State != MergeRequestState.Merged)
83 return;
84
85 // We don't just assume, actually check the repo contains the merge commit.
86 if (await repository.CommittishIsParent(mergeRequest.MergeCommitSha, cancellationToken))
87 {
88 if (lastMerged == null || lastMerged.ClosedAt < mergeRequest.ClosedAt)
89 lastMerged = mergeRequest;
90 newList.Remove(
91 newList.First(
92 potential => potential.Number == mergeRequest.Id));
93 }
94 }
95
96 foreach (var prTask in tasks)
97 await CheckRemoveMR(prTask);
98
99 return newList;
100 }
101
103 public override ValueTask FailDeployment(
104 CompileJob compileJob,
105 string errorMessage,
106 CancellationToken cancellationToken) => ValueTask.CompletedTask;
107
109 public override ValueTask StartDeployment(
110 Api.Models.Internal.IGitRemoteInformation remoteInformation,
111 CompileJob compileJob,
112 CancellationToken cancellationToken) => ValueTask.CompletedTask;
113
115 protected override ValueTask ApplyDeploymentImpl(
116 CompileJob compileJob,
117 CancellationToken cancellationToken) => ValueTask.CompletedTask;
118
120 protected override ValueTask StageDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken) => ValueTask.CompletedTask;
121
123 protected override ValueTask MarkInactiveImpl(CompileJob compileJob, CancellationToken cancellationToken) => ValueTask.CompletedTask;
124
126 protected override async ValueTask CommentOnTestMergeSource(
127 RepositorySettings repositorySettings,
128 string remoteRepositoryOwner,
129 string remoteRepositoryName,
130 string comment,
131 int testMergeNumber,
132 CancellationToken cancellationToken)
133 {
134 var client = repositorySettings.AccessToken != null
135 ? new GitLabClient(GitLabRemoteFeatures.GitLabUrl, repositorySettings.AccessToken)
136 : new GitLabClient(GitLabRemoteFeatures.GitLabUrl);
137
138 try
139 {
140 await client
141 .MergeRequests
142 .CreateNoteAsync(
143 $"{remoteRepositoryOwner}/{remoteRepositoryName}",
144 testMergeNumber,
145 new CreateMergeRequestNoteRequest(comment))
146 .WaitAsync(cancellationToken);
147 }
148 catch (Exception ex) when (ex is not OperationCanceledException)
149 {
150 Logger.LogWarning(ex, "Error posting GitHub comment!");
151 }
152 }
153
155 protected override string FormatTestMerge(
156 RepositorySettings repositorySettings,
157 CompileJob compileJob,
158 TestMerge testMerge,
159 string remoteRepositoryOwner,
160 string remoteRepositoryName,
161 bool updated) => String.Format(
162 CultureInfo.InvariantCulture,
163 "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Merge Request: {2}{0}Server: {7}{3}",
164 Environment.NewLine,
165 repositorySettings.ShowTestMergeCommitters!.Value
166 ? String.Format(
167 CultureInfo.InvariantCulture,
168 "{0}{0}##### Merged By{0}{1}",
169 Environment.NewLine,
170 testMerge.MergedBy!.Name)
171 : String.Empty,
172 testMerge.TargetCommitSha,
173 testMerge.Comment != null
174 ? String.Format(
175 CultureInfo.InvariantCulture,
176 "{0}{0}##### Comment{0}{1}",
177 Environment.NewLine,
178 testMerge.Comment)
179 : String.Empty,
180 updated ? "Updated" : "Deployed",
181 Metadata.Name,
182 compileJob.RevisionInformation.OriginCommitSha,
183 compileJob.RevisionInformation.CommitSha);
184 }
185}
string? AccessToken
The token/password to access the git repository with. Can also be a TGS encoded app private key....
Api.Models.Instance Metadata
The Api.Models.Instance for the BaseRemoteDeploymentManager.
readonly ConcurrentDictionary< long, Action< bool > > activationCallbacks
A map of CompileJob Api.Models.EntityId.Ids to activation callback Action<T1>s.
ILogger< BaseRemoteDeploymentManager > Logger
The ILogger for the BaseRemoteDeploymentManager.
override async 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 IReadOnl...
override ValueTask ApplyDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken)
override string FormatTestMerge(RepositorySettings repositorySettings, CompileJob compileJob, TestMerge testMerge, string remoteRepositoryOwner, string remoteRepositoryName, bool updated)
override async ValueTask CommentOnTestMergeSource(RepositorySettings repositorySettings, string remoteRepositoryOwner, string remoteRepositoryName, string comment, int testMergeNumber, CancellationToken cancellationToken)
override ValueTask StageDeploymentImpl(CompileJob compileJob, CancellationToken cancellationToken)
override ValueTask StartDeployment(Api.Models.Internal.IGitRemoteInformation remoteInformation, CompileJob compileJob, CancellationToken cancellationToken)
Start a deployment for a given compileJob .A ValueTask representing the running operation.
GitLabRemoteDeploymentManager(ILogger< GitLabRemoteDeploymentManager > logger, Api.Models.Instance metadata, ConcurrentDictionary< long, Action< bool > > activationCallbacks)
Initializes a new instance of the GitLabRemoteDeploymentManager class.
override ValueTask MarkInactiveImpl(CompileJob compileJob, CancellationToken cancellationToken)
override ValueTask FailDeployment(CompileJob compileJob, string errorMessage, CancellationToken cancellationToken)
Fail a deployment for a given compileJob .A ValueTask representing the running operation.
ICollection< RevInfoTestMerge >? ActiveTestMerges
See Api.Models.RevisionInformation.ActiveTestMerges.
Represents an on-disk git repository.
Task< bool > CommittishIsParent(string committish, CancellationToken cancellationToken)
Check if a given committish is a parent of the current Head.