mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 15:07:03 +01:00
Repo controller create
This commit is contained in:
@@ -9,6 +9,18 @@ namespace Tgstation.Server.Api.Models.Internal
|
||||
[Model(RightsType.Repository, ReadRight = RepositoryRights.Read, RequiresInstance = true)]
|
||||
public class RepositorySettings
|
||||
{
|
||||
/// <summary>
|
||||
/// The origin URL. If <see langword="null"/>, the <see cref="Repository"/> does not exist
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = RepositoryRights.SetOrigin)]
|
||||
public string Origin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last commit recognized from <see cref="Origin"/>
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true)]
|
||||
public string LastOriginCommitSha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the committer
|
||||
/// </summary>
|
||||
|
||||
@@ -8,17 +8,11 @@ namespace Tgstation.Server.Api.Models
|
||||
/// </summary>
|
||||
public sealed class Repository : Internal.RepositorySettings
|
||||
{
|
||||
/// <summary>
|
||||
/// The origin URL. If <see langword="null"/>, the <see cref="Repository"/> does not exist
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = RepositoryRights.SetOrigin)]
|
||||
public string Origin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The commit HEAD points to
|
||||
/// </summary>
|
||||
[Permissions(WriteRight = RepositoryRights.SetSha)]
|
||||
public string NewRevision { get; set; }
|
||||
public string Sha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current <see cref="Models.RevisionInformation"/> for the <see cref="Repository"/>
|
||||
|
||||
@@ -4,10 +4,15 @@ namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class RevisionInformation : Internal.RevisionInformation
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="TestMerge"/>s active in the <see cref="RevisionInformation"/>
|
||||
/// </summary>
|
||||
public List<TestMerge> TestMerges { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CompileJob"/>s made from the <see cref="RevisionInformation"/>
|
||||
/// </summary>
|
||||
public List<CompileJob> CompileJobs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -33,7 +34,7 @@ namespace Tgstation.Server.Host.Components
|
||||
|
||||
/// <inheritdoc />
|
||||
public StaticFiles.IConfiguration Configuration { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ICompileJobConsumer"/> for the <see cref="Instance"/>
|
||||
/// </summary>
|
||||
@@ -49,6 +50,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly IDmbFactory dmbFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="Instance"/>
|
||||
/// </summary>
|
||||
readonly ILogger<Instance> logger;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Api.Models.Instance"/> for the <see cref="Instance"/>
|
||||
/// </summary>
|
||||
@@ -76,7 +82,8 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="compileJobConsumer">The value of <see cref="compileJobConsumer"/></param>
|
||||
/// <param name="databaseContextFactory">The value of <see cref="databaseContextFactory"/></param>
|
||||
/// <param name="dmbFactory">The value of <see cref="dmbFactory"/></param>
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory)
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, ILogger<Instance> logger)
|
||||
{
|
||||
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
|
||||
RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
|
||||
@@ -88,6 +95,7 @@ namespace Tgstation.Server.Host.Components
|
||||
this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -109,9 +117,8 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
async Task TimerLoop(int minutes, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
while (true)
|
||||
try
|
||||
{
|
||||
await Task.Delay(new TimeSpan(0, minutes, 0), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -128,14 +135,31 @@ namespace Tgstation.Server.Host.Components
|
||||
});
|
||||
using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
await dbTask.ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await dbTask.ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Database error in auto update loop! Exception: {0}", e);
|
||||
continue;
|
||||
}
|
||||
if (repo == null)
|
||||
continue;
|
||||
await repo.FetchOrigin(accessToken, cancellationToken).ConfigureAwait(false);
|
||||
await repo.ResetToOrigin(cancellationToken).ConfigureAwait(false);
|
||||
var job = await DreamMaker.Compile(projectName, timeout, repo, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (OperationCanceledException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError("Error in auto update loop! Exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace Tgstation.Server.Host.Components
|
||||
var commandFactory = new CommandFactory(application);
|
||||
var chatFactory = new ChatFactory(instanceIoManager, loggerFactory, commandFactory, providerFactory);
|
||||
|
||||
var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager);
|
||||
var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager, eventConsumer);
|
||||
try
|
||||
{
|
||||
var byond = new ByondManager(byondIOManager, byondInstaller, loggerFactory.CreateLogger<ByondManager>());
|
||||
@@ -160,7 +160,7 @@ namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
var dreamMaker = new DreamMaker(byond, ioManager, configuration, sessionControllerFactory, dmbFactory, application, eventConsumer, loggerFactory.CreateLogger<DreamMaker>());
|
||||
|
||||
return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory);
|
||||
return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, loggerFactory.CreateLogger<Instance>());
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -13,16 +13,24 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// Attempt to load the <see cref="IRepository"/> from the default location
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>The loaded <see cref="IRepository"/></returns>
|
||||
/// <returns>The loaded <see cref="IRepository"/> if it exists, <see langword="null"/> otherwise</returns>
|
||||
Task<IRepository> LoadRepository(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Delete the current <see cref="IRepository"/> and replaces it with a clone of the repository at <paramref name="url"/>
|
||||
/// Clone the repository at <paramref name="url"/>
|
||||
/// </summary>
|
||||
/// <param name="url">The <see cref="Uri"/> of the remote repository to clone</param>
|
||||
/// <param name="initialBranch">The branch to clone</param>
|
||||
/// <param name="accessString">The access string to clone from <paramref name="url"/></param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>The newly cloned <see cref="IRepository"/></returns>
|
||||
Task<IRepository> CloneRepository(Uri url, string accessString, CancellationToken cancellationToken);
|
||||
Task<IRepository> CloneRepository(Uri url, string initialBranch, string accessString, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Delete the current repository
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task DeleteRepository(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models.Internal;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
@@ -15,6 +16,11 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IEventConsumer"/> for the <see cref="RepositoryManager"/>
|
||||
/// </summary>
|
||||
readonly IEventConsumer eventConsumer;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RepositorySettings"/> for the <see cref="RepositoryManager"/>
|
||||
/// </summary>
|
||||
@@ -30,10 +36,12 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// </summary>
|
||||
/// <param name="repositorySettings">The value of <see cref="repositorySettings"/></param>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
public RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager)
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
public RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer)
|
||||
{
|
||||
this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
semaphore = new SemaphoreSlim(1);
|
||||
}
|
||||
|
||||
@@ -41,28 +49,32 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
public void Dispose() => semaphore.Dispose();
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IRepository> CloneRepository(Uri url, string accessString, CancellationToken cancellationToken)
|
||||
public async Task<IRepository> CloneRepository(Uri url, string initialBranch, string accessString, CancellationToken cancellationToken)
|
||||
{
|
||||
await ioManager.DeleteDirectory(".", cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
string path = null;
|
||||
try
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
path = LibGit2Sharp.Repository.Clone(Repository.GenerateAuthUrl(url.ToString(), accessString), ioManager.ResolvePath("."), new CloneOptions
|
||||
{
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnTransferProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
RecurseSubmodules = true,
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested
|
||||
});
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
await DeleteRepository(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
string path = null;
|
||||
try
|
||||
{
|
||||
path = LibGit2Sharp.Repository.Clone(Repository.GenerateAuthUrl(url.ToString(), accessString), ioManager.ResolvePath("."), new CloneOptions
|
||||
{
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnTransferProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
RecurseSubmodules = true,
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
|
||||
BranchName = initialBranch
|
||||
});
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
}
|
||||
return await LoadRepository(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -73,14 +85,27 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
LibGit2Sharp.Repository repo = null;
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
repo = new LibGit2Sharp.Repository(ioManager.ResolvePath("."));
|
||||
try
|
||||
{
|
||||
repo = new LibGit2Sharp.Repository(ioManager.ResolvePath("."));
|
||||
}
|
||||
catch (RepositoryNotFoundException) { }
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
if (repo == null)
|
||||
return null;
|
||||
var localSemaphore = semaphore;
|
||||
return new Repository(repo, ioManager, () =>
|
||||
return new Repository(repo, ioManager, eventConsumer, () =>
|
||||
{
|
||||
localSemaphore?.Release();
|
||||
localSemaphore = null;
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task DeleteRepository(CancellationToken cancellationToken)
|
||||
{
|
||||
using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
await ioManager.DeleteDirectory(".", cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,11 @@ namespace Tgstation.Server.Host.Controllers
|
||||
Task<RevisionInformation> revInfoTask;
|
||||
using (var repo = await instance.RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
if (repo == null)
|
||||
{
|
||||
job.ExceptionDetails = "Missing repository!";
|
||||
return;
|
||||
}
|
||||
revInfoTask = databaseContext.RevisionInformations.Where(x => x.CommitSha == repo.Head).Select(x => new RevisionInformation { Id = x.Id }).FirstAsync();
|
||||
compileJob = await instance.DreamMaker.Compile(projectName, timeout.Value, repo, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Rights;
|
||||
using Tgstation.Server.Host.Components;
|
||||
using Tgstation.Server.Host.Models;
|
||||
using Tgstation.Server.Host.Security;
|
||||
@@ -9,8 +17,8 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// <summary>
|
||||
/// Controller for managing the <see cref="Api.Models.Repository"/>s
|
||||
/// </summary>
|
||||
[Route("/" + nameof(Api.Models.Repository))]
|
||||
public sealed class RepositoryController : ModelController<Api.Models.Repository>
|
||||
[Route("/" + nameof(Repository))]
|
||||
public sealed class RepositoryController : ModelController<Repository>
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IInstanceManager"/> for the <see cref="RepositoryController"/>
|
||||
@@ -22,10 +30,83 @@ namespace Tgstation.Server.Host.Controllers
|
||||
/// </summary>
|
||||
/// <param name="databaseContext">The <see cref="IDatabaseContext"/> for the <see cref="ApiController"/></param>
|
||||
/// <param name="authenticationContextFactory">The <see cref="IAuthenticationContextFactory"/> for the <see cref="ApiController"/></param>
|
||||
/// <param name="instanceMangaer">The value of <see cref="instanceMangaer"/></param>
|
||||
/// <param name="instanceManager">The value of <see cref="instanceManager"/></param>
|
||||
public RepositoryController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager) : base(databaseContext, authenticationContextFactory, true)
|
||||
{
|
||||
this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
|
||||
}
|
||||
|
||||
static string GetAccessString(Api.Models.Internal.RepositorySettings repositorySettings) => repositorySettings.AccessUser != null ? String.Concat(repositorySettings.AccessUser, '@', repositorySettings.AccessToken) : null;
|
||||
|
||||
async Task<bool> PopulateApi(Repository model, Components.Repository.IRepository repository, string lastOriginCommitSha, CancellationToken cancellationToken)
|
||||
{
|
||||
model.IsGitHub = repository.IsGitHubRepository;
|
||||
model.Origin = repository.Origin;
|
||||
model.Reference = repository.Reference;
|
||||
model.Sha = repository.Head;
|
||||
|
||||
//rev info stuff
|
||||
var revisionInfo = await DatabaseContext.RevisionInformations.Where(x => x.CommitSha == model.Sha)
|
||||
.Include(x => x.CompileJobs)
|
||||
.Include(x => x.TestMerges) //minimal info, they can query the rest if they're allowed
|
||||
.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false); //search every rev info because LOL SHA COLLISIONS
|
||||
|
||||
var needsDbUpdate = revisionInfo == default;
|
||||
if (needsDbUpdate)
|
||||
{
|
||||
//needs insertion
|
||||
revisionInfo = new Models.RevisionInformation
|
||||
{
|
||||
CommitSha = model.Sha,
|
||||
CompileJobs = new List<Models.CompileJob>(),
|
||||
TestMerges = new List<Models.TestMerge>(), //non null vals for api returns
|
||||
OriginCommitSha = lastOriginCommitSha ?? model.Sha
|
||||
};
|
||||
|
||||
DatabaseContext.RevisionInformations.Add(revisionInfo);
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
model.RevisionInformation = revisionInfo.ToApi();
|
||||
return needsDbUpdate;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[TgsAuthorize(RepositoryRights.SetOrigin)]
|
||||
public override async Task<IActionResult> Create([FromBody] Repository model, CancellationToken cancellationToken)
|
||||
{
|
||||
if (model == null)
|
||||
return BadRequest(new { message = "Missing request model!" });
|
||||
|
||||
if (model.Origin == null)
|
||||
return BadRequest(new { message = "Missing repo origin!" });
|
||||
|
||||
if (model.AccessUser == null ^ model.AccessToken == null)
|
||||
return BadRequest(new { message = "Either both accessToken and accessUser must be present or neither!" });
|
||||
|
||||
var currentModel = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.RepositorySettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (currentModel == default)
|
||||
return StatusCode((int)HttpStatusCode.Gone);
|
||||
|
||||
|
||||
currentModel.AccessToken = model.AccessToken;
|
||||
currentModel.AccessUser = model.AccessUser;
|
||||
currentModel.Origin = model.Origin; //intentionally only these fields, user not allowed to change anything else atm
|
||||
var cloneBranch = model.Reference;
|
||||
|
||||
var repoManager = instanceManager.GetInstance(Instance).RepositoryManager;
|
||||
using (var repo = await repoManager.CloneRepository(new Uri(currentModel.Origin), cloneBranch, GetAccessString(currentModel), cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
if (repo == null)
|
||||
//clone conflict
|
||||
return Conflict();
|
||||
var api = currentModel.ToApi();
|
||||
await PopulateApi(api, repo, null, cancellationToken).ConfigureAwait(false);
|
||||
currentModel.LastOriginCommitSha = repo.Head;
|
||||
await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
return Json(api);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Tgstation.Server.Api.Models;
|
||||
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class RepositorySettings : Api.Models.Internal.RepositorySettings
|
||||
public sealed class RepositorySettings : Api.Models.Internal.RepositorySettings, IApiConvertable<Repository>
|
||||
{
|
||||
/// <summary>
|
||||
/// The row Id
|
||||
@@ -20,5 +21,19 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Instance Instance { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Repository ToApi() => new Repository {
|
||||
AccessToken = AccessToken,
|
||||
AccessUser = AccessUser,
|
||||
AutoUpdatesKeepTestMerges = AutoUpdatesKeepTestMerges,
|
||||
AutoUpdatesSynchronize = AutoUpdatesSynchronize,
|
||||
CommitterEmail = CommitterEmail,
|
||||
CommitterName = CommitterName,
|
||||
//intentionally don't populate origin just in case
|
||||
PushTestMergeCommits = PushTestMergeCommits,
|
||||
//revision information and the rest retrieved by controller
|
||||
ShowTestMergeCommitters = ShowTestMergeCommitters
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
CommitSha = CommitSha,
|
||||
OriginCommitSha = OriginCommitSha,
|
||||
TestMerges = TestMerges.Select(x => x.ToApi()).ToList()
|
||||
TestMerges = TestMerges.Select(x => x.ToApi()).ToList(),
|
||||
CompileJobs = CompileJobs.Select(x => x.ToApi()).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user