2using System.Collections.Generic;
5using System.Threading.Tasks;
7using Microsoft.Extensions.Logging;
28 readonly ILogger<GitHubService>
logger;
44 this.logger =
logger ??
throw new ArgumentNullException(nameof(
logger));
51 ArgumentNullException.ThrowIfNull(oAuthConfiguration);
53 ArgumentNullException.ThrowIfNull(code);
55 logger.LogTrace(
"CreateOAuthAccessToken");
60 new OauthTokenRequest(
65 RedirectUri = oAuthConfiguration.RedirectUrl,
67 .WaitAsync(cancellationToken);
69 var token = response.AccessToken;
74 public async ValueTask<Dictionary<Version, Release>>
GetTgsReleases(CancellationToken cancellationToken)
76 logger.LogTrace(
"GetTgsReleases");
81 .WaitAsync(cancellationToken);
83 var gitPrefix = updatesConfiguration.GitTagPrefix ?? String.Empty;
85 logger.LogTrace(
"{totalReleases} total releases", allReleases.Count);
86 var releases = allReleases!
89 if (!release.PublishedAt.HasValue)
91 logger.LogDebug(
"Release tag without PublishedAt: {releaseTag}", release.TagName);
95 if (!release.TagName.StartsWith(gitPrefix, StringComparison.InvariantCulture))
102 if (!Version.TryParse(release.TagName.Replace(gitPrefix, String.Empty, StringComparison.Ordinal), out var version))
104 logger.LogDebug(
"Unparsable release tag: {releaseTag}", release.TagName);
110 .Where(grouping => grouping.Key !=
null)
113 .Select(grouping => Tuple.Create(grouping.Key!, grouping.OrderBy(x => x.PublishedAt ?? DateTimeOffset.MinValue).First()))
114 .ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
116 logger.LogTrace(
"{parsedReleases} parsed releases", releases.Count);
123 logger.LogTrace(
"GetUpdatesRepositoryUrl");
127 .WaitAsync(cancellationToken);
129 var repoUrl =
new Uri(repository.HtmlUrl);
130 logger.LogTrace(
"Maps to {repostioryUrl}", repoUrl);
138 logger.LogTrace(
"CreateOAuthAccessToken");
140 var userDetails = await
gitHubClient.User.Current().WaitAsync(cancellationToken);
141 return userDetails.Id;
145 public Task
CommentOnIssue(
string repoOwner,
string repoName,
string comment,
int issueNumber, CancellationToken cancellationToken)
147 ArgumentNullException.ThrowIfNull(repoOwner);
149 ArgumentNullException.ThrowIfNull(repoName);
151 ArgumentNullException.ThrowIfNull(comment);
153 logger.LogTrace(
"CommentOnIssue");
163 .WaitAsync(cancellationToken);
167 public Task
AppendCommentOnIssue(
string repoOwner,
string repoName,
string comment, IssueComment issueComment, CancellationToken cancellationToken)
169 ArgumentNullException.ThrowIfNull(repoOwner);
171 ArgumentNullException.ThrowIfNull(repoName);
173 ArgumentNullException.ThrowIfNull(comment);
175 ArgumentNullException.ThrowIfNull(issueComment);
177 logger.LogTrace(
"AppendCommentOnIssue");
186 issueComment.Body + comment)
187 .WaitAsync(cancellationToken);
191 public async ValueTask<IssueComment?>
GetExistingCommentOnIssue(
string repoOwner,
string repoName,
string header,
int issueNumber, CancellationToken cancellationToken)
193 ArgumentNullException.ThrowIfNull(repoOwner);
195 ArgumentNullException.ThrowIfNull(repoName);
197 ArgumentNullException.ThrowIfNull(header);
199 logger.LogTrace(
"GetExistingCommentOnIssue");
208 .WaitAsync(cancellationToken);
209 if (comments ==
null)
216 for (
int i = comments.Count - 1; i > -1; i--)
218 var currentComment = comments[i];
219 if (currentComment.User?.Id == userId && (currentComment.Body?.StartsWith(header) ??
false))
221 if (currentComment.Body.Length > 250000)
226 return currentComment;
234 public async ValueTask<long>
GetRepositoryId(
string repoOwner,
string repoName, CancellationToken cancellationToken)
236 ArgumentNullException.ThrowIfNull(repoOwner);
238 ArgumentNullException.ThrowIfNull(repoName);
240 logger.LogTrace(
"GetRepositoryId");
247 .WaitAsync(cancellationToken);
253 public async ValueTask<long>
CreateDeployment(NewDeployment newDeployment,
string repoOwner,
string repoName, CancellationToken cancellationToken)
255 ArgumentNullException.ThrowIfNull(newDeployment);
257 ArgumentNullException.ThrowIfNull(repoOwner);
259 ArgumentNullException.ThrowIfNull(repoName);
261 logger.LogTrace(
"CreateDeployment");
270 .WaitAsync(cancellationToken);
272 return deployment.Id;
276 public Task
CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus,
string repoOwner,
string repoName,
long deploymentId, CancellationToken cancellationToken)
278 ArgumentNullException.ThrowIfNull(newDeploymentStatus);
280 ArgumentNullException.ThrowIfNull(repoOwner);
282 ArgumentNullException.ThrowIfNull(repoName);
284 logger.LogTrace(
"CreateDeploymentStatus");
294 .WaitAsync(cancellationToken);
298 public Task
CreateDeploymentStatus(NewDeploymentStatus newDeploymentStatus,
long repoId,
long deploymentId, CancellationToken cancellationToken)
300 ArgumentNullException.ThrowIfNull(newDeploymentStatus);
302 logger.LogTrace(
"CreateDeploymentStatus");
311 .WaitAsync(cancellationToken);
315 public Task<PullRequest>
GetPullRequest(
string repoOwner,
string repoName,
int pullRequestNumber, CancellationToken cancellationToken)
317 ArgumentNullException.ThrowIfNull(repoOwner);
319 ArgumentNullException.ThrowIfNull(repoName);
321 logger.LogTrace(
"GetPullRequest");
329 .WaitAsync(cancellationToken);
333 public Task<GitHubCommit>
GetCommit(
string repoOwner,
string repoName,
string committish, CancellationToken cancellationToken)
335 ArgumentNullException.ThrowIfNull(repoOwner);
337 ArgumentNullException.ThrowIfNull(repoName);
339 logger.LogTrace(
"GetPulGetCommitlRequest");
347 .WaitAsync(cancellationToken);
string? ClientSecret
The client secret.
string? ClientId
The client ID.
OAuth configuration options.
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.
async ValueTask< IssueComment?> GetExistingCommentOnIssue(string repoOwner, string repoName, string header, int issueNumber, CancellationToken cancellationToken)
Gets an IssueComment for a particular issueNumber with the provided header if it exists and is not ...
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.
Task AppendCommentOnIssue(string repoOwner, string repoName, string comment, IssueComment issueComment, CancellationToken cancellationToken)
Append a comment on an existing issueComment .A Task representing the running operation.
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.