Merge pull request #1104 from tgstation/1089-DeploymentsButGitHubThisTime

GitHub Deployments
This commit is contained in:
Jordan Brown
2020-08-13 14:23:03 -04:00
committed by GitHub
33 changed files with 3941 additions and 76 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
[![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](http://forthebadge.com)
This is a toolset to manage production BYOND servers. It includes the ability to update the server without having to stop or shutdown the server (the update will take effect on a "reboot" of the server) the ability start the server and restart it if it crashes, as well as systems for managing code and game files, and merging GitHub Pull Requests for test deployments.
This is a toolset to manage production BYOND servers. It includes the ability to update the server without having to stop or shutdown the server, (the update will take effect on a "reboot" of the server) the ability to start the server and restart it if it crashes, as well as systems for managing code and game files, and merging GitHub Pull Requests for test deployments.
### Legacy Servers
+2 -2
View File
@@ -2,9 +2,9 @@
<PropertyGroup>
<!-- This is the authorative version list -->
<!-- Integration tests will ensure they match across the board -->
<TgsCoreVersion>4.4.5</TgsCoreVersion>
<TgsCoreVersion>4.5.0</TgsCoreVersion>
<TgsConfigVersion>2.0.0</TgsConfigVersion>
<TgsApiVersion>7.2.3</TgsApiVersion>
<TgsApiVersion>7.3.0</TgsApiVersion>
<TgsClientVersion>8.2.0</TgsClientVersion>
<TgsDmapiVersion>5.2.3</TgsDmapiVersion>
<TgsControlPanelVersion>0.4.0</TgsControlPanelVersion>
@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Api.Models.Internal
{
@@ -35,11 +35,17 @@ namespace Tgstation.Server.Api.Models.Internal
public string? AccessToken { get; set; }
/// <summary>
/// If commits created from testmerges are pushed to the remote
/// If commits created from testmerges are pushed to the remote. Requires <see cref="AccessUser"/> and <see cref="AccessToken"/> to be set to function.
/// </summary>
[Required]
public bool? PushTestMergeCommits { get; set; }
/// <summary>
/// If GitHub deployments should be created. Requires <see cref="AccessUser"/>, <see cref="AccessToken"/>, and <see cref="PushTestMergeCommits"/> to be set to function.
/// </summary>
[Required]
public bool? CreateGitHubDeployments { get; set; }
/// <summary>
/// If test merge commits are signed with the username of the person who merged it. Note this only affects future commits
/// </summary>
@@ -53,13 +59,13 @@ namespace Tgstation.Server.Api.Models.Internal
public bool? AutoUpdatesKeepTestMerges { get; set; }
/// <summary>
/// If synchronization should occur when auto updating
/// If synchronization should occur when auto updating. Requries <see cref="AccessUser"/> and <see cref="AccessToken"/> to be set to function.
/// </summary>
[Required]
public bool? AutoUpdatesSynchronize { get; set; }
/// <summary>
/// If test merging should create a comment
/// If test merging should create a comment. Requires <see cref="AccessToken"/> to be set to function.
/// </summary>
[Required]
public bool? PostTestMergeComment { get; set; }
@@ -1,4 +1,4 @@
using System;
using System;
namespace Tgstation.Server.Api.Rights
{
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Api.Rights
None = 0,
/// <summary>
/// User may cancel synchronize operations
/// User may cancel update operations.
/// </summary>
CancelPendingChanges = 1,
@@ -44,7 +44,7 @@ namespace Tgstation.Server.Api.Rights
ChangeCommitter = 32,
/// <summary>
/// User may change <see cref="Models.Internal.RepositorySettings.PushTestMergeCommits"/> and <see cref="Models.Internal.RepositorySettings.PostTestMergeComment"/>
/// User may change <see cref="Models.Internal.RepositorySettings.PushTestMergeCommits"/>, <see cref="Models.Internal.RepositorySettings.PostTestMergeComment"/>, and <see cref="Models.Internal.RepositorySettings.CreateGitHubDeployments"/>.
/// </summary>
ChangeTestMergeCommits = 64,
@@ -40,6 +40,11 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
readonly IIOManager ioManager;
/// <summary>
/// The <see cref="IGitHubDeploymentManager"/> for the <see cref="DmbFactory"/>.
/// </summary>
readonly IGitHubDeploymentManager gitHubDeploymentManager;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="DmbFactory"/>
/// </summary>
@@ -75,17 +80,29 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
IDmbProvider nextDmbProvider;
/// <summary>
/// If the <see cref="DmbFactory"/> is "started" via <see cref="Microsoft.Extensions.Hosting.IHostedService"/>.
/// </summary>
bool started;
/// <summary>
/// Construct a <see cref="DmbFactory"/>
/// </summary>
/// <param name="databaseContextFactory">The value of <see cref="databaseContextFactory"/></param>
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
/// <param name="gitHubDeploymentManager">The value of <see cref="gitHubDeploymentManager"/>.</param>
/// <param name="logger">The value of <see cref="logger"/></param>
/// <param name="instance">The value of <see cref="instance"/></param>
public DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger<DmbFactory> logger, Api.Models.Instance instance)
public DmbFactory(
IDatabaseContextFactory databaseContextFactory,
IIOManager ioManager,
IGitHubDeploymentManager gitHubDeploymentManager,
ILogger<DmbFactory> logger,
Api.Models.Instance instance)
{
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.gitHubDeploymentManager = gitHubDeploymentManager ?? throw new ArgumentNullException(nameof(gitHubDeploymentManager));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
@@ -107,11 +124,11 @@ namespace Tgstation.Server.Host.Components.Deployment
async Task HandleCleanup()
{
var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
Task otherTask;
// lock (this) //already locked below
otherTask = cleanupTask;
await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
// DCT: None available
var deploymentJob = gitHubDeploymentManager.MarkInactive(job, default);
var otherTask = cleanupTask;
await Task.WhenAll(otherTask, deleteJob, deploymentJob).ConfigureAwait(false);
}
lock (jobLockCounts)
@@ -137,6 +154,14 @@ namespace Tgstation.Server.Host.Components.Deployment
var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
if (newProvider == null)
return;
// Do this first, because it's entirely possible when we set the tcs it will immediately need to be applied
if (started)
await gitHubDeploymentManager.StageDeployment(
newProvider.CompileJob,
cancellationToken)
.ConfigureAwait(false);
lock (jobLockCounts)
{
nextDmbProvider?.Dispose();
@@ -184,6 +209,7 @@ namespace Tgstation.Server.Host.Components.Deployment
if (cj == default(CompileJob))
return;
await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false);
started = true;
// we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet
}
@@ -191,8 +217,15 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <inheritdoc />
public async Task StopAsync(CancellationToken cancellationToken)
{
using (cancellationToken.Register(() => cleanupCts.Cancel()))
await cleanupTask.ConfigureAwait(false);
try
{
using (cancellationToken.Register(() => cleanupCts.Cancel()))
await cleanupTask.ConfigureAwait(false);
}
finally
{
started = false;
}
}
/// <inheritdoc />
@@ -88,6 +88,11 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
readonly ICompileJobSink compileJobConsumer;
/// <summary>
/// The <see cref="IGitHubDeploymentManager"/> for <see cref="DreamMaker"/>.
/// </summary>
readonly IGitHubDeploymentManager gitHubDeploymentManager;
/// <summary>
/// The <see cref="ILogger"/> for <see cref="DreamMaker"/>
/// </summary>
@@ -112,6 +117,16 @@ namespace Tgstation.Server.Host.Components.Deployment
/// </summary>
bool deploying;
/// <summary>
/// Format a given <see cref="Exception"/> for display to users.
/// </summary>
/// <param name="exception">The <see cref="Exception"/> to format.</param>
/// <returns>An error <see cref="string"/> for end users.</returns>
static string FormatExceptionForUsers(Exception exception)
=> exception is OperationCanceledException
? "The job was cancelled!"
: exception.Message;
/// <summary>
/// Construct <see cref="DreamMaker"/>
/// </summary>
@@ -125,6 +140,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
/// <param name="compileJobConsumer">The value of <see cref="compileJobConsumer"/>.</param>
/// <param name="repositoryManager">The value of <see cref="repositoryManager"/>.</param>
/// <param name="gitHubDeploymentManager">The value of <see cref="gitHubDeploymentManager"/>.</param>
/// <param name="logger">The value of <see cref="logger"/></param>
/// <param name="metadata">The value of <see cref="metadata"/>.</param>
public DreamMaker(
@@ -138,6 +154,7 @@ namespace Tgstation.Server.Host.Components.Deployment
IGitHubClientFactory gitHubClientFactory,
ICompileJobSink compileJobConsumer,
IRepositoryManager repositoryManager,
IGitHubDeploymentManager gitHubDeploymentManager,
ILogger<DreamMaker> logger,
Api.Models.Instance metadata)
{
@@ -151,6 +168,7 @@ namespace Tgstation.Server.Host.Components.Deployment
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
this.gitHubDeploymentManager = gitHubDeploymentManager ?? throw new ArgumentNullException(nameof(gitHubDeploymentManager));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
@@ -345,22 +363,36 @@ namespace Tgstation.Server.Host.Components.Deployment
}
/// <summary>
/// Cleans up a failed compile <paramref name="job"/>
/// Cleans up a failed compile <paramref name="job"/>.
/// </summary>
/// <param name="job">The running <see cref="CompileJob"/></param>
/// <param name="job">The running <see cref="CompileJob"/>.</param>
/// <param name="exception">The <see cref="Exception"/> that was thrown.</param>
/// <returns>A <see cref="Task"/> representing the running operation</returns>
async Task CleanupFailedCompile(Models.CompileJob job)
async Task CleanupFailedCompile(Models.CompileJob job, Exception exception)
{
logger.LogTrace("Cleaning compile directory...");
var jobPath = job.DirectoryName.ToString();
try
async Task CleanDir()
{
await ioManager.DeleteDirectory(jobPath, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception e)
{
logger.LogWarning(e, "Error cleaning up compile directory {0}!", ioManager.ResolvePath(jobPath));
logger.LogTrace("Cleaning compile directory...");
var jobPath = job.DirectoryName.ToString();
try
{
// DCT: None available
await ioManager.DeleteDirectory(jobPath, default).ConfigureAwait(false);
}
catch (Exception e)
{
logger.LogWarning(e, "Error cleaning up compile directory {0}!", ioManager.ResolvePath(jobPath));
}
}
// DCT: None available
await Task.WhenAll(
CleanDir(),
gitHubDeploymentManager.FailDeployment(
job,
FormatExceptionForUsers(exception),
default))
.ConfigureAwait(false);
}
/// <summary>
@@ -461,9 +493,9 @@ namespace Tgstation.Server.Host.Components.Deployment
logger.LogDebug("Compile complete!");
}
catch
catch (Exception ex)
{
await CleanupFailedCompile(job).ConfigureAwait(false);
await CleanupFailedCompile(job, ex).ConfigureAwait(false);
throw;
}
}
@@ -651,14 +683,14 @@ namespace Tgstation.Server.Host.Components.Deployment
})
.ConfigureAwait(false);
}
catch
catch (Exception ex)
{
await CleanupFailedCompile(compileJob).ConfigureAwait(false);
await CleanupFailedCompile(compileJob, ex).ConfigureAwait(false);
throw;
}
var commentsTask = PostDeploymentComments(
revInfo,
compileJob,
activeCompileJob?.RevisionInformation,
repositorySettings,
repoOwner,
@@ -683,9 +715,7 @@ namespace Tgstation.Server.Host.Components.Deployment
{
if (currentChatCallback != null)
await currentChatCallback(
ex is OperationCanceledException
? "The job was cancelled!"
: ex.Message,
FormatExceptionForUsers(ex),
currentDreamMakerOutput)
.ConfigureAwait(false);
@@ -767,6 +797,12 @@ namespace Tgstation.Server.Host.Components.Deployment
ByondVersion = byondLock.Version.ToString()
};
await gitHubDeploymentManager.StartDeployment(
repository,
job,
cancellationToken)
.ConfigureAwait(false);
await RunCompileJob(job, dreamMakerSettings, byondLock, repository, apiValidateTimeout, cancellationToken).ConfigureAwait(false);
return job;
@@ -787,7 +823,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <summary>
/// Post deployment GitHub comments.
/// </summary>
/// <param name="deployedRevisionInformation">The deployed <see cref="RevisionInformation"/>.</param>
/// <param name="compileJob">The deployed <see cref="CompileJob"/>.</param>
/// <param name="previousRevisionInformation">The <see cref="RevisionInformation"/> of the previous deployment.</param>
/// <param name="repositorySettings">The <see cref="RepositorySettings"/>.</param>
/// <param name="repoOwner">The GitHub repostiory owner.</param>
@@ -795,7 +831,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
async Task PostDeploymentComments(
Models.RevisionInformation deployedRevisionInformation,
Models.CompileJob compileJob,
Models.RevisionInformation previousRevisionInformation,
Models.RepositorySettings repositorySettings,
string repoOwner,
@@ -832,7 +868,8 @@ namespace Tgstation.Server.Host.Components.Deployment
var tasks = new List<Task>();
string FormatTestMerge(Models.TestMerge testMerge, bool updated) => String.Format(CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}",
var deployedRevisionInformation = compileJob.RevisionInformation;
string FormatTestMerge(Models.TestMerge testMerge, bool updated) => String.Format(CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}{8}",
Environment.NewLine,
repositorySettings.ShowTestMergeCommitters.Value ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty,
testMerge.PullRequestRevision,
@@ -840,7 +877,10 @@ namespace Tgstation.Server.Host.Components.Deployment
updated ? "Updated" : "Deployed",
metadata.Name,
deployedRevisionInformation.OriginCommitSha,
deployedRevisionInformation.CommitSha);
deployedRevisionInformation.CommitSha,
compileJob.GitHubDeploymentId.HasValue
? $"{Environment.NewLine}[GitHub Deployments](https://github.com/{repoOwner}/{repoName}/deployments/activity_log?environment=TGS%3A%20{metadata.Name})"
: String.Empty);
// added prs
foreach (var I in deployedRevisionInformation
@@ -853,8 +893,8 @@ namespace Tgstation.Server.Host.Components.Deployment
// removed prs
foreach (var I in previousRevisionInformation
.ActiveTestMerges
.Select(x => x.TestMerge)
.ActiveTestMerges
.Select(x => x.TestMerge)
.Where(x => !deployedRevisionInformation
.ActiveTestMerges
.Any(y => y.TestMerge.Number == x.Number)))
@@ -0,0 +1,243 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Octokit;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Components.Repository;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.Extensions;
using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Components.Deployment
{
/// <inheritdoc />
sealed class GitHubDeploymentManager : IGitHubDeploymentManager
{
/// <summary>
/// The <see cref="IDatabaseContextFactory"/> for the <see cref="GitHubDeploymentManager"/>.
/// </summary>
readonly IDatabaseContextFactory databaseContextFactory;
/// <summary>
/// The <see cref="IGitHubClientFactory"/> for the <see cref="GitHubDeploymentManager"/>.
/// </summary>
readonly IGitHubClientFactory gitHubClientFactory;
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="GitHubDeploymentManager"/>.
/// </summary>
readonly ILogger<GitHubDeploymentManager> logger;
/// <summary>
/// The <see cref="Models.Instance"/> for the <see cref="GitHubDeploymentManager"/>.
/// </summary>
readonly Api.Models.Instance metadata;
/// <summary>
/// Initializes a new instance of the <see cref="GitHubDeploymentManager"/> <see langword="class"/>.
/// </summary>
/// <param name="databaseContextFactory">The value of <see cref="databaseContextFactory"/>.</param>
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
/// <param name="metadata">The value of <see cref="metadata"/>.</param>
public GitHubDeploymentManager(
IDatabaseContextFactory databaseContextFactory,
IGitHubClientFactory gitHubClientFactory,
ILogger<GitHubDeploymentManager> logger,
Api.Models.Instance metadata)
{
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
}
/// <inheritdoc />
public async Task StartDeployment(IRepository repository, CompileJob compileJob, CancellationToken cancellationToken)
{
if (repository == null)
throw new ArgumentNullException(nameof(repository));
if (compileJob == null)
throw new ArgumentNullException(nameof(compileJob));
if (!repository.IsGitHubRepository)
{
logger.LogTrace("Not managing deployment as this is not a GitHub repo");
return;
}
logger.LogTrace("Starting deployment...");
RepositorySettings repositorySettings = null;
await databaseContextFactory.UseContext(
async databaseContext =>
repositorySettings = await databaseContext
.RepositorySettings
.AsQueryable()
.Where(x => x.InstanceId == metadata.Id)
.FirstAsync(cancellationToken)
.ConfigureAwait(false))
.ConfigureAwait(false);
var gitHubClient = repositorySettings.AccessToken == null
? gitHubClientFactory.CreateClient()
: gitHubClientFactory.CreateClient(repositorySettings.AccessToken);
var repositoryTask = gitHubClient
.Repository
.Get(
repository.GitHubOwner,
repository.GitHubRepoName);
if (repositorySettings.CreateGitHubDeployments.Value)
{
logger.LogTrace("Creating deployment...");
var deployment = await gitHubClient
.Repository
.Deployment
.Create(
repository.GitHubOwner,
repository.GitHubRepoName,
new NewDeployment(compileJob.RevisionInformation.CommitSha)
{
AutoMerge = false,
Description = "TGS Game Deployment",
Environment = $"TGS: {metadata.Name}",
ProductionEnvironment = true,
RequiredContexts = new Collection<string>()
})
.WithToken(cancellationToken)
.ConfigureAwait(false);
compileJob.GitHubDeploymentId = deployment.Id;
logger.LogDebug("Created deployment ID {0}", deployment.Id);
await gitHubClient
.Repository
.Deployment
.Status
.Create(
repository.GitHubOwner,
repository.GitHubRepoName,
deployment.Id,
new NewDeploymentStatus(DeploymentState.InProgress)
{
Description = "The project is being deployed",
AutoInactive = false
})
.WithToken(cancellationToken)
.ConfigureAwait(false);
logger.LogTrace("In-progress deployment status created");
}
else
logger.LogTrace("Not creating deployment");
try
{
var gitHubRepo = await repositoryTask
.WithToken(cancellationToken)
.ConfigureAwait(false);
compileJob.GitHubRepoId = gitHubRepo.Id;
logger.LogTrace("Set GitHub ID as {0}", compileJob.GitHubRepoId);
}
catch (RateLimitExceededException ex) when (!repositorySettings.CreateGitHubDeployments.Value)
{
logger.LogWarning(ex, "Unable to set compile job repository ID!");
}
}
async Task UpdateDeployment(
CompileJob compileJob,
string description,
DeploymentState deploymentState,
CancellationToken cancellationToken)
{
if (compileJob == null)
throw new ArgumentNullException(nameof(compileJob));
if (!compileJob.GitHubRepoId.HasValue || !compileJob.GitHubDeploymentId.HasValue)
{
logger.LogTrace("Not updating deployment as it is missing a repo ID or deployment ID.");
return;
}
logger.LogTrace("Updating deployment {0} to {1}...", compileJob.GitHubDeploymentId.Value, deploymentState);
string gitHubAccessToken = null;
await databaseContextFactory.UseContext(
async databaseContext =>
gitHubAccessToken = await databaseContext
.RepositorySettings
.AsQueryable()
.Where(x => x.InstanceId == metadata.Id)
.Select(x => x.AccessToken)
.FirstAsync(cancellationToken)
.ConfigureAwait(false))
.ConfigureAwait(false);
if (gitHubAccessToken == null)
{
logger.LogWarning(
"GitHub access token disappeared during deployment, can't update to {0}!",
deploymentState);
return;
}
var gitHubClient = gitHubClientFactory.CreateClient(gitHubAccessToken);
await gitHubClient
.Repository
.Deployment
.Status
.Create(
compileJob.GitHubRepoId.Value,
compileJob.GitHubDeploymentId.Value,
new NewDeploymentStatus(deploymentState)
{
Description = description
})
.WithToken(cancellationToken)
.ConfigureAwait(false);
}
/// <inheritdoc />
public Task StageDeployment(
CompileJob compileJob,
CancellationToken cancellationToken)
=> UpdateDeployment(
compileJob,
"The deployment succeeded and will be applied a the next server reboot.",
DeploymentState.Pending,
cancellationToken);
/// <inheritdoc />
public Task ApplyDeployment(CompileJob compileJob, CompileJob oldCompileJob, CancellationToken cancellationToken)
=> UpdateDeployment(
compileJob,
"The deployment is now live on the server.",
DeploymentState.Success,
cancellationToken);
/// <inheritdoc />
public Task FailDeployment(CompileJob compileJob, string errorMessage, CancellationToken cancellationToken)
=> UpdateDeployment(
compileJob,
errorMessage,
DeploymentState.Error,
cancellationToken);
/// <inheritdoc />
public Task MarkInactive(CompileJob compileJob, CancellationToken cancellationToken)
=> UpdateDeployment(
compileJob,
"The deployment has been superceeded.",
DeploymentState.Inactive,
cancellationToken);
}
}
@@ -0,0 +1,58 @@
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Components.Repository;
using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Components.Deployment
{
/// <summary>
/// Creates and updates GitHub deployments.
/// </summary>
interface IGitHubDeploymentManager
{
/// <summary>
/// Start a deployment for a given <paramref name="compileJob"/>.
/// </summary>
/// <param name="repository">The <see cref="IRepository"/> being deployed.</param>
/// <param name="compileJob">The active <see cref="CompileJob"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task StartDeployment(IRepository repository, CompileJob compileJob, CancellationToken cancellationToken);
/// <summary>
/// Stage a given <paramref name="compileJob"/>'s deployment.
/// </summary>
/// <param name="compileJob">The staged <see cref="CompileJob"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task StageDeployment(
CompileJob compileJob,
CancellationToken cancellationToken);
/// <summary>
/// Stage a given <paramref name="compileJob"/>'s deployment.
/// </summary>
/// <param name="compileJob">The <see cref="CompileJob"/> being applied.</param>
/// <param name="oldCompileJob">The currently active <see cref="CompileJob"/>, if any.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task ApplyDeployment(CompileJob compileJob, CompileJob oldCompileJob, CancellationToken cancellationToken);
/// <summary>
/// Fail a deployment for a given <paramref name="compileJob"/>.
/// </summary>
/// <param name="compileJob">The failed <see cref="CompileJob"/>.</param>
/// <param name="errorMessage">The error message.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task FailDeployment(CompileJob compileJob, string errorMessage, CancellationToken cancellationToken);
/// <summary>
/// Mark the deplotment for a given <paramref name="compileJob"/> as inactive.
/// </summary>
/// <param name="compileJob">The inactive <see cref="CompileJob"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
Task MarkInactive(CompileJob compileJob, CancellationToken cancellationToken);
}
}
@@ -248,7 +248,18 @@ namespace Tgstation.Server.Host.Components
loggerFactory.CreateLogger<SessionControllerFactory>(),
metadata.CloneMetadata());
var dmbFactory = new DmbFactory(databaseContextFactory, gameIoManager, loggerFactory.CreateLogger<DmbFactory>(), metadata.CloneMetadata());
var gitHubDeploymentManager = new GitHubDeploymentManager(
databaseContextFactory,
gitHubClientFactory,
loggerFactory.CreateLogger<GitHubDeploymentManager>(),
metadata.CloneMetadata());
var dmbFactory = new DmbFactory(
databaseContextFactory,
gameIoManager,
gitHubDeploymentManager,
loggerFactory.CreateLogger<DmbFactory>(),
metadata.CloneMetadata());
try
{
var reattachInfoHandler = new SessionPersistor(
@@ -265,6 +276,7 @@ namespace Tgstation.Server.Host.Components
gameIoManager,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
metadata.CloneMetadata(),
metadata.DreamDaemonSettings);
eventConsumer.SetWatchdog(watchdog);
@@ -283,6 +295,7 @@ namespace Tgstation.Server.Host.Components
gitHubClientFactory,
dmbFactory,
repoManager,
gitHubDeploymentManager,
loggerFactory.CreateLogger<DreamMaker>(),
metadata.CloneMetadata());
@@ -47,6 +47,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gitHubDeploymentManager">The <see cref="IGitHubDeploymentManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="initialLaunchParameters">The <see cref="DreamDaemonLaunchParameters"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="instance">The <see cref="Api.Models.Instance"/> for the <see cref="WatchdogBase"/>.</param>
@@ -61,6 +62,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IAsyncDelayer asyncDelayer,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
ILogger<BasicWatchdog> logger,
DreamDaemonLaunchParameters initialLaunchParameters,
Api.Models.Instance instance,
@@ -75,6 +77,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
asyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
logger,
initialLaunchParameters,
instance,
@@ -123,7 +126,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
switch (rebootState)
{
case Session.RebootState.Normal:
return HandleNormalReboot();
return await HandleNormalReboot(cancellationToken).ConfigureAwait(false);
case Session.RebootState.Restart:
return MonitorAction.Restart;
case Session.RebootState.Shutdown:
@@ -187,6 +190,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
if (!reattachInProgress)
{
dmbToUse = await PrepServerForLaunch(dmbToUse, cancellationToken).ConfigureAwait(false);
await BeforeApplyDmb(dmbToUse.CompileJob, cancellationToken).ConfigureAwait(false);
serverLaunchTask = SessionControllerFactory.LaunchNew(
dmbToUse,
null,
@@ -236,11 +240,13 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <summary>
/// Handler for <see cref="MonitorActivationReason.ActiveServerRebooted"/> when the <see cref="RebootState"/> is <see cref="RebootState.Normal"/>.
/// </summary>
/// <returns>The <see cref="MonitorAction"/> to take.</returns>
protected virtual MonitorAction HandleNormalReboot()
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="MonitorAction"/> to take.</returns>
protected virtual Task<MonitorAction> HandleNormalReboot(CancellationToken cancellationToken)
{
bool dmbUpdatePending = ActiveLaunchParameters != LastLaunchParameters;
return dmbUpdatePending ? MonitorAction.Restart : MonitorAction.Continue;
var settingsUpdatePending = ActiveLaunchParameters != LastLaunchParameters;
var result = settingsUpdatePending ? MonitorAction.Restart : MonitorAction.Continue;
return Task.FromResult(result);
}
/// <summary>
@@ -1,4 +1,4 @@
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Deployment;
using Tgstation.Server.Host.Components.Events;
@@ -22,6 +22,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="gameIOManager">The <see cref="IIOManager"/> pointing to the Game directory for the <see cref="IWatchdog"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> pointing to the Diagnostics directory for the <see cref="IWatchdog"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="IWatchdog"/>.</param>
/// <param name="gitHubDeploymentManager">The <see cref="IGitHubDeploymentManager"/> for the <see cref="IWatchdog"/>.</param>
/// <param name="instance">The <see cref="Instance"/> for the <see cref="IWatchdog"/></param>
/// <param name="settings">The initial <see cref="DreamDaemonSettings"/> for the <see cref="IWatchdog"/></param>
/// <returns>A new <see cref="IWatchdog"/></returns>
@@ -33,6 +34,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IIOManager gameIOManager,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
Api.Models.Instance instance,
DreamDaemonSettings settings);
}
@@ -34,6 +34,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gitHubDeploymentManager">The <see cref="IGitHubDeploymentManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gameIOManager">The <see cref="IIOManager"/> pointing to the game directory for the <see cref="WindowsWatchdog"/>..</param>
/// <param name="symlinkFactory">The <see cref="ISymlinkFactory"/> for the <see cref="WindowsWatchdog"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
@@ -50,6 +51,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IAsyncDelayer asyncDelayer,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
IIOManager gameIOManager,
ISymlinkFactory symlinkFactory,
ILogger<PosixWatchdog> logger,
@@ -66,6 +68,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
asyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
gameIOManager,
symlinkFactory,
logger,
@@ -52,6 +52,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IIOManager gameIOManager,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
Api.Models.Instance instance,
DreamDaemonSettings settings)
=> new PosixWatchdog(
@@ -64,6 +65,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
AsyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
gameIOManager,
SymlinkFactory,
LoggerFactory.CreateLogger<PosixWatchdog>(),
@@ -60,7 +60,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <summary>
/// The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.
/// </summary>
protected ILogger Logger { get; }
protected ILogger<WatchdogBase> Logger { get; }
/// <summary>
/// The <see cref="IChatManager"/> for the <see cref="WatchdogBase"/>
@@ -122,6 +122,11 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// </summary>
readonly IEventConsumer eventConsumer;
/// <summary>
/// The <see cref="IGitHubDeploymentManager"/> for the <see cref="WatchdogBase"/>.
/// </summary>
readonly IGitHubDeploymentManager gitHubDeploymentManager;
/// <summary>
/// If the <see cref="WatchdogBase"/> should <see cref="LaunchNoLock(bool, bool, bool, ReattachInformation, CancellationToken)"/> in <see cref="StartAsync(CancellationToken)"/>
/// </summary>
@@ -174,6 +179,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="asyncDelayer">The value of <see cref="AsyncDelayer"/>.</param>
/// <param name="diagnosticsIOManager">The value of <see cref="diagnosticsIOManager"/>.</param>
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/>.</param>
/// <param name="gitHubDeploymentManager">The value of <see cref="gitHubDeploymentManager"/>.</param>
/// <param name="logger">The value of <see cref="Logger"/></param>
/// <param name="initialLaunchParameters">The initial value of <see cref="ActiveLaunchParameters"/>. May be modified</param>
/// <param name="instance">The value of <see cref="instance"/></param>
@@ -188,7 +194,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
IAsyncDelayer asyncDelayer,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
ILogger logger,
IGitHubDeploymentManager gitHubDeploymentManager,
ILogger<WatchdogBase> logger,
DreamDaemonLaunchParameters initialLaunchParameters,
Api.Models.Instance instance,
bool autoStart)
@@ -201,6 +208,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
AsyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
this.diagnosticsIOManager = diagnosticsIOManager ?? throw new ArgumentNullException(nameof(diagnosticsIOManager));
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
this.gitHubDeploymentManager = gitHubDeploymentManager ?? throw new ArgumentNullException(nameof(gitHubDeploymentManager));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
ActiveLaunchParameters = initialLaunchParameters ?? throw new ArgumentNullException(nameof(initialLaunchParameters));
this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
@@ -520,6 +528,23 @@ namespace Tgstation.Server.Host.Components.Watchdog
MonitorActivationReason activationReason,
CancellationToken cancellationToken);
/// <summary>
/// To be called before a given <paramref name="newCompileJob"/> goes live.
/// </summary>
/// <param name="newCompileJob">The new <see cref="Models.CompileJob"/> being applied.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
protected Task BeforeApplyDmb(Models.CompileJob newCompileJob, CancellationToken cancellationToken)
{
if (newCompileJob.Id == ActiveCompileJob?.Id)
{
Logger.LogTrace("Same compile job, not sending deployment event");
return Task.CompletedTask;
}
return gitHubDeploymentManager.ApplyDeployment(newCompileJob, ActiveCompileJob, cancellationToken);
}
/// <summary>
/// Attempt to restart the monitor from scratch.
/// </summary>
@@ -528,6 +553,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
private async Task MonitorRestart(CancellationToken cancellationToken)
{
Logger.LogTrace("Monitor restart!");
await DisposeAndNullControllers(cancellationToken).ConfigureAwait(false);
var chatTask = Task.CompletedTask;
@@ -72,6 +72,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IIOManager gameIOManager,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
Api.Models.Instance instance,
DreamDaemonSettings settings)
=> new BasicWatchdog(
@@ -84,6 +85,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
AsyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
LoggerFactory.CreateLogger<BasicWatchdog>(),
settings,
instance,
@@ -55,6 +55,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
/// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="diagnosticsIOManager">The <see cref="IIOManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="eventConsumer">The <see cref="IEventConsumer"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gitHubDeploymentManager">The <see cref="IGitHubDeploymentManager"/> for the <see cref="WatchdogBase"/>.</param>
/// <param name="gameIOManager">The value of <see cref="GameIOManager"/>.</param>
/// <param name="symlinkFactory">The value of <see cref="symlinkFactory"/>.</param>
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="WatchdogBase"/>.</param>
@@ -71,6 +72,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IAsyncDelayer asyncDelayer,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
IIOManager gameIOManager,
ISymlinkFactory symlinkFactory,
ILogger<WindowsWatchdog> logger,
@@ -86,6 +88,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
asyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
logger,
initialLaunchParameters,
instance,
@@ -118,14 +121,17 @@ namespace Tgstation.Server.Host.Components.Watchdog
}
/// <inheritdoc />
protected override MonitorAction HandleNormalReboot()
protected override async Task<MonitorAction> HandleNormalReboot(CancellationToken cancellationToken)
{
if (pendingSwappable != null)
{
var updateTask = BeforeApplyDmb(pendingSwappable.CompileJob, cancellationToken);
Logger.LogTrace("Replacing activeSwappable with pendingSwappable...");
Server.ReplaceDmbProvider(pendingSwappable);
ActiveSwappable = pendingSwappable;
pendingSwappable = null;
await updateTask.ConfigureAwait(false);
}
else
Logger.LogTrace("Nothing to do as pendingSwappable is null.");
@@ -58,6 +58,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
IIOManager gameIOManager,
IIOManager diagnosticsIOManager,
IEventConsumer eventConsumer,
IGitHubDeploymentManager gitHubDeploymentManager,
Api.Models.Instance instance,
DreamDaemonSettings settings)
=> new WindowsWatchdog(
@@ -70,6 +71,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
AsyncDelayer,
diagnosticsIOManager,
eventConsumer,
gitHubDeploymentManager,
gameIOManager,
SymlinkFactory,
LoggerFactory.CreateLogger<WindowsWatchdog>(),
@@ -132,7 +132,8 @@ namespace Tgstation.Server.Host.Controllers
ShowTestMergeCommitters = false,
AutoUpdatesKeepTestMerges = false,
AutoUpdatesSynchronize = false,
PostTestMergeComment = false
PostTestMergeComment = false,
CreateGitHubDeployments = false
},
InstanceUsers = new List<Models.InstanceUser> // give this user full privileges on the instance
{
@@ -420,6 +420,7 @@ namespace Tgstation.Server.Host.Controllers
|| CheckModified(x => x.CommitterEmail, RepositoryRights.ChangeCommitter)
|| CheckModified(x => x.CommitterName, RepositoryRights.ChangeCommitter)
|| CheckModified(x => x.PushTestMergeCommits, RepositoryRights.ChangeTestMergeCommits)
|| CheckModified(x => x.CreateGitHubDeployments, RepositoryRights.ChangeTestMergeCommits)
|| CheckModified(x => x.ShowTestMergeCommitters, RepositoryRights.ChangeTestMergeCommits)
|| CheckModified(x => x.PostTestMergeComment, RepositoryRights.ChangeTestMergeCommits)
|| (model.UpdateFromOrigin == true && !userRights.HasFlag(RepositoryRights.UpdateBranch)))
@@ -0,0 +1,781 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20200807213255_MSAddDeploymentColumns")]
partial class MSAddDeploymentColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ChannelLimit")
.HasColumnType("int");
b.Property<string>("ConnectionString")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("Enabled")
.HasColumnType("bit");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(100)")
.HasMaxLength(100);
b.Property<int>("Provider")
.HasColumnType("int");
b.Property<long>("ReconnectionInterval")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId", "Name")
.IsUnique();
b.ToTable("ChatBots");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<long>("ChatSettingsId")
.HasColumnType("bigint");
b.Property<decimal?>("DiscordChannelId")
.HasColumnType("decimal(20,0)");
b.Property<string>("IrcChannel")
.HasColumnType("nvarchar(100)")
.HasMaxLength(100);
b.Property<bool?>("IsAdminChannel")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("IsUpdatesChannel")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("IsWatchdogChannel")
.IsRequired()
.HasColumnType("bit");
b.Property<string>("Tag")
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.HasKey("Id");
b.HasIndex("ChatSettingsId", "DiscordChannelId")
.IsUnique()
.HasFilter("[DiscordChannelId] IS NOT NULL");
b.HasIndex("ChatSettingsId", "IrcChannel")
.IsUnique()
.HasFilter("[IrcChannel] IS NOT NULL");
b.ToTable("ChatChannels");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ByondVersion")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("DMApiMajorVersion")
.HasColumnType("int");
b.Property<int?>("DMApiMinorVersion")
.HasColumnType("int");
b.Property<int?>("DMApiPatchVersion")
.HasColumnType("int");
b.Property<Guid?>("DirectoryName")
.IsRequired()
.HasColumnType("uniqueidentifier");
b.Property<string>("DmeName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("int");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<int?>("MinimumSecurityLevel")
.HasColumnType("int");
b.Property<string>("Output")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("DirectoryName");
b.HasIndex("JobId")
.IsUnique();
b.HasIndex("RevisionInformationId");
b.ToTable("CompileJobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<bool?>("AllowWebClient")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("AutoStart")
.IsRequired()
.HasColumnType("bit");
b.Property<long>("HeartbeatSeconds")
.HasColumnType("bigint");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<int>("Port")
.HasColumnType("int");
b.Property<int>("SecurityLevel")
.HasColumnType("int");
b.Property<long>("StartupTimeout")
.HasColumnType("bigint");
b.Property<long>("TopicRequestTimeout")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamDaemonSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiValidationPort")
.HasColumnType("int");
b.Property<int>("ApiValidationSecurityLevel")
.HasColumnType("int");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("ProjectName")
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("RequireDMApiValidation")
.IsRequired()
.HasColumnType("bit");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamMakerSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<long>("AutoUpdateInterval")
.HasColumnType("bigint");
b.Property<int>("ChatBotLimit")
.HasColumnType("int");
b.Property<int>("ConfigurationType")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("Online")
.IsRequired()
.HasColumnType("bit");
b.Property<string>("Path")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("Path")
.IsUnique();
b.ToTable("Instances");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<decimal>("ByondRights")
.HasColumnType("decimal(20,0)");
b.Property<decimal>("ChatBotRights")
.HasColumnType("decimal(20,0)");
b.Property<decimal>("ConfigurationRights")
.HasColumnType("decimal(20,0)");
b.Property<decimal>("DreamDaemonRights")
.HasColumnType("decimal(20,0)");
b.Property<decimal>("DreamMakerRights")
.HasColumnType("decimal(20,0)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<decimal>("InstanceUserRights")
.HasColumnType("decimal(20,0)");
b.Property<decimal>("RepositoryRights")
.HasColumnType("decimal(20,0)");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId");
b.HasIndex("UserId", "InstanceId")
.IsUnique();
b.ToTable("InstanceUsers");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<decimal?>("CancelRight")
.HasColumnType("decimal(20,0)");
b.Property<decimal?>("CancelRightsType")
.HasColumnType("decimal(20,0)");
b.Property<bool?>("Cancelled")
.IsRequired()
.HasColumnType("bit");
b.Property<long?>("CancelledById")
.HasColumnType("bigint");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long?>("ErrorCode")
.HasColumnType("bigint");
b.Property<string>("ExceptionDetails")
.HasColumnType("nvarchar(max)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StartedAt")
.IsRequired()
.HasColumnType("datetimeoffset");
b.Property<long>("StartedById")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StoppedAt")
.HasColumnType("datetimeoffset");
b.HasKey("Id");
b.HasIndex("CancelledById");
b.HasIndex("InstanceId");
b.HasIndex("StartedById");
b.ToTable("Jobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("AccessIdentifier")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<long>("CompileJobId")
.HasColumnType("bigint");
b.Property<int>("LaunchSecurityLevel")
.HasColumnType("int");
b.Property<int>("Port")
.HasColumnType("int");
b.Property<int>("ProcessId")
.HasColumnType("int");
b.Property<int>("RebootState")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CompileJobId");
b.ToTable("ReattachInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("AccessToken")
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<string>("AccessUser")
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("AutoUpdatesKeepTestMerges")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("AutoUpdatesSynchronize")
.IsRequired()
.HasColumnType("bit");
b.Property<string>("CommitterEmail")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<string>("CommitterName")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("bit");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<bool?>("PostTestMergeComment")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("PushTestMergeCommits")
.IsRequired()
.HasColumnType("bit");
b.Property<bool?>("ShowTestMergeCommitters")
.IsRequired()
.HasColumnType("bit");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("RepositorySettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.Property<long>("TestMergeId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("RevisionInformationId");
b.HasIndex("TestMergeId");
b.ToTable("RevInfoTestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("CommitSha")
.IsRequired()
.HasColumnType("nvarchar(40)")
.HasMaxLength(40);
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("OriginCommitSha")
.IsRequired()
.HasColumnType("nvarchar(40)")
.HasMaxLength(40);
b.HasKey("Id");
b.HasIndex("InstanceId", "CommitSha")
.IsUnique();
b.ToTable("RevisionInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Author")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("BodyAtMerge")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Comment")
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<DateTimeOffset>("MergedAt")
.HasColumnType("datetimeoffset");
b.Property<long>("MergedById")
.HasColumnType("bigint");
b.Property<int>("Number")
.HasColumnType("int");
b.Property<long?>("PrimaryRevisionInformationId")
.IsRequired()
.HasColumnType("bigint");
b.Property<string>("PullRequestRevision")
.IsRequired()
.HasColumnType("nvarchar(40)")
.HasMaxLength(40);
b.Property<string>("TitleAtMerge")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("MergedById");
b.HasIndex("PrimaryRevisionInformationId")
.IsUnique();
b.ToTable("TestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.Property<long?>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<decimal>("AdministrationRights")
.HasColumnType("decimal(20,0)");
b.Property<string>("CanonicalName")
.IsRequired()
.HasColumnType("nvarchar(450)");
b.Property<DateTimeOffset?>("CreatedAt")
.IsRequired()
.HasColumnType("datetimeoffset");
b.Property<long?>("CreatedById")
.HasColumnType("bigint");
b.Property<bool?>("Enabled")
.IsRequired()
.HasColumnType("bit");
b.Property<decimal>("InstanceManagerRights")
.HasColumnType("decimal(20,0)");
b.Property<DateTimeOffset?>("LastPasswordUpdate")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("SystemIdentifier")
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("CanonicalName")
.IsUnique();
b.HasIndex("CreatedById");
b.HasIndex("SystemIdentifier")
.IsUnique()
.HasFilter("[SystemIdentifier] IS NOT NULL");
b.ToTable("Users");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("ChatSettings")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
.WithMany("Channels")
.HasForeignKey("ChatSettingsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
.WithOne()
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("CompileJobs")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamDaemonSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamMakerSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("InstanceUsers")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", null)
.WithMany("InstanceUsers")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
.WithMany()
.HasForeignKey("CancelledById");
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("Jobs")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
.WithMany()
.HasForeignKey("StartedById")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
.WithMany()
.HasForeignKey("CompileJobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("RepositorySettings")
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("ActiveTestMerges")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
.WithMany("RevisonInformations")
.HasForeignKey("TestMergeId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("RevisionInformations")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
.WithMany("TestMerges")
.HasForeignKey("MergedById")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
.WithOne("PrimaryTestMerge")
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
.WithMany("CreatedUsers")
.HasForeignKey("CreatedById");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Tgstation.Server.Host.Database.Migrations
{
/// <summary>
/// Adds columns for GitHub deployments for MSSQL.
/// </summary>
public partial class MSAddDeploymentColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.AddColumn<bool>(
name: "CreateGitHubDeployments",
table: "RepositorySettings",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "GitHubDeploymentId",
table: "CompileJobs",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "GitHubRepoId",
table: "CompileJobs",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.DropColumn(
name: "CreateGitHubDeployments",
table: "RepositorySettings");
migrationBuilder.DropColumn(
name: "GitHubDeploymentId",
table: "CompileJobs");
migrationBuilder.DropColumn(
name: "GitHubRepoId",
table: "CompileJobs");
}
}
}
@@ -0,0 +1,771 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20200807213742_MYAddDeploymentColumns")]
partial class MYAddDeploymentColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<ushort?>("ChannelLimit")
.IsRequired()
.HasColumnType("smallint unsigned");
b.Property<string>("ConnectionString")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("Enabled")
.HasColumnType("tinyint(1)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<int>("Provider")
.HasColumnType("int");
b.Property<uint?>("ReconnectionInterval")
.IsRequired()
.HasColumnType("int unsigned");
b.HasKey("Id");
b.HasIndex("InstanceId", "Name")
.IsUnique();
b.ToTable("ChatBots");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("ChatSettingsId")
.HasColumnType("bigint");
b.Property<ulong?>("DiscordChannelId")
.HasColumnType("bigint unsigned");
b.Property<string>("IrcChannel")
.HasColumnType("varchar(100) CHARACTER SET utf8mb4")
.HasMaxLength(100);
b.Property<bool?>("IsAdminChannel")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("IsUpdatesChannel")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("IsWatchdogChannel")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<string>("Tag")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.HasKey("Id");
b.HasIndex("ChatSettingsId", "DiscordChannelId")
.IsUnique();
b.HasIndex("ChatSettingsId", "IrcChannel")
.IsUnique();
b.ToTable("ChatChannels");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("ByondVersion")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<int?>("DMApiMajorVersion")
.HasColumnType("int");
b.Property<int?>("DMApiMinorVersion")
.HasColumnType("int");
b.Property<int?>("DMApiPatchVersion")
.HasColumnType("int");
b.Property<Guid?>("DirectoryName")
.IsRequired()
.HasColumnType("char(36)");
b.Property<string>("DmeName")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("int");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<int?>("MinimumSecurityLevel")
.HasColumnType("int");
b.Property<string>("Output")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("DirectoryName");
b.HasIndex("JobId")
.IsUnique();
b.HasIndex("RevisionInformationId");
b.ToTable("CompileJobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool?>("AllowWebClient")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("AutoStart")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<uint?>("HeartbeatSeconds")
.IsRequired()
.HasColumnType("int unsigned");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<ushort?>("Port")
.IsRequired()
.HasColumnType("smallint unsigned");
b.Property<int>("SecurityLevel")
.HasColumnType("int");
b.Property<uint?>("StartupTimeout")
.IsRequired()
.HasColumnType("int unsigned");
b.Property<uint?>("TopicRequestTimeout")
.IsRequired()
.HasColumnType("int unsigned");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamDaemonSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<ushort?>("ApiValidationPort")
.IsRequired()
.HasColumnType("smallint unsigned");
b.Property<int>("ApiValidationSecurityLevel")
.HasColumnType("int");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("ProjectName")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("RequireDMApiValidation")
.IsRequired()
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamMakerSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<uint?>("AutoUpdateInterval")
.IsRequired()
.HasColumnType("int unsigned");
b.Property<ushort?>("ChatBotLimit")
.IsRequired()
.HasColumnType("smallint unsigned");
b.Property<int>("ConfigurationType")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("Online")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<string>("Path")
.IsRequired()
.HasColumnType("varchar(255) CHARACTER SET utf8mb4");
b.HasKey("Id");
b.HasIndex("Path")
.IsUnique();
b.ToTable("Instances");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<ulong>("ByondRights")
.HasColumnType("bigint unsigned");
b.Property<ulong>("ChatBotRights")
.HasColumnType("bigint unsigned");
b.Property<ulong>("ConfigurationRights")
.HasColumnType("bigint unsigned");
b.Property<ulong>("DreamDaemonRights")
.HasColumnType("bigint unsigned");
b.Property<ulong>("DreamMakerRights")
.HasColumnType("bigint unsigned");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<ulong>("InstanceUserRights")
.HasColumnType("bigint unsigned");
b.Property<ulong>("RepositoryRights")
.HasColumnType("bigint unsigned");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId");
b.HasIndex("UserId", "InstanceId")
.IsUnique();
b.ToTable("InstanceUsers");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<ulong?>("CancelRight")
.HasColumnType("bigint unsigned");
b.Property<ulong?>("CancelRightsType")
.HasColumnType("bigint unsigned");
b.Property<bool?>("Cancelled")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<long?>("CancelledById")
.HasColumnType("bigint");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<uint?>("ErrorCode")
.HasColumnType("int unsigned");
b.Property<string>("ExceptionDetails")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StartedAt")
.IsRequired()
.HasColumnType("datetime(6)");
b.Property<long>("StartedById")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StoppedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("CancelledById");
b.HasIndex("InstanceId");
b.HasIndex("StartedById");
b.ToTable("Jobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("AccessIdentifier")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<long>("CompileJobId")
.HasColumnType("bigint");
b.Property<int>("LaunchSecurityLevel")
.HasColumnType("int");
b.Property<ushort>("Port")
.HasColumnType("smallint unsigned");
b.Property<int>("ProcessId")
.HasColumnType("int");
b.Property<int>("RebootState")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("CompileJobId");
b.ToTable("ReattachInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("AccessToken")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<string>("AccessUser")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("AutoUpdatesKeepTestMerges")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("AutoUpdatesSynchronize")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<string>("CommitterEmail")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<string>("CommitterName")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<bool?>("PostTestMergeComment")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("PushTestMergeCommits")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<bool?>("ShowTestMergeCommitters")
.IsRequired()
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("RepositorySettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.Property<long>("TestMergeId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("RevisionInformationId");
b.HasIndex("TestMergeId");
b.ToTable("RevInfoTestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("CommitSha")
.IsRequired()
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasMaxLength(40);
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("OriginCommitSha")
.IsRequired()
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasMaxLength(40);
b.HasKey("Id");
b.HasIndex("InstanceId", "CommitSha")
.IsUnique();
b.ToTable("RevisionInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("BodyAtMerge")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("Comment")
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<DateTimeOffset>("MergedAt")
.HasColumnType("datetime(6)");
b.Property<long>("MergedById")
.HasColumnType("bigint");
b.Property<int>("Number")
.HasColumnType("int");
b.Property<long?>("PrimaryRevisionInformationId")
.IsRequired()
.HasColumnType("bigint");
b.Property<string>("PullRequestRevision")
.IsRequired()
.HasColumnType("varchar(40) CHARACTER SET utf8mb4")
.HasMaxLength(40);
b.Property<string>("TitleAtMerge")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.HasKey("Id");
b.HasIndex("MergedById");
b.HasIndex("PrimaryRevisionInformationId")
.IsUnique();
b.ToTable("TestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.Property<long?>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<ulong>("AdministrationRights")
.HasColumnType("bigint unsigned");
b.Property<string>("CanonicalName")
.IsRequired()
.HasColumnType("varchar(255) CHARACTER SET utf8mb4");
b.Property<DateTimeOffset?>("CreatedAt")
.IsRequired()
.HasColumnType("datetime(6)");
b.Property<long?>("CreatedById")
.HasColumnType("bigint");
b.Property<bool?>("Enabled")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<ulong>("InstanceManagerRights")
.HasColumnType("bigint unsigned");
b.Property<DateTimeOffset?>("LastPasswordUpdate")
.HasColumnType("datetime(6)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<string>("PasswordHash")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<string>("SystemIdentifier")
.HasColumnType("varchar(255) CHARACTER SET utf8mb4");
b.HasKey("Id");
b.HasIndex("CanonicalName")
.IsUnique();
b.HasIndex("CreatedById");
b.HasIndex("SystemIdentifier")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("ChatSettings")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
.WithMany("Channels")
.HasForeignKey("ChatSettingsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
.WithOne()
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("CompileJobs")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamDaemonSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamMakerSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("InstanceUsers")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", null)
.WithMany("InstanceUsers")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
.WithMany()
.HasForeignKey("CancelledById");
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("Jobs")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
.WithMany()
.HasForeignKey("StartedById")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
.WithMany()
.HasForeignKey("CompileJobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("RepositorySettings")
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("ActiveTestMerges")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
.WithMany("RevisonInformations")
.HasForeignKey("TestMergeId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("RevisionInformations")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
.WithMany("TestMerges")
.HasForeignKey("MergedById")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
.WithOne("PrimaryTestMerge")
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
.WithMany("CreatedUsers")
.HasForeignKey("CreatedById");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Tgstation.Server.Host.Database.Migrations
{
/// <summary>
/// Adds columns for GitHub deployments for MYSQL.
/// </summary>
public partial class MYAddDeploymentColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.AddColumn<bool>(
name: "CreateGitHubDeployments",
table: "RepositorySettings",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "GitHubDeploymentId",
table: "CompileJobs",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "GitHubRepoId",
table: "CompileJobs",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.DropColumn(
name: "CreateGitHubDeployments",
table: "RepositorySettings");
migrationBuilder.DropColumn(
name: "GitHubDeploymentId",
table: "CompileJobs");
migrationBuilder.DropColumn(
name: "GitHubRepoId",
table: "CompileJobs");
}
}
}
@@ -0,0 +1,778 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(PostgresSqlDatabaseContext))]
[Migration("20200807214330_PGAddDeploymentColumns")]
partial class PGAddDeploymentColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<int>("ChannelLimit")
.HasColumnType("integer");
b.Property<string>("ConnectionString")
.IsRequired()
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("Enabled")
.HasColumnType("boolean");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(100)")
.HasMaxLength(100);
b.Property<int>("Provider")
.HasColumnType("integer");
b.Property<long>("ReconnectionInterval")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId", "Name")
.IsUnique();
b.ToTable("ChatBots");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<long>("ChatSettingsId")
.HasColumnType("bigint");
b.Property<decimal?>("DiscordChannelId")
.HasColumnType("numeric(20,0)");
b.Property<string>("IrcChannel")
.HasColumnType("character varying(100)")
.HasMaxLength(100);
b.Property<bool?>("IsAdminChannel")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("IsUpdatesChannel")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("IsWatchdogChannel")
.IsRequired()
.HasColumnType("boolean");
b.Property<string>("Tag")
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.HasKey("Id");
b.HasIndex("ChatSettingsId", "DiscordChannelId")
.IsUnique();
b.HasIndex("ChatSettingsId", "IrcChannel")
.IsUnique();
b.ToTable("ChatChannels");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("ByondVersion")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("DMApiMajorVersion")
.HasColumnType("integer");
b.Property<int?>("DMApiMinorVersion")
.HasColumnType("integer");
b.Property<int?>("DMApiPatchVersion")
.HasColumnType("integer");
b.Property<Guid?>("DirectoryName")
.IsRequired()
.HasColumnType("uuid");
b.Property<string>("DmeName")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("integer");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
b.Property<int?>("MinimumSecurityLevel")
.HasColumnType("integer");
b.Property<string>("Output")
.IsRequired()
.HasColumnType("text");
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("DirectoryName");
b.HasIndex("JobId")
.IsUnique();
b.HasIndex("RevisionInformationId");
b.ToTable("CompileJobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<bool?>("AllowWebClient")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("AutoStart")
.IsRequired()
.HasColumnType("boolean");
b.Property<long>("HeartbeatSeconds")
.HasColumnType("bigint");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<int>("Port")
.HasColumnType("integer");
b.Property<int>("SecurityLevel")
.HasColumnType("integer");
b.Property<long>("StartupTimeout")
.HasColumnType("bigint");
b.Property<long>("TopicRequestTimeout")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamDaemonSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<int>("ApiValidationPort")
.HasColumnType("integer");
b.Property<int>("ApiValidationSecurityLevel")
.HasColumnType("integer");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("ProjectName")
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("RequireDMApiValidation")
.IsRequired()
.HasColumnType("boolean");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamMakerSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<long>("AutoUpdateInterval")
.HasColumnType("bigint");
b.Property<int>("ChatBotLimit")
.HasColumnType("integer");
b.Property<int>("ConfigurationType")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("Online")
.IsRequired()
.HasColumnType("boolean");
b.Property<string>("Path")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("Path")
.IsUnique();
b.ToTable("Instances");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<decimal>("ByondRights")
.HasColumnType("numeric(20,0)");
b.Property<decimal>("ChatBotRights")
.HasColumnType("numeric(20,0)");
b.Property<decimal>("ConfigurationRights")
.HasColumnType("numeric(20,0)");
b.Property<decimal>("DreamDaemonRights")
.HasColumnType("numeric(20,0)");
b.Property<decimal>("DreamMakerRights")
.HasColumnType("numeric(20,0)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<decimal>("InstanceUserRights")
.HasColumnType("numeric(20,0)");
b.Property<decimal>("RepositoryRights")
.HasColumnType("numeric(20,0)");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("InstanceId");
b.HasIndex("UserId", "InstanceId")
.IsUnique();
b.ToTable("InstanceUsers");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<decimal?>("CancelRight")
.HasColumnType("numeric(20,0)");
b.Property<decimal?>("CancelRightsType")
.HasColumnType("numeric(20,0)");
b.Property<bool?>("Cancelled")
.IsRequired()
.HasColumnType("boolean");
b.Property<long?>("CancelledById")
.HasColumnType("bigint");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("ErrorCode")
.HasColumnType("bigint");
b.Property<string>("ExceptionDetails")
.HasColumnType("text");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StartedAt")
.IsRequired()
.HasColumnType("timestamp with time zone");
b.Property<long>("StartedById")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("StoppedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CancelledById");
b.HasIndex("InstanceId");
b.HasIndex("StartedById");
b.ToTable("Jobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("AccessIdentifier")
.IsRequired()
.HasColumnType("text");
b.Property<long>("CompileJobId")
.HasColumnType("bigint");
b.Property<int>("LaunchSecurityLevel")
.HasColumnType("integer");
b.Property<int>("Port")
.HasColumnType("integer");
b.Property<int>("ProcessId")
.HasColumnType("integer");
b.Property<int>("RebootState")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CompileJobId");
b.ToTable("ReattachInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("AccessToken")
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<string>("AccessUser")
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("AutoUpdatesKeepTestMerges")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("AutoUpdatesSynchronize")
.IsRequired()
.HasColumnType("boolean");
b.Property<string>("CommitterEmail")
.IsRequired()
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<string>("CommitterName")
.IsRequired()
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("boolean");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<bool?>("PostTestMergeComment")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("PushTestMergeCommits")
.IsRequired()
.HasColumnType("boolean");
b.Property<bool?>("ShowTestMergeCommitters")
.IsRequired()
.HasColumnType("boolean");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("RepositorySettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<long>("RevisionInformationId")
.HasColumnType("bigint");
b.Property<long>("TestMergeId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("RevisionInformationId");
b.HasIndex("TestMergeId");
b.ToTable("RevInfoTestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("CommitSha")
.IsRequired()
.HasColumnType("character varying(40)")
.HasMaxLength(40);
b.Property<long>("InstanceId")
.HasColumnType("bigint");
b.Property<string>("OriginCommitSha")
.IsRequired()
.HasColumnType("character varying(40)")
.HasMaxLength(40);
b.HasKey("Id");
b.HasIndex("InstanceId", "CommitSha")
.IsUnique();
b.ToTable("RevisionInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("Author")
.IsRequired()
.HasColumnType("text");
b.Property<string>("BodyAtMerge")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Comment")
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<DateTimeOffset>("MergedAt")
.HasColumnType("timestamp with time zone");
b.Property<long>("MergedById")
.HasColumnType("bigint");
b.Property<int>("Number")
.HasColumnType("integer");
b.Property<long?>("PrimaryRevisionInformationId")
.IsRequired()
.HasColumnType("bigint");
b.Property<string>("PullRequestRevision")
.IsRequired()
.HasColumnType("character varying(40)")
.HasMaxLength(40);
b.Property<string>("TitleAtMerge")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("MergedById");
b.HasIndex("PrimaryRevisionInformationId")
.IsUnique();
b.ToTable("TestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.Property<long?>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<decimal>("AdministrationRights")
.HasColumnType("numeric(20,0)");
b.Property<string>("CanonicalName")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset?>("CreatedAt")
.IsRequired()
.HasColumnType("timestamp with time zone");
b.Property<long?>("CreatedById")
.HasColumnType("bigint");
b.Property<bool?>("Enabled")
.IsRequired()
.HasColumnType("boolean");
b.Property<decimal>("InstanceManagerRights")
.HasColumnType("numeric(20,0)");
b.Property<DateTimeOffset?>("LastPasswordUpdate")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("SystemIdentifier")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CanonicalName")
.IsUnique();
b.HasIndex("CreatedById");
b.HasIndex("SystemIdentifier")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("ChatSettings")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
.WithMany("Channels")
.HasForeignKey("ChatSettingsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
.WithOne()
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("CompileJobs")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamDaemonSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamMakerSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("InstanceUsers")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", null)
.WithMany("InstanceUsers")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
.WithMany()
.HasForeignKey("CancelledById");
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("Jobs")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
.WithMany()
.HasForeignKey("StartedById")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
.WithMany()
.HasForeignKey("CompileJobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("RepositorySettings")
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("ActiveTestMerges")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
.WithMany("RevisonInformations")
.HasForeignKey("TestMergeId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("RevisionInformations")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
.WithMany("TestMerges")
.HasForeignKey("MergedById")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
.WithOne("PrimaryTestMerge")
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
.WithMany("CreatedUsers")
.HasForeignKey("CreatedById");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,53 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Tgstation.Server.Host.Database.Migrations
{
/// <summary>
/// Adds columns for GitHub deployments for PostgresSQL.
/// </summary>
public partial class PGAddDeploymentColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.AddColumn<bool>(
name: "CreateGitHubDeployments",
table: "RepositorySettings",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "GitHubDeploymentId",
table: "CompileJobs",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "GitHubRepoId",
table: "CompileJobs",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.DropColumn(
name: "CreateGitHubDeployments",
table: "RepositorySettings");
migrationBuilder.DropColumn(
name: "GitHubDeploymentId",
table: "CompileJobs");
migrationBuilder.DropColumn(
name: "GitHubRepoId",
table: "CompileJobs");
}
}
}
@@ -0,0 +1,770 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqliteDatabaseContext))]
[Migration("20200807214754_SLAddDeploymentColumns")]
partial class SLAddDeploymentColumns
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.6");
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ushort?>("ChannelLimit")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("ConnectionString")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("Enabled")
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(100);
b.Property<int>("Provider")
.HasColumnType("INTEGER");
b.Property<uint?>("ReconnectionInterval")
.IsRequired()
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("InstanceId", "Name")
.IsUnique();
b.ToTable("ChatBots");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<long>("ChatSettingsId")
.HasColumnType("INTEGER");
b.Property<ulong?>("DiscordChannelId")
.HasColumnType("INTEGER");
b.Property<string>("IrcChannel")
.HasColumnType("TEXT")
.HasMaxLength(100);
b.Property<bool?>("IsAdminChannel")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("IsUpdatesChannel")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("IsWatchdogChannel")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("Tag")
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.HasKey("Id");
b.HasIndex("ChatSettingsId", "DiscordChannelId")
.IsUnique();
b.HasIndex("ChatSettingsId", "IrcChannel")
.IsUnique();
b.ToTable("ChatChannels");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ByondVersion")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("DMApiMajorVersion")
.HasColumnType("INTEGER");
b.Property<int?>("DMApiMinorVersion")
.HasColumnType("INTEGER");
b.Property<int?>("DMApiPatchVersion")
.HasColumnType("INTEGER");
b.Property<Guid?>("DirectoryName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DmeName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("INTEGER");
b.Property<long?>("GitHubRepoId")
.HasColumnType("INTEGER");
b.Property<long>("JobId")
.HasColumnType("INTEGER");
b.Property<int?>("MinimumSecurityLevel")
.HasColumnType("INTEGER");
b.Property<string>("Output")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("RevisionInformationId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("DirectoryName");
b.HasIndex("JobId")
.IsUnique();
b.HasIndex("RevisionInformationId");
b.ToTable("CompileJobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<bool?>("AllowWebClient")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("AutoStart")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<uint?>("HeartbeatSeconds")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<ushort?>("Port")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<int>("SecurityLevel")
.HasColumnType("INTEGER");
b.Property<uint?>("StartupTimeout")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<uint?>("TopicRequestTimeout")
.IsRequired()
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamDaemonSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ushort?>("ApiValidationPort")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<int>("ApiValidationSecurityLevel")
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<string>("ProjectName")
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("RequireDMApiValidation")
.IsRequired()
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DreamMakerSettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<uint?>("AutoUpdateInterval")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<ushort?>("ChatBotLimit")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<int>("ConfigurationType")
.HasColumnType("INTEGER");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("Online")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("Path")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("Path")
.IsUnique();
b.ToTable("Instances");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("ByondRights")
.HasColumnType("INTEGER");
b.Property<ulong>("ChatBotRights")
.HasColumnType("INTEGER");
b.Property<ulong>("ConfigurationRights")
.HasColumnType("INTEGER");
b.Property<ulong>("DreamDaemonRights")
.HasColumnType("INTEGER");
b.Property<ulong>("DreamMakerRights")
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<ulong>("InstanceUserRights")
.HasColumnType("INTEGER");
b.Property<ulong>("RepositoryRights")
.HasColumnType("INTEGER");
b.Property<long>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("InstanceId");
b.HasIndex("UserId", "InstanceId")
.IsUnique();
b.ToTable("InstanceUsers");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong?>("CancelRight")
.HasColumnType("INTEGER");
b.Property<ulong?>("CancelRightsType")
.HasColumnType("INTEGER");
b.Property<bool?>("Cancelled")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<long?>("CancelledById")
.HasColumnType("INTEGER");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint?>("ErrorCode")
.HasColumnType("INTEGER");
b.Property<string>("ExceptionDetails")
.HasColumnType("TEXT");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("StartedAt")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("StartedById")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("StoppedAt")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CancelledById");
b.HasIndex("InstanceId");
b.HasIndex("StartedById");
b.ToTable("Jobs");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccessIdentifier")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("CompileJobId")
.HasColumnType("INTEGER");
b.Property<int>("LaunchSecurityLevel")
.HasColumnType("INTEGER");
b.Property<ushort>("Port")
.HasColumnType("INTEGER");
b.Property<int>("ProcessId")
.HasColumnType("INTEGER");
b.Property<int>("RebootState")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("CompileJobId");
b.ToTable("ReattachInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccessToken")
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<string>("AccessUser")
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("AutoUpdatesKeepTestMerges")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("AutoUpdatesSynchronize")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("CommitterEmail")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<string>("CommitterName")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<bool?>("PostTestMergeComment")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("PushTestMergeCommits")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<bool?>("ShowTestMergeCommitters")
.IsRequired()
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("RepositorySettings");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<long>("RevisionInformationId")
.HasColumnType("INTEGER");
b.Property<long>("TestMergeId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("RevisionInformationId");
b.HasIndex("TestMergeId");
b.ToTable("RevInfoTestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("CommitSha")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(40);
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
b.Property<string>("OriginCommitSha")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(40);
b.HasKey("Id");
b.HasIndex("InstanceId", "CommitSha")
.IsUnique();
b.ToTable("RevisionInformations");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("BodyAtMerge")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Comment")
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<DateTimeOffset>("MergedAt")
.HasColumnType("TEXT");
b.Property<long>("MergedById")
.HasColumnType("INTEGER");
b.Property<int>("Number")
.HasColumnType("INTEGER");
b.Property<long?>("PrimaryRevisionInformationId")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<string>("PullRequestRevision")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(40);
b.Property<string>("TitleAtMerge")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("MergedById");
b.HasIndex("PrimaryRevisionInformationId")
.IsUnique();
b.ToTable("TestMerges");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.Property<long?>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("AdministrationRights")
.HasColumnType("INTEGER");
b.Property<string>("CanonicalName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<DateTimeOffset?>("CreatedAt")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long?>("CreatedById")
.HasColumnType("INTEGER");
b.Property<bool?>("Enabled")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<ulong>("InstanceManagerRights")
.HasColumnType("INTEGER");
b.Property<DateTimeOffset?>("LastPasswordUpdate")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<string>("PasswordHash")
.HasColumnType("TEXT");
b.Property<string>("SystemIdentifier")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("CanonicalName")
.IsUnique();
b.HasIndex("CreatedById");
b.HasIndex("SystemIdentifier")
.IsUnique();
b.ToTable("Users");
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("ChatSettings")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
{
b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
.WithMany("Channels")
.HasForeignKey("ChatSettingsId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
.WithOne()
.HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("CompileJobs")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamDaemonSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("DreamMakerSettings")
.HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("InstanceUsers")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", null)
.WithMany("InstanceUsers")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
.WithMany()
.HasForeignKey("CancelledById");
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("Jobs")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
.WithMany()
.HasForeignKey("StartedById")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
.WithMany()
.HasForeignKey("CompileJobId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithOne("RepositorySettings")
.HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
.WithMany("ActiveTestMerges")
.HasForeignKey("RevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
.WithMany("RevisonInformations")
.HasForeignKey("TestMergeId")
.OnDelete(DeleteBehavior.ClientNoAction)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
{
b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
.WithMany("RevisionInformations")
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
.WithMany("TestMerges")
.HasForeignKey("MergedById")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
.WithOne("PrimaryTestMerge")
.HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
{
b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
.WithMany("CreatedUsers")
.HasForeignKey("CreatedById");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,122 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Tgstation.Server.Host.Database.Migrations
{
/// <summary>
/// Adds columns for GitHub deployments for SQLite.
/// </summary>
public partial class SLAddDeploymentColumns : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.AddColumn<bool>(
name: "CreateGitHubDeployments",
table: "RepositorySettings",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<int>(
name: "GitHubDeploymentId",
table: "CompileJobs",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "GitHubRepoId",
table: "CompileJobs",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
if (migrationBuilder == null)
throw new ArgumentNullException(nameof(migrationBuilder));
migrationBuilder.RenameTable(
name: "RepositorySettings",
newName: "RepositorySettings_down");
migrationBuilder.CreateTable(
name: "RepositorySettings",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
CommitterName = table.Column<string>(maxLength: 10000, nullable: false),
CommitterEmail = table.Column<string>(maxLength: 10000, nullable: false),
AccessUser = table.Column<string>(maxLength: 10000, nullable: true),
AccessToken = table.Column<string>(maxLength: 10000, nullable: true),
PushTestMergeCommits = table.Column<bool>(nullable: false),
ShowTestMergeCommitters = table.Column<bool>(nullable: false),
AutoUpdatesKeepTestMerges = table.Column<bool>(nullable: false),
AutoUpdatesSynchronize = table.Column<bool>(nullable: false),
PostTestMergeComment = table.Column<bool>(nullable: false),
InstanceId = table.Column<long>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RepositorySettings", x => x.Id);
table.ForeignKey(
name: "FK_RepositorySettings_Instances_InstanceId",
column: x => x.InstanceId,
principalTable: "Instances",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.Sql(
$"INSERT INTO RepositorySettings SELECT Id,CommitterName,CommitterEmail,AccessUser,AccessToken,PushTestMergeCommits,ShowTestMergeCommitters,AutoUpdatesKeepTestMerges,AutoUpdatesSynchronize,PostTestMergeComment,InstanceId FROM RepositorySettings_down");
migrationBuilder.DropTable(
name: "RepositorySettings_down");
migrationBuilder.RenameTable(
name: "CompileJobs",
newName: "CompileJobs_down");
migrationBuilder.CreateTable(
name: "CompileJobs",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DmeName = table.Column<string>(nullable: false),
Output = table.Column<string>(nullable: false),
DirectoryName = table.Column<Guid>(nullable: false),
MinimumSecurityLevel = table.Column<int>(nullable: true),
JobId = table.Column<long>(nullable: false),
RevisionInformationId = table.Column<long>(nullable: false),
ByondVersion = table.Column<string>(nullable: false),
DMApiMajorVersion = table.Column<int>(nullable: true),
DMApiMinorVersion = table.Column<int>(nullable: true),
DMApiPatchVersion = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CompileJobs", x => x.Id);
table.ForeignKey(
name: "FK_CompileJobs_Jobs_JobId",
column: x => x.JobId,
principalTable: "Jobs",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CompileJobs_RevisionInformations_RevisionInformationId",
column: x => x.RevisionInformationId,
principalTable: "RevisionInformations",
principalColumn: "Id");
});
migrationBuilder.Sql(
$"INSERT INTO CompileJobs SELECT Id,DmeName,Output,DirectoryName,MinimumSecurityLevel,JobId,RevisionInformationId,ByondVersion,DMApiMajorVersion,DMApiMinorVersion,DMApiPatchVersion FROM CompileJobs_down");
migrationBuilder.DropTable(
name: "CompileJobs_down");
}
}
}
@@ -1,11 +1,10 @@
// <auto-generated />
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace Tgstation.Server.Host.Database.Migrations
{
/// <inheritdoc />
[DbContext(typeof(MySqlDatabaseContext))]
partial class MySqlDatabaseContextModelSnapshot : ModelSnapshot
{
@@ -13,7 +12,7 @@ namespace Tgstation.Server.Host.Database.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
@@ -127,6 +126,12 @@ namespace Tgstation.Server.Host.Database.Migrations
.IsRequired()
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("int");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
@@ -296,8 +301,7 @@ namespace Tgstation.Server.Host.Database.Migrations
b.Property<ulong>("RepositoryRights")
.HasColumnType("bigint unsigned");
b.Property<long?>("UserId")
.IsRequired()
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
@@ -427,6 +431,10 @@ namespace Tgstation.Server.Host.Database.Migrations
.HasColumnType("longtext CHARACTER SET utf8mb4")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("tinyint(1)");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
@@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -9,13 +9,12 @@ namespace Tgstation.Server.Host.Database.Migrations
[DbContext(typeof(PostgresSqlDatabaseContext))]
partial class PostgresSqlDatabaseContextModelSnapshot : ModelSnapshot
{
/// <inheritdoc />
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
@@ -130,6 +129,12 @@ namespace Tgstation.Server.Host.Database.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("integer");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
@@ -296,8 +301,7 @@ namespace Tgstation.Server.Host.Database.Migrations
b.Property<decimal>("RepositoryRights")
.HasColumnType("numeric(20,0)");
b.Property<long?>("UserId")
.IsRequired()
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
@@ -430,6 +434,10 @@ namespace Tgstation.Server.Host.Database.Migrations
.HasColumnType("character varying(10000)")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("boolean");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
@@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Database.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.5")
.HasAnnotation("ProductVersion", "3.1.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
@@ -132,6 +132,12 @@ namespace Tgstation.Server.Host.Database.Migrations
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("int");
b.Property<long?>("GitHubRepoId")
.HasColumnType("bigint");
b.Property<long>("JobId")
.HasColumnType("bigint");
@@ -298,8 +304,7 @@ namespace Tgstation.Server.Host.Database.Migrations
b.Property<decimal>("RepositoryRights")
.HasColumnType("decimal(20,0)");
b.Property<long?>("UserId")
.IsRequired()
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
@@ -432,6 +437,10 @@ namespace Tgstation.Server.Host.Database.Migrations
.HasColumnType("nvarchar(max)")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("bit");
b.Property<long>("InstanceId")
.HasColumnType("bigint");
@@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -13,7 +13,7 @@ namespace Tgstation.Server.Host.Database.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.5");
.HasAnnotation("ProductVersion", "3.1.6");
modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
{
@@ -126,6 +126,12 @@ namespace Tgstation.Server.Host.Database.Migrations
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("GitHubDeploymentId")
.HasColumnType("INTEGER");
b.Property<long?>("GitHubRepoId")
.HasColumnType("INTEGER");
b.Property<long>("JobId")
.HasColumnType("INTEGER");
@@ -295,8 +301,7 @@ namespace Tgstation.Server.Host.Database.Migrations
b.Property<ulong>("RepositoryRights")
.HasColumnType("INTEGER");
b.Property<long?>("UserId")
.IsRequired()
b.Property<long>("UserId")
.HasColumnType("INTEGER");
b.HasKey("Id");
@@ -426,6 +431,10 @@ namespace Tgstation.Server.Host.Database.Migrations
.HasColumnType("TEXT")
.HasMaxLength(10000);
b.Property<bool?>("CreateGitHubDeployments")
.IsRequired()
.HasColumnType("INTEGER");
b.Property<long>("InstanceId")
.HasColumnType("INTEGER");
+11 -1
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel.DataAnnotations;
namespace Tgstation.Server.Host.Models
@@ -44,6 +44,16 @@ namespace Tgstation.Server.Host.Models
/// </summary>
public int? DMApiPatchVersion { get; set; }
/// <summary>
/// The source GitHub repository the deployment came from if any.
/// </summary>
public long? GitHubRepoId { get; set; }
/// <summary>
/// The GitHub deployment ID associated with the <see cref="CompileJob"/> if any.
/// </summary>
public int? GitHubDeploymentId { get; set; }
/// <inheritdoc />
public override Version DMApiVersion
{
-4
View File
@@ -28,12 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6FF654E6
build\BuildDox.ps1 = build\BuildDox.ps1
build\Dockerfile = build\Dockerfile
build\GenerateMigrations.sh = build\GenerateMigrations.sh
build\install_byond.sh = build\install_byond.sh
build\InstallCodeCoverage.ps1 = build\InstallCodeCoverage.ps1
build\OpenApiValidationSettings.json = build\OpenApiValidationSettings.json
build\prep_deployment.ps1 = build\prep_deployment.ps1
build\stylecop.json = build\stylecop.json
build\test_core.sh = build\test_core.sh
build\tgs.docker.sh = build\tgs.docker.sh
build\tgs.ico = build\tgs.ico
build\tgs.png = build\tgs.png