mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-22 20:47:28 +01:00
Diverse test merging big commit
This commit is contained in:
@@ -14,5 +14,10 @@ namespace Tgstation.Server.Api.Models
|
||||
/// Remote provider is GitHub.com
|
||||
/// </summary>
|
||||
GitHub,
|
||||
|
||||
/// <summary>
|
||||
/// Remote provider is GitLab.com
|
||||
/// </summary>
|
||||
GitLab,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
#pragma warning disable CA1506
|
||||
#pragma warning disable CA1506, CA1508
|
||||
public async Task DeploymentProcess(
|
||||
Models.Job job,
|
||||
IDatabaseContextFactory databaseContextFactory,
|
||||
@@ -714,7 +714,7 @@ namespace Tgstation.Server.Host.Components.Deployment
|
||||
deploying = false;
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1506
|
||||
#pragma warning restore CA1506, CA1508
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the average length of a deployment using a given <paramref name="databaseContext"/>.
|
||||
|
||||
@@ -132,6 +132,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly IFileTransferTicketProvider fileTransferService;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IGitRemoteFeaturesFactory"/> for the <see cref="InstanceFactory"/>.
|
||||
/// </summary>
|
||||
readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="GeneralConfiguration"/> for the <see cref="InstanceFactory"/>.
|
||||
/// </summary>
|
||||
@@ -161,6 +166,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="repositoryCommands">The value of <see cref="repositoryCommands"/>.</param>
|
||||
/// <param name="serverPortProvider">The value of <see cref="serverPortProvider"/>.</param>
|
||||
/// <param name="fileTransferService">The value of <see cref="fileTransferService"/>.</param>
|
||||
/// <param name="gitRemoteFeaturesFactory">The value of <see cref="gitRemoteFeaturesFactory"/>.</param>
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
|
||||
public InstanceFactory(
|
||||
IIOManager ioManager,
|
||||
@@ -184,6 +190,7 @@ namespace Tgstation.Server.Host.Components
|
||||
ILibGit2Commands repositoryCommands,
|
||||
IServerPortProvider serverPortProvider,
|
||||
IFileTransferTicketProvider fileTransferService,
|
||||
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
|
||||
IOptions<GeneralConfiguration> generalConfigurationOptions)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
@@ -207,6 +214,7 @@ namespace Tgstation.Server.Host.Components
|
||||
this.repositoryCommands = repositoryCommands ?? throw new ArgumentNullException(nameof(repositoryCommands));
|
||||
this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
|
||||
this.fileTransferService = fileTransferService ?? throw new ArgumentNullException(nameof(fileTransferService));
|
||||
this.gitRemoteFeaturesFactory = gitRemoteFeaturesFactory ?? throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory));
|
||||
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
|
||||
}
|
||||
|
||||
@@ -239,6 +247,7 @@ namespace Tgstation.Server.Host.Components
|
||||
repositoryCommands,
|
||||
repoIoManager,
|
||||
eventConsumer,
|
||||
gitRemoteFeaturesFactory,
|
||||
loggerFactory.CreateLogger<Repository.Repository>(),
|
||||
loggerFactory.CreateLogger<RepositoryManager>());
|
||||
try
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
@@ -8,7 +11,10 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
sealed class DefaultGitRemoteFeatures : IGitRemoteFeatures
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string TestMergeRefSpecFormatter => null;
|
||||
public string TestMergeRefSpecFormatter => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public string TestMergeLocalBranchNameFormatter => throw new NotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public RemoteGitProvider? RemoteGitProvider => Api.Models.RemoteGitProvider.Unknown;
|
||||
@@ -18,5 +24,11 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RemoteRepositoryName => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Models.TestMerge> GetTestMerge(
|
||||
TestMergeParameters parameters,
|
||||
Api.Models.Internal.RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,117 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Octokit;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// GitHub <see cref="IGitRemoteFeatures"/>.
|
||||
/// </summary>
|
||||
sealed class GitHubRemoteFeatures : IGitRemoteFeatures
|
||||
sealed class GitHubRemoteFeatures : GitRemoteFeaturesBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string TestMergeRefSpecFormatter => "pull/{0}/head:{1}";
|
||||
public override string TestMergeRefSpecFormatter => "pull/{0}/head:{1}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public RemoteGitProvider? RemoteGitProvider => Api.Models.RemoteGitProvider.GitHub;
|
||||
public override string TestMergeLocalBranchNameFormatter => "pull/{0}/headrefs/heads/{1}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RemoteRepositoryOwner { get; }
|
||||
public override RemoteGitProvider? RemoteGitProvider => Api.Models.RemoteGitProvider.GitHub;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RemoteRepositoryName { get; }
|
||||
public override string RemoteRepositoryOwner { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string RemoteRepositoryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IGitHubClientFactory"/> for the <see cref="GitHubRemoteFeatures"/>.
|
||||
/// </summary>
|
||||
readonly IGitHubClientFactory gitHubClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GitHubRemoteFeatures"/> <see langword="class"/>.
|
||||
/// </summary>
|
||||
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GitRemoteFeaturesBase"/>.</param>
|
||||
/// <param name="remoteUrl">The remote repository <see cref="Uri"/>.</param>
|
||||
public GitHubRemoteFeatures(Uri remoteUrl)
|
||||
public GitHubRemoteFeatures(IGitHubClientFactory gitHubClientFactory, ILogger<GitHubRemoteFeatures> logger, Uri remoteUrl)
|
||||
: base(logger, remoteUrl)
|
||||
{
|
||||
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
||||
|
||||
if (remoteUrl == null)
|
||||
throw new ArgumentNullException(nameof(remoteUrl));
|
||||
|
||||
RemoteRepositoryOwner = remoteUrl.Segments[1].TrimEnd('/');
|
||||
RemoteRepositoryName = remoteUrl.Segments[2].TrimEnd('/');
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<Models.TestMerge> GetTestMergeImpl(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var gitHubClient = repositorySettings.AccessToken != null
|
||||
? gitHubClientFactory.CreateClient(repositorySettings.AccessToken)
|
||||
: gitHubClientFactory.CreateClient();
|
||||
|
||||
PullRequest pr = null;
|
||||
ApiException exception = null;
|
||||
string errorMessage = null;
|
||||
try
|
||||
{
|
||||
pr = await gitHubClient
|
||||
.PullRequest
|
||||
.Get(RemoteRepositoryOwner, RemoteRepositoryName, parameters.Number)
|
||||
.WithToken(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (RateLimitExceededException ex)
|
||||
{
|
||||
// you look at your anonymous access and sigh
|
||||
errorMessage = "GITHUB API ERROR: RATE LIMITED";
|
||||
exception = ex;
|
||||
}
|
||||
catch (AuthorizationException ex)
|
||||
{
|
||||
errorMessage = "GITHUB API ERROR: BAD CREDENTIALS";
|
||||
exception = ex;
|
||||
}
|
||||
catch (NotFoundException ex)
|
||||
{
|
||||
// you look at your shithub and sigh
|
||||
errorMessage = "GITHUB API ERROR: PULL REQUEST NOT FOUND";
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
Logger.LogWarning(exception, "Error retrieving pull request metadata!");
|
||||
|
||||
var revisionToUse = parameters.PullRequestRevision == null
|
||||
|| pr?.Head.Sha.StartsWith(parameters.PullRequestRevision, StringComparison.OrdinalIgnoreCase) == true
|
||||
? pr?.Head.Sha
|
||||
: parameters.PullRequestRevision;
|
||||
|
||||
var testMerge = new Models.TestMerge
|
||||
{
|
||||
Author = pr?.User.Login ?? errorMessage,
|
||||
BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,
|
||||
TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,
|
||||
Comment = parameters.Comment,
|
||||
Number = parameters.Number,
|
||||
PullRequestRevision = revisionToUse,
|
||||
Url = pr?.HtmlUrl ?? errorMessage
|
||||
};
|
||||
|
||||
return testMerge;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using GitLabApiClient;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// GitLab <see cref="IGitRemoteFeatures"/>.
|
||||
/// </summary>
|
||||
sealed class GitLabRemoteFeatures : GitRemoteFeaturesBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string TestMergeRefSpecFormatter => "merge-requests/{0}/head:{1}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string TestMergeLocalBranchNameFormatter => "merge-requests/{0}/headrefs/heads/{1}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override RemoteGitProvider? RemoteGitProvider => Api.Models.RemoteGitProvider.GitLab;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string RemoteRepositoryOwner { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string RemoteRepositoryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GitLabRemoteFeatures"/> <see langword="class"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GitRemoteFeaturesBase"/>.</param>
|
||||
/// <param name="remoteUrl">The remote repository <see cref="Uri"/>.</param>
|
||||
public GitLabRemoteFeatures(ILogger<GitLabRemoteFeatures> logger, Uri remoteUrl)
|
||||
: base(logger, remoteUrl)
|
||||
{
|
||||
RemoteRepositoryOwner = remoteUrl.Segments[1].TrimEnd('/');
|
||||
RemoteRepositoryName = remoteUrl.Segments[2].TrimEnd('/');
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<Models.TestMerge> GetTestMergeImpl(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
const string GitLabUrl = "https://gitlab.com";
|
||||
|
||||
var client = repositorySettings.AccessToken != null
|
||||
? new GitLabClient(GitLabUrl, repositorySettings.AccessToken)
|
||||
: new GitLabClient(GitLabUrl);
|
||||
|
||||
try
|
||||
{
|
||||
var mr = await client
|
||||
.MergeRequests
|
||||
.GetAsync($"{RemoteRepositoryOwner}/{RemoteRepositoryName}", parameters.Number)
|
||||
.WithToken(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var revisionToUse = parameters.PullRequestRevision == null
|
||||
|| mr.Sha.StartsWith(parameters.PullRequestRevision, StringComparison.OrdinalIgnoreCase)
|
||||
? mr.Sha
|
||||
: parameters.PullRequestRevision;
|
||||
|
||||
return new Models.TestMerge
|
||||
{
|
||||
Author = mr.Author.Username,
|
||||
BodyAtMerge = mr.Description,
|
||||
TitleAtMerge = mr.Title,
|
||||
Comment = parameters.Comment,
|
||||
Number = parameters.Number,
|
||||
PullRequestRevision = mr.Sha,
|
||||
Url = mr.WebUrl
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Error retrieving merge request metadata!");
|
||||
|
||||
return new Models.TestMerge
|
||||
{
|
||||
Author = ex.Message,
|
||||
BodyAtMerge = ex.Message,
|
||||
TitleAtMerge = ex.Message,
|
||||
Comment = parameters.Comment,
|
||||
Number = parameters.Number,
|
||||
PullRequestRevision = parameters.PullRequestRevision,
|
||||
Url = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Base <see langword="class"/> for implementing <see cref="IGitRemoteFeatures"/>.
|
||||
/// </summary>
|
||||
abstract class GitRemoteFeaturesBase : IGitRemoteFeatures
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public abstract string TestMergeRefSpecFormatter { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string TestMergeLocalBranchNameFormatter { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract RemoteGitProvider? RemoteGitProvider { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string RemoteRepositoryOwner { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string RemoteRepositoryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="GitRemoteFeaturesBase"/>.
|
||||
/// </summary>
|
||||
protected ILogger<GitRemoteFeaturesBase> Logger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Cache of created <see cref="Models.TestMerge"/>s.
|
||||
/// </summary>
|
||||
readonly Dictionary<TestMergeParameters, Models.TestMerge> cachedLookups;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GitRemoteFeaturesBase"/> <see langword="class"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">The value of <see cref="Logger"/>.</param>
|
||||
/// <param name="remoteUrl">The remote repository <see cref="Uri"/>.</param>
|
||||
public GitRemoteFeaturesBase(ILogger<GitRemoteFeaturesBase> logger, Uri remoteUrl)
|
||||
{
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
if (remoteUrl == null)
|
||||
throw new ArgumentNullException(nameof(remoteUrl));
|
||||
|
||||
cachedLookups = new Dictionary<TestMergeParameters, Models.TestMerge>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Models.TestMerge> GetTestMerge(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException(nameof(parameters));
|
||||
if (repositorySettings == null)
|
||||
throw new ArgumentNullException(nameof(repositorySettings));
|
||||
|
||||
Models.TestMerge result;
|
||||
lock (cachedLookups)
|
||||
if (cachedLookups.TryGetValue(parameters, out result))
|
||||
Logger.LogTrace("Using cache for test merge #{0}", parameters.Number);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
Logger.LogTrace("Retrieving metadata for test merge #{0}...", parameters.Number);
|
||||
result = await GetTestMergeImpl(parameters, repositorySettings, cancellationToken).ConfigureAwait(false);
|
||||
lock (cachedLookups)
|
||||
if (!cachedLookups.TryAdd(parameters, result))
|
||||
Logger.LogError("Race condition on adding test merge #{0}!", parameters.Number);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="GetTestMerge(TestMergeParameters, RepositorySettings, CancellationToken)"/>
|
||||
/// </summary>
|
||||
/// <param name="parameters">The <see cref="TestMergeParameters"/>.</param>
|
||||
/// <param name="repositorySettings">The <see cref="RepositorySettings"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="Models.TestMerge"/> of the <paramref name="parameters"/>.</returns>
|
||||
protected abstract Task<Models.TestMerge> GetTestMergeImpl(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class GitRemoteFeaturesFactory : IGitRemoteFeaturesFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IGitHubClientFactory"/> for the <see cref="GitRemoteFeaturesFactory"/>.
|
||||
/// </summary>
|
||||
readonly IGitHubClientFactory gitHubClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILoggerFactory"/> for the <see cref="GitRemoteFeaturesFactory"/>.
|
||||
/// </summary>
|
||||
readonly ILoggerFactory loggerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="GitRemoteFeaturesFactory"/>.
|
||||
/// </summary>
|
||||
readonly ILogger<GitRemoteFeaturesFactory> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GitRemoteFeaturesFactory"/> <see langword="class"/>.
|
||||
/// </summary>
|
||||
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
|
||||
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
public GitRemoteFeaturesFactory(
|
||||
IGitHubClientFactory gitHubClientFactory,
|
||||
ILoggerFactory loggerFactory,
|
||||
ILogger<GitRemoteFeaturesFactory> logger)
|
||||
{
|
||||
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
||||
this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IGitRemoteFeatures CreateGitRemoteFeatures(IRepository repository)
|
||||
{
|
||||
if (repository == null)
|
||||
throw new ArgumentNullException(nameof(repository));
|
||||
|
||||
var primaryRemote = repository.Origin;
|
||||
try
|
||||
{
|
||||
var primaryRemoteUrl = new Uri(primaryRemote);
|
||||
|
||||
switch (primaryRemoteUrl.Host.ToUpperInvariant())
|
||||
{
|
||||
case "GITHUB.COM":
|
||||
case "WWW.GITHUB.COM":
|
||||
case "GIT.GITHUB.COM":
|
||||
return new GitHubRemoteFeatures(
|
||||
gitHubClientFactory,
|
||||
loggerFactory.CreateLogger<GitHubRemoteFeatures>(),
|
||||
primaryRemoteUrl);
|
||||
case "GITLAB.COM":
|
||||
case "WWW.GITLAB.COM":
|
||||
case "GIT.GITLAB.COM":
|
||||
return new GitLabRemoteFeatures(
|
||||
loggerFactory.CreateLogger<GitLabRemoteFeatures>(),
|
||||
primaryRemoteUrl);
|
||||
default:
|
||||
logger.LogTrace("Unknown git remote: {0}", primaryRemoteUrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "Error parsing remote git provider.");
|
||||
}
|
||||
|
||||
return new DefaultGitRemoteFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Additional information from git remotes.
|
||||
/// </summary>
|
||||
public interface IGitRemoteAdditionalInformation : IGitRemoteInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve the <see cref="Models.TestMerge"/> representation of given test merge <paramref name="parameters"/>.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The <see cref="TestMergeParameters"/>.</param>
|
||||
/// <param name="repositorySettings">The <see cref="RepositorySettings"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="Models.TestMerge"/> of the <paramref name="parameters"/>.</returns>
|
||||
Task<Models.TestMerge> GetTestMerge(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides features for remote git services
|
||||
/// </summary>
|
||||
interface IGitRemoteFeatures : IGitRemoteInformation
|
||||
interface IGitRemoteFeatures : IGitRemoteAdditionalInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a formatter string which creates the remote refspec for fetching the HEAD of passed in pull request number.
|
||||
/// </summary>
|
||||
string TestMergeRefSpecFormatter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get
|
||||
/// </summary>
|
||||
string TestMergeLocalBranchNameFormatter { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for creating <see cref="IGitRemoteFeatures"/>.
|
||||
/// </summary>
|
||||
interface IGitRemoteFeaturesFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the <see cref="IGitRemoteFeatures"/> for a given <paramref name="repository"/>.
|
||||
/// </summary>
|
||||
/// <param name="repository">The <see cref="IRepository"/> to create <see cref="IGitRemoteFeatures"/> for.</param>
|
||||
/// <returns>A new <see cref="IGitRemoteFeatures"/> instance.</returns>
|
||||
IGitRemoteFeatures CreateGitRemoteFeatures(IRepository repository);
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,8 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// </summary>
|
||||
/// <param name="path">The full path to the <see cref="LibGit2Sharp.IRepository"/>.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in a <see cref="Tuple{T1, T2}"/> containing the loaded <see cref="LibGit2Sharp.IRepository"/> and the associated <see cref="IGitRemoteFeatures"/>.</returns>
|
||||
Task<Tuple<LibGit2Sharp.IRepository, IGitRemoteFeatures>> CreateFromPath(string path, CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the loaded <see cref="LibGit2Sharp.IRepository"/>.</returns>
|
||||
Task<LibGit2Sharp.IRepository> CreateFromPath(string path, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Clone a remote <see cref="LibGit2Sharp.IRepository"/>.
|
||||
|
||||
@@ -2,14 +2,13 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an on-disk git repository
|
||||
/// </summary>
|
||||
public interface IRepository : IGitRemoteInformation, IDisposable
|
||||
public interface IRepository : IGitRemoteAdditionalInformation, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// If <see cref="Reference"/> tracks an upstream branch
|
||||
|
||||
@@ -2,7 +2,6 @@ using LibGit2Sharp;
|
||||
using LibGit2Sharp.Handlers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
@@ -36,7 +35,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Tuple<LibGit2Sharp.IRepository, IGitRemoteFeatures>> CreateFromPath(string path, CancellationToken cancellationToken)
|
||||
public async Task<LibGit2Sharp.IRepository> CreateFromPath(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
@@ -52,42 +51,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
TaskScheduler.Current)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
var remoteFeatures = CreateGitRemoteFeatures(repo);
|
||||
return Tuple.Create(repo, remoteFeatures);
|
||||
}
|
||||
catch
|
||||
{
|
||||
repo.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
IGitRemoteFeatures CreateGitRemoteFeatures(LibGit2Sharp.IRepository repo)
|
||||
{
|
||||
var primaryRemote = repo.Network.Remotes.First();
|
||||
var primaryRemoteUrl = new Uri(primaryRemote.Url);
|
||||
|
||||
try
|
||||
{
|
||||
switch (primaryRemoteUrl.Host.ToUpperInvariant())
|
||||
{
|
||||
case "GITHUB.COM":
|
||||
case "WWW.GITHUB.COM":
|
||||
case "GIT.GITHUB.COM":
|
||||
return new GitHubRemoteFeatures(primaryRemoteUrl);
|
||||
default:
|
||||
logger.LogTrace("Unknown git remote: {0}", primaryRemoteUrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "Error parsing remote git provider.");
|
||||
}
|
||||
|
||||
return new DefaultGitRemoteFeatures();
|
||||
return repo;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Components.Events;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
@@ -123,7 +124,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <param name="ioMananger">The value of <see cref="ioMananger"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="credentialsProvider">The value of <see cref="credentialsProvider"/></param>
|
||||
/// <param name="gitRemoteFeatures">The value of <see cref="gitRemoteFeatures"/>.</param>
|
||||
/// <param name="gitRemoteFeaturesFactory">The <see cref="IGitRemoteFeaturesFactory"/> to provide the value of <see cref="gitRemoteFeatures"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
/// <param name="onDispose">The value if <see cref="onDispose"/></param>
|
||||
public Repository(
|
||||
@@ -132,7 +133,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
IIOManager ioMananger,
|
||||
IEventConsumer eventConsumer,
|
||||
ICredentialsProvider credentialsProvider,
|
||||
IGitRemoteFeatures gitRemoteFeatures,
|
||||
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
|
||||
ILogger<Repository> logger,
|
||||
Action onDispose)
|
||||
{
|
||||
@@ -141,9 +142,13 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
this.ioMananger = ioMananger ?? throw new ArgumentNullException(nameof(ioMananger));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
|
||||
this.gitRemoteFeatures = gitRemoteFeatures ?? throw new ArgumentNullException(nameof(gitRemoteFeatures));
|
||||
if (gitRemoteFeaturesFactory == null)
|
||||
throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory));
|
||||
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
|
||||
|
||||
gitRemoteFeatures = gitRemoteFeaturesFactory.CreateGitRemoteFeatures(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -299,7 +304,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
testMergeParameters.Comment ?? String.Empty);
|
||||
|
||||
var prBranchName = String.Format(CultureInfo.InvariantCulture, "pr-{0}", testMergeParameters.Number);
|
||||
var localBranchName = String.Format(CultureInfo.InvariantCulture, "pull/{0}/headrefs/heads/{1}", testMergeParameters.Number, prBranchName);
|
||||
var localBranchName = String.Format(CultureInfo.InvariantCulture, gitRemoteFeatures.TestMergeLocalBranchNameFormatter, testMergeParameters.Number, prBranchName);
|
||||
|
||||
var refSpec = String.Format(CultureInfo.InvariantCulture, gitRemoteFeatures.TestMergeRefSpecFormatter, testMergeParameters.Number, prBranchName);
|
||||
var refSpecList = new List<string> { refSpec };
|
||||
@@ -774,5 +779,14 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
|
||||
return false;
|
||||
}, cancellationToken, DefaultIOManager.BlockingTaskCreationOptions, TaskScheduler.Current);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<Models.TestMerge> GetTestMerge(
|
||||
TestMergeParameters parameters,
|
||||
RepositorySettings repositorySettings,
|
||||
CancellationToken cancellationToken) => gitRemoteFeatures.GetTestMerge(
|
||||
parameters,
|
||||
repositorySettings,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// </summary>
|
||||
readonly IEventConsumer eventConsumer;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IGitRemoteFeaturesFactory"/> for the <see cref="RepositoryManager"/>
|
||||
/// </summary>
|
||||
readonly IGitRemoteFeaturesFactory gitRemoteFeaturesFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> created <see cref="Repository"/>s
|
||||
/// </summary>
|
||||
@@ -62,6 +67,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <param name="commands">The value of <see cref="commands"/>.</param>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="gitRemoteFeaturesFactory">The value of <see cref="gitRemoteFeaturesFactory"/>.</param>
|
||||
/// <param name="repositoryLogger">The value of <see cref="repositoryLogger"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public RepositoryManager(
|
||||
@@ -69,6 +75,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
ILibGit2Commands commands,
|
||||
IIOManager ioManager,
|
||||
IEventConsumer eventConsumer,
|
||||
IGitRemoteFeaturesFactory gitRemoteFeaturesFactory,
|
||||
ILogger<Repository> repositoryLogger,
|
||||
ILogger<RepositoryManager> logger)
|
||||
{
|
||||
@@ -76,6 +83,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
this.commands = commands ?? throw new ArgumentNullException(nameof(commands));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.gitRemoteFeaturesFactory = gitRemoteFeaturesFactory ?? throw new ArgumentNullException(nameof(gitRemoteFeaturesFactory));
|
||||
this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
semaphore = new SemaphoreSlim(1);
|
||||
@@ -188,32 +196,21 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
try
|
||||
{
|
||||
var repoTuple = await repositoryFactory.CreateFromPath(ioManager.ResolvePath(), cancellationToken).ConfigureAwait(false);
|
||||
var libGit2Repo = await repositoryFactory.CreateFromPath(ioManager.ResolvePath(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
var libGit2Repo = repoTuple.Item1;
|
||||
var gitRemoteFeatures = repoTuple.Item2;
|
||||
|
||||
return new Repository(
|
||||
libGit2Repo,
|
||||
commands,
|
||||
ioManager,
|
||||
eventConsumer,
|
||||
repositoryFactory,
|
||||
gitRemoteFeatures,
|
||||
repositoryLogger,
|
||||
() =>
|
||||
{
|
||||
logger.LogTrace("Releasing semaphore due to Repository disposal...");
|
||||
semaphore.Release();
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
repoTuple.Item1.Dispose();
|
||||
throw;
|
||||
}
|
||||
return new Repository(
|
||||
libGit2Repo,
|
||||
commands,
|
||||
ioManager,
|
||||
eventConsumer,
|
||||
repositoryFactory,
|
||||
gitRemoteFeaturesFactory,
|
||||
repositoryLogger,
|
||||
() =>
|
||||
{
|
||||
logger.LogTrace("Releasing semaphore due to Repository disposal...");
|
||||
semaphore.Release();
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@ using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.Database;
|
||||
using Tgstation.Server.Host.Extensions;
|
||||
using Tgstation.Server.Host.Jobs;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -644,7 +643,6 @@ namespace Tgstation.Server.Host.Controllers
|
||||
}
|
||||
|
||||
// test merging
|
||||
Dictionary<int, Octokit.PullRequest> prMap = null;
|
||||
if (newTestMerges)
|
||||
{
|
||||
if (repo.RemoteGitProvider == RemoteGitProvider.Unknown)
|
||||
@@ -666,10 +664,6 @@ namespace Tgstation.Server.Host.Controllers
|
||||
bool needToApplyRemainingPrs = true;
|
||||
if (lastRevisionInfo.OriginCommitSha == lastRevisionInfo.CommitSha)
|
||||
{
|
||||
// In order for this to work though we need the shas of all the commits
|
||||
if (model.NewTestMerges.Any(x => x.PullRequestRevision == null))
|
||||
prMap = new Dictionary<int, Octokit.PullRequest>();
|
||||
|
||||
bool cantSearch = false;
|
||||
foreach (var I in model.NewTestMerges)
|
||||
{
|
||||
@@ -681,11 +675,10 @@ namespace Tgstation.Server.Host.Controllers
|
||||
try
|
||||
{
|
||||
// retrieve the latest sha
|
||||
var pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number)
|
||||
.WithToken(ct)
|
||||
.ConfigureAwait(false);
|
||||
prMap.Add(I.Number, pr);
|
||||
I.PullRequestRevision = pr.Head.Sha;
|
||||
var pr = await repo.GetTestMerge(I, currentModel, ct).ConfigureAwait(false);
|
||||
|
||||
// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it
|
||||
I.PullRequestRevision = pr.PullRequestRevision;
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -798,47 +791,10 @@ namespace Tgstation.Server.Host.Controllers
|
||||
{
|
||||
foreach (var I in model.NewTestMerges)
|
||||
{
|
||||
Octokit.PullRequest pr = null;
|
||||
string errorMessage = null;
|
||||
|
||||
if (lastRevisionInfo.ActiveTestMerges.Any(x => x.TestMerge.Number == I.Number))
|
||||
throw new JobException(ErrorCode.RepoDuplicateTestMerge);
|
||||
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
// load from cache if possible
|
||||
if (prMap == null || !prMap.TryGetValue(I.Number, out pr))
|
||||
pr = await gitHubClient
|
||||
.PullRequest
|
||||
.Get(repoOwner, repoName, I.Number)
|
||||
.WithToken(ct)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Octokit.RateLimitExceededException ex)
|
||||
{
|
||||
// you look at your anonymous access and sigh
|
||||
errorMessage = "REMOTE API ERROR: RATE LIMITED";
|
||||
exception = ex;
|
||||
}
|
||||
catch (Octokit.AuthorizationException ex)
|
||||
{
|
||||
errorMessage = "REMOTE API ERROR: BAD CREDENTIALS";
|
||||
exception = ex;
|
||||
}
|
||||
catch (Octokit.NotFoundException ex)
|
||||
{
|
||||
// you look at your shithub and sigh
|
||||
errorMessage = "REMOTE API ERROR: PULL REQUEST NOT FOUND";
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
Logger.LogWarning(exception, "Error retrieving pull request metadata!");
|
||||
|
||||
// we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it
|
||||
if (I.PullRequestRevision == null && pr != null)
|
||||
I.PullRequestRevision = pr.Head.Sha;
|
||||
var fullTestMergeTask = repo.GetTestMerge(I, currentModel, ct);
|
||||
|
||||
var mergeResult = await repo.AddTestMerge(
|
||||
I,
|
||||
@@ -849,28 +805,38 @@ namespace Tgstation.Server.Host.Controllers
|
||||
NextProgressReporter(),
|
||||
ct).ConfigureAwait(false);
|
||||
|
||||
if (!mergeResult.HasValue)
|
||||
if (mergeResult == null)
|
||||
throw new JobException(
|
||||
ErrorCode.RepoTestMergeConflict,
|
||||
new JobException(
|
||||
$"Merge of PR #{I.Number} at {I.PullRequestRevision.Substring(0, 7)} conflicted!"));
|
||||
|
||||
++doneSteps;
|
||||
Models.TestMerge fullTestMerge;
|
||||
try
|
||||
{
|
||||
fullTestMerge = await fullTestMergeTask.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning("Error retrieving metadata for test merge #{0}!", I.Number);
|
||||
|
||||
fullTestMerge = new Models.TestMerge
|
||||
{
|
||||
Author = ex.Message,
|
||||
BodyAtMerge = ex.Message,
|
||||
MergedAt = DateTimeOffset.Now,
|
||||
TitleAtMerge = ex.Message,
|
||||
Comment = I.Comment,
|
||||
Number = I.Number,
|
||||
PullRequestRevision = I.PullRequestRevision,
|
||||
Url = ex.Message
|
||||
};
|
||||
}
|
||||
|
||||
// MergedBy will be set later
|
||||
var tm = new Models.TestMerge
|
||||
{
|
||||
Author = pr?.User.Login ?? errorMessage,
|
||||
BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,
|
||||
MergedAt = DateTimeOffset.Now,
|
||||
TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,
|
||||
Comment = I.Comment,
|
||||
Number = I.Number,
|
||||
PullRequestRevision = I.PullRequestRevision,
|
||||
Url = pr?.HtmlUrl ?? errorMessage
|
||||
};
|
||||
++doneSteps;
|
||||
|
||||
await UpdateRevInfo(tm).ConfigureAwait(false);
|
||||
await UpdateRevInfo(fullTestMerge).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,24 +306,23 @@ namespace Tgstation.Server.Host.Core
|
||||
services.AddSingleton<INetworkPromptReaper, PosixNetworkPromptReaper>();
|
||||
}
|
||||
|
||||
// configure misc services
|
||||
// configure component/misc services
|
||||
services.AddScoped<IPortAllocator, PortAllocator>();
|
||||
services.AddTransient<IActionResultExecutor<LimitedFileStreamResult>, LimitedFileStreamResultExecutor>();
|
||||
services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
|
||||
services.AddSingleton<IGitHubClientFactory, GitHubClientFactory>();
|
||||
services.AddSingleton<IProcessExecutor, ProcessExecutor>();
|
||||
services.AddSingleton<IServerPortProvider, ServerPortProivder>();
|
||||
services.AddSingleton<ITopicClientFactory, TopicClientFactory>();
|
||||
services.AddSingleton<FileTransferService>();
|
||||
services.AddSingleton<IFileTransferStreamHandler>(x => x.GetRequiredService<FileTransferService>());
|
||||
services.AddSingleton<IFileTransferTicketProvider>(x => x.GetRequiredService<FileTransferService>());
|
||||
|
||||
// configure component services
|
||||
services.AddSingleton<IInstanceFactory, InstanceFactory>();
|
||||
services.AddSingleton<IGitRemoteFeaturesFactory, GitRemoteFeaturesFactory>();
|
||||
services.AddSingleton<ILibGit2RepositoryFactory, LibGit2RepositoryFactory>();
|
||||
services.AddSingleton<ILibGit2Commands, LibGit2Commands>();
|
||||
services.AddSingleton<IProviderFactory, ProviderFactory>();
|
||||
services.AddSingleton<IChatManagerFactory, ChatManagerFactory>();
|
||||
services.AddSingleton<IInstanceFactory, InstanceFactory>();
|
||||
services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
|
||||
services.AddSingleton<FileTransferService>();
|
||||
services.AddSingleton<IFileTransferStreamHandler>(x => x.GetRequiredService<FileTransferService>());
|
||||
services.AddSingleton<IFileTransferTicketProvider>(x => x.GetRequiredService<FileTransferService>());
|
||||
|
||||
// configure root services
|
||||
services.AddSingleton<IJobManager, JobManager>();
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
#pragma warning disable CA1724 // naming conflict with gitlab package
|
||||
public sealed class Job : Api.Models.Internal.Job
|
||||
#pragma warning restore CA1724
|
||||
{
|
||||
/// <summary>
|
||||
/// See <see cref="Api.Models.Job.StartedBy"/>
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<PackageReference Include="Cyberboss.AspNetCore.AsyncInitializer" Version="1.2.0" />
|
||||
<PackageReference Include="Cyberboss.SmartIrc4net.Standard" Version="0.4.6" />
|
||||
<PackageReference Include="Discord.Net.WebSocket" Version="2.2.0" />
|
||||
<PackageReference Include="GitLabApiClient" Version="1.7.0" />
|
||||
<PackageReference Include="LibGit2Sharp" Version="0.27.0-preview-0034" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.10" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.10" />
|
||||
|
||||
@@ -20,8 +20,7 @@ namespace Tgstation.Server.Host.Components.Repository.Tests
|
||||
string path,
|
||||
ILibGit2RepositoryFactory repositoryFactory = null) =>
|
||||
(await (repositoryFactory ?? CreateFactory())
|
||||
.CreateFromPath(path, default))
|
||||
.Item1;
|
||||
.CreateFromPath(path, default));
|
||||
|
||||
[TestMethod]
|
||||
public void TestConstructionThrows() => Assert.ThrowsException<ArgumentNullException>(() => new LibGit2RepositoryFactory(null));
|
||||
|
||||
@@ -480,7 +480,7 @@ namespace Tgstation.Server.Tests
|
||||
Mock.Of<Host.IO.IIOManager>(),
|
||||
Mock.Of<IEventConsumer>(),
|
||||
Mock.Of<ICredentialsProvider>(),
|
||||
Mock.Of<IGitRemoteFeatures>(),
|
||||
Mock.Of<IGitRemoteFeaturesFactory>(),
|
||||
Mock.Of<ILogger<Host.Components.Repository.Repository>>(),
|
||||
() => { });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user