tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
GitHubService.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Threading;
5using System.Threading.Tasks;
6
7using Microsoft.Extensions.Logging;
8
9using Octokit;
10
12
14{
19 {
23 readonly IGitHubClient gitHubClient;
24
28 readonly ILogger<GitHubService> logger;
29
34
41 public GitHubService(IGitHubClient gitHubClient, ILogger<GitHubService> logger, UpdatesConfiguration updatesConfiguration)
42 {
43 this.gitHubClient = gitHubClient ?? throw new ArgumentNullException(nameof(gitHubClient));
44 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
45 this.updatesConfiguration = updatesConfiguration ?? throw new ArgumentNullException(nameof(updatesConfiguration));
46 }
47
49 public async ValueTask<string> CreateOAuthAccessToken(OAuthConfiguration oAuthConfiguration, string code, CancellationToken cancellationToken)
50 {
51 ArgumentNullException.ThrowIfNull(oAuthConfiguration);
52
53 ArgumentNullException.ThrowIfNull(code);
54
55 logger.LogTrace("CreateOAuthAccessToken");
56
57 var response = await gitHubClient
58 .Oauth
59 .CreateAccessToken(
60 new OauthTokenRequest(
61 oAuthConfiguration.ClientId,
62 oAuthConfiguration.ClientSecret,
63 code)
64 {
65 RedirectUri = oAuthConfiguration.RedirectUrl,
66 })
67 .WaitAsync(cancellationToken);
68
69 var token = response.AccessToken;
70 return token;
71 }
72
74 public async ValueTask<Dictionary<Version, Release>> GetTgsReleases(CancellationToken cancellationToken)
75 {
76 logger.LogTrace("GetTgsReleases");
77 var allReleases = await gitHubClient
78 .Repository
79 .Release
81 .WaitAsync(cancellationToken);
82
83 var gitPrefix = updatesConfiguration.GitTagPrefix ?? String.Empty;
84
85 logger.LogTrace("{totalReleases} total releases", allReleases.Count);
86 var releases = allReleases!
87 .Where(release =>
88 {
89 if (!release.PublishedAt.HasValue)
90 {
91 logger.LogDebug("Release tag without PublishedAt: {releaseTag}", release.TagName);
92 return false;
93 }
94
95 if (!release.TagName.StartsWith(gitPrefix, StringComparison.InvariantCulture))
96 return false;
97
98 return true;
99 })
100 .GroupBy(release =>
101 {
102 if (!Version.TryParse(release.TagName.Replace(gitPrefix, String.Empty, StringComparison.Ordinal), out var version))
103 {
104 logger.LogDebug("Unparsable release tag: {releaseTag}", release.TagName);
105 return null;
106 }
107
108 return version;
109 })
110 .Where(grouping => grouping.Key != null)
111
112 // GitHub can return the same result twice or some other nonsense
113 .Select(grouping => Tuple.Create(grouping.Key!, grouping.OrderBy(x => x.PublishedAt ?? DateTimeOffset.MinValue).First()))
114 .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
115
116 logger.LogTrace("{parsedReleases} parsed releases", releases.Count);
117 return releases;
118 }
119
121 public async ValueTask<Uri> GetUpdatesRepositoryUrl(CancellationToken cancellationToken)
122 {
123 logger.LogTrace("GetUpdatesRepositoryUrl");
124 var repository = await gitHubClient
125 .Repository
127 .WaitAsync(cancellationToken);
128
129 var repoUrl = new Uri(repository.HtmlUrl);
130 logger.LogTrace("Maps to {repostioryUrl}", repoUrl);
131
132 return repoUrl;
133 }
134
136 public async ValueTask<long> GetCurrentUserId(CancellationToken cancellationToken)
137 {
138 logger.LogTrace("CreateOAuthAccessToken");
139
140 var userDetails = await gitHubClient.User.Current().WaitAsync(cancellationToken);
141 return userDetails.Id;
142 }
143
145 public Task CommentOnIssue(string repoOwner, string repoName, string comment, int issueNumber, CancellationToken cancellationToken)
146 {
147 ArgumentNullException.ThrowIfNull(repoOwner);
148
149 ArgumentNullException.ThrowIfNull(repoName);
150
151 ArgumentNullException.ThrowIfNull(comment);
152
153 logger.LogTrace("CommentOnIssue");
154
155 return gitHubClient
156 .Issue
157 .Comment
158 .Create(
159 repoOwner,
160 repoName,
161 issueNumber,
162 comment)
163 .WaitAsync(cancellationToken);
164 }
165
167 public async ValueTask<long> GetRepositoryId(string repoOwner, string repoName, CancellationToken cancellationToken)
168 {
169 ArgumentNullException.ThrowIfNull(repoOwner);
170
171 ArgumentNullException.ThrowIfNull(repoName);
172
173 logger.LogTrace("GetRepositoryId");
174
175 var repo = await gitHubClient
176 .Repository
177 .Get(
178 repoOwner,
179 repoName)
180 .WaitAsync(cancellationToken);
181
182 return repo.Id;
183 }
184
186 public async ValueTask<long> CreateDeployment(NewDeployment newDeployment, string repoOwner, string repoName, CancellationToken cancellationToken)
187 {
188 ArgumentNullException.ThrowIfNull(newDeployment);
189
190 ArgumentNullException.ThrowIfNull(repoOwner);
191
192 ArgumentNullException.ThrowIfNull(repoName);
193
194 logger.LogTrace("CreateDeployment");
195
196 var deployment = await gitHubClient
197 .Repository
198 .Deployment
199 .Create(
200 repoOwner,
201 repoName,
202 newDeployment)
203 .WaitAsync(cancellationToken);
204
205 return deployment.Id;
206 }
207
209 public Task CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus, string repoOwner, string repoName, long deploymentId, CancellationToken cancellationToken)
210 {
211 ArgumentNullException.ThrowIfNull(newDeploymentStatus);
212
213 ArgumentNullException.ThrowIfNull(repoOwner);
214
215 ArgumentNullException.ThrowIfNull(repoName);
216
217 logger.LogTrace("CreateDeploymentStatus");
218 return gitHubClient
219 .Repository
220 .Deployment
221 .Status
222 .Create(
223 repoOwner,
224 repoName,
225 deploymentId,
226 newDeploymentStatus)
227 .WaitAsync(cancellationToken);
228 }
229
231 public Task CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus, long repoId, long deploymentId, CancellationToken cancellationToken)
232 {
233 ArgumentNullException.ThrowIfNull(newDeploymentStatus);
234
235 logger.LogTrace("CreateDeploymentStatus");
236 return gitHubClient
237 .Repository
238 .Deployment
239 .Status
240 .Create(
241 repoId,
242 deploymentId,
243 newDeploymentStatus)
244 .WaitAsync(cancellationToken);
245 }
246
248 public Task<PullRequest> GetPullRequest(string repoOwner, string repoName, int pullRequestNumber, CancellationToken cancellationToken)
249 {
250 ArgumentNullException.ThrowIfNull(repoOwner);
251
252 ArgumentNullException.ThrowIfNull(repoName);
253
254 logger.LogTrace("GetPullRequest");
255 return gitHubClient
256 .Repository
257 .PullRequest
258 .Get(
259 repoOwner,
260 repoName,
261 pullRequestNumber)
262 .WaitAsync(cancellationToken);
263 }
264
266 public Task<GitHubCommit> GetCommit(string repoOwner, string repoName, string committish, CancellationToken cancellationToken)
267 {
268 ArgumentNullException.ThrowIfNull(repoOwner);
269
270 ArgumentNullException.ThrowIfNull(repoName);
271
272 logger.LogTrace("GetPulGetCommitlRequest");
273 return gitHubClient
274 .Repository
275 .Commit
276 .Get(
277 repoOwner,
278 repoName,
279 committish)
280 .WaitAsync(cancellationToken);
281 }
282 }
283}
Configuration for the automatic update system.
long GitHubRepositoryId
The Octokit.Repository.Id of the tgstation-server fork to receive updates from.
Service for interacting with the GitHub API. Authenticated or otherwise.
async ValueTask< long > CreateDeployment(NewDeployment newDeployment, string repoOwner, string repoName, CancellationToken cancellationToken)
Create a newDeployment on a target repostiory.A ValueTask<TResult> resulting in the new deployment's...
Task< PullRequest > GetPullRequest(string repoOwner, string repoName, int pullRequestNumber, CancellationToken cancellationToken)
Get a given pullRequestNumber .A Task<TResult> resulting in the target PullRequest.
readonly UpdatesConfiguration updatesConfiguration
The UpdatesConfiguration for the GitHubService.
GitHubService(IGitHubClient gitHubClient, ILogger< GitHubService > logger, UpdatesConfiguration updatesConfiguration)
Initializes a new instance of the GitHubService class.
readonly ILogger< GitHubService > logger
The ILogger for the GitHubService.
async ValueTask< Uri > GetUpdatesRepositoryUrl(CancellationToken cancellationToken)
Gets the Uri of the repository designated as the updates repository.A ValueTask<TResult> resulting in...
Task< GitHubCommit > GetCommit(string repoOwner, string repoName, string committish, CancellationToken cancellationToken)
Get a given committish .A Task<TResult> resulting in the target GitHubCommit.
async ValueTask< long > GetRepositoryId(string repoOwner, string repoName, CancellationToken cancellationToken)
Get a target repostiory's ID.A ValueTask<TResult> resulting in the target repository's ID.
async ValueTask< string > CreateOAuthAccessToken(OAuthConfiguration oAuthConfiguration, string code, CancellationToken cancellationToken)
Attempt to get an OAuth token from a given code .A ValueTask<TResult> resulting in a string represent...
Task CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus, long repoId, long deploymentId, CancellationToken cancellationToken)
Create a newDeploymentStatus on a target deployment.A Task representing the running operation.
Task CommentOnIssue(string repoOwner, string repoName, string comment, int issueNumber, CancellationToken cancellationToken)
Create a comment on a given issueNumber .A Task representing the running operation.
Task CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus, string repoOwner, string repoName, long deploymentId, CancellationToken cancellationToken)
Create a newDeploymentStatus on a target deployment.A Task representing the running operation.
async ValueTask< Dictionary< Version, Release > > GetTgsReleases(CancellationToken cancellationToken)
Get all valid TGS Releases from the configured update source.A ValueTask<TResult> resulting in a Dict...
async ValueTask< long > GetCurrentUserId(CancellationToken cancellationToken)
Get the current user's ID.A ValueTask<TResult> resulting in the current user's ID.
readonly IGitHubClient gitHubClient
The IGitHubClient for the GitHubService.
IGitHubService that exposes functions that require authentication.