Merge pull request #943 from tgstation/INTEGRATE

Add some repository integration tests
This commit is contained in:
Jordan Brown
2020-04-26 21:00:50 -04:00
committed by GitHub
30 changed files with 8152 additions and 9307 deletions
+1 -1
View File
@@ -63,6 +63,6 @@ install:
- if [ $DockerBuild = false ] && [ $DMAPI = false ]; then dotnet restore tgstation-server.sln; fi
script:
- if [ $DockerBuild = false ] && [ $DMAPI = true ]; then tests/DMAPI/build_byond.sh || travis_terminate 1; fi
- if [ $DockerBuild = false ] && [ $DMAPI = true ]; then tests/DMAPI/BasicOperation/build_byond.sh || travis_terminate 1; fi
- if [ $DockerBuild = false ] && [ $DMAPI = false ]; then build/test_core.sh; fi
- if [ $DockerBuild = true ]; then docker build . -f build/Dockerfile; fi
+3 -3
View File
@@ -3,10 +3,10 @@
<!-- This is the authorative version list -->
<!-- Integration tests will ensure they match across the board -->
<TgsCoreVersion>4.1.0</TgsCoreVersion>
<TgsApiVersion>5.1.0</TgsApiVersion>
<TgsClientVersion>5.1.0</TgsClientVersion>
<TgsApiVersion>6.0.0</TgsApiVersion>
<TgsClientVersion>6.0.0</TgsClientVersion>
<TgsDmapiVersion>5.0.0</TgsDmapiVersion>
<TgsControlPanelVersion>0.1.6</TgsControlPanelVersion>
<TgsControlPanelVersion>0.4.0</TgsControlPanelVersion>
<TgsHostWatchdogVersion>1.1.0</TgsHostWatchdogVersion>
</PropertyGroup>
</Project>
+1 -1
View File
@@ -106,7 +106,7 @@ namespace Tgstation.Server.Api
/// </summary>
/// <param name="otherVersion">The <see cref="Version"/> to test</param>
/// <returns><see langword="true"/> if the given version is compatible with the API. <see langword="false"/> otherwise</returns>
public static bool CheckCompatibility(Version otherVersion) => !(Version.Major != (otherVersion?.Major ?? throw new ArgumentNullException(nameof(otherVersion))) || Version.Minor > otherVersion.Minor);
public static bool CheckCompatibility(Version otherVersion) => Version.Major == (otherVersion?.Major ?? throw new ArgumentNullException(nameof(otherVersion)));
/// <summary>
/// Construct <see cref="ApiHeaders"/> for JWT authentication
@@ -2,7 +2,7 @@
<Import Project="../../build/Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<DebugType>Full</DebugType>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Cyberboss</Authors>
@@ -2,7 +2,7 @@
<Import Project="../../build/Version.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<DebugType>Full</DebugType>
<Version>$(TgsClientVersion)</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
File diff suppressed because it is too large Load Diff
@@ -1,24 +1,25 @@
{
"private": true,
"dependencies": {
"react-dom": "^16.7.0",
"tgstation-server-control-panel": "0.1.6"
"react-dom": "^16.13.1",
"tgstation-server-control-panel": "0.4.0"
},
"optionalDependencies": {
"fsevents": "1.2.9"
},
"_comment": "fsevent@1.2.9 is locked in to prevent broken builds on windows for v1.2.11",
"scripts": {
"msbuild": "npm run clean && tslint -p tsconfig.json && react-scripts build && cp-cli node_modules/tgstation-server-control-panel/build/public/ build/ && cp-cli ../../../build/tgs.ico build/favicon.ico && minify-json build && rimraf ../wwwroot && move-cli build ../wwwroot",
"msbuild": "npm run clean && react-scripts build && cp-cli node_modules/tgstation-server-control-panel/build/public/ build/ && rimraf ../wwwroot && move-cli build ../wwwroot",
"clean": "rimraf build"
},
"devDependencies": {
"@types/node": "^10.12.0",
"@types/react-dom": "^16.0.9",
"@types/node": "^13.13.2",
"@types/react-dom": "^16.9.6",
"cp-cli": "^1.1.2",
"minify-json": "^1.0.0",
"move-cli": "^1.2.0",
"react-scripts": "^2.1.3",
"rimraf": "^2.6.2",
"tslint": "^5.12.0",
"tslint-react": "^3.6.0",
"typescript": "^3.1.3"
"move-cli": "^1.2.1",
"react-scripts": "^3.4.1",
"rimraf": "^3.0.2",
"typescript": "^3.8.3"
},
"browserslist": [
">0.2%",
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
@@ -10,6 +11,15 @@
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon-16x16.png">
<link rel="mask-icon" href="%PUBLIC_URL%/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css"
integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
@@ -20,10 +30,11 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Tgstation Server Control Panel</title>
</head>
<body>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
@@ -36,5 +47,6 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</body>
</html>
@@ -1,15 +0,0 @@
{
"short_name": "TGS",
"name": "Tgstation Server",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
@@ -13,7 +13,7 @@ if (!contentElement)
throw new Error("Missing root div, cannot render app!");
const legacyUserLanguageKey = "userLanguage";
const userLang = navigator.language || navigator[legacyUserLanguageKey];
const userLang = navigator.language || navigator[legacyUserLanguageKey] || "en-CA";
const serverAddress = window.location.href;
const controlPanel = <ControlPanel serverAddress={serverAddress} locale={userLang} />;
@@ -1,51 +0,0 @@
{
"extends": [
"tslint:recommended",
"tslint-react"
],
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js"
]
},
"rules": {
"curly": [
true,
"as-needed"
],
"semicolon": [
true,
"always"
],
"one-line": [
true,
"check-catch",
"check-finally",
"check-else",
"check-open-brace",
"check-whitespace"
],
"quotemark": [
true,
"double",
"jsx-double"
],
"trailing-comma": [
true,
{
"multiline": "never",
"singleline": "never"
}
],
"arrow-parens": [
true,
"ban-single-arg-parens"
],
"max-line-length": [
true,
150
]
}
}
@@ -207,15 +207,39 @@ namespace Tgstation.Server.Host.Components.Repository
progressReporter(0);
cancellationToken.ThrowIfCancellationRequested();
commands.Checkout(
var checkoutOptions = new CheckoutOptions
{
CheckoutModifiers = CheckoutModifiers.Force,
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
};
void RunCheckout() => commands.Checkout(
libGitRepo,
new CheckoutOptions
{
CheckoutModifiers = CheckoutModifiers.Force,
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
},
checkoutOptions,
committish);
try
{
RunCheckout();
}
catch (NotFoundException)
{
// Maybe (likely) a remote?
var remoteName = $"origin/{committish}";
var potentialBranch = libGitRepo.Branches.FirstOrDefault(
branch => branch.FriendlyName.Equals(remoteName, StringComparison.Ordinal));
cancellationToken.ThrowIfCancellationRequested();
if (potentialBranch == default)
throw;
logger.LogDebug("Creating local branch for {0}...", potentialBranch.FriendlyName);
libGitRepo.CreateBranch(committish, potentialBranch.Tip);
cancellationToken.ThrowIfCancellationRequested();
RunCheckout();
}
cancellationToken.ThrowIfCancellationRequested();
libGitRepo.RemoveUntrackedFiles();
@@ -99,8 +99,8 @@ namespace Tgstation.Server.Host.Controllers
if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
return Forbid();
job = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
return job != null ? (IActionResult)Accepted(job.ToApi()) : StatusCode((int)HttpStatusCode.Gone);
var updatedJob = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
return updatedJob != null ? (IActionResult)Accepted(updatedJob.ToApi()) : StatusCode((int)HttpStatusCode.Gone);
}
/// <summary>
@@ -326,9 +326,6 @@ namespace Tgstation.Server.Host.Controllers
if (model.CheckoutSha != null && model.UpdateFromOrigin == true)
return BadRequest(new ErrorMessage(ErrorCode.RepoMismatchShaAndUpdate));
if (model.Origin != null)
return BadRequest(new ErrorMessage(ErrorCode.RepoCantChangeOrigin));
if (model.NewTestMerges?.Any(x => model.NewTestMerges.Any(y => x != y && x.Number == y.Number)) == true)
return BadRequest(new ErrorMessage(ErrorCode.RepoDuplicateTestMerge));
@@ -404,6 +401,9 @@ namespace Tgstation.Server.Host.Controllers
if (repo == null)
return Conflict(new ErrorMessage(ErrorCode.RepoMissing));
await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken).ConfigureAwait(false);
if (model.Origin != null && model.Origin != repo.Origin)
return BadRequest(new ErrorMessage(ErrorCode.RepoCantChangeOrigin));
}
}
@@ -524,8 +524,13 @@ namespace Tgstation.Server.Host.Controllers
// checkout/hard reset
if (modelHasShaOrReference)
{
if ((model.CheckoutSha != null && repo.Head.ToUpperInvariant().StartsWith(model.CheckoutSha.ToUpperInvariant(), StringComparison.Ordinal))
|| (model.Reference != null && repo.Reference.ToUpperInvariant() != model.Reference.ToUpperInvariant()))
var validCheckoutSha =
model.CheckoutSha != null
&& !repo.Head.StartsWith(model.CheckoutSha, StringComparison.OrdinalIgnoreCase);
var validCheckoutReference =
model.Reference != null
&& !repo.Reference.Equals(model.Reference, StringComparison.OrdinalIgnoreCase);
if (validCheckoutSha || validCheckoutReference)
{
var committish = model.CheckoutSha ?? model.Reference;
var isSha = await repo.IsSha(committish, cancellationToken).ConfigureAwait(false);
+4 -3
View File
@@ -244,14 +244,15 @@ namespace Tgstation.Server.Host.Jobs
handler.Cancel(); // this will ensure the db update is only done once
await databaseContextFactory.UseContext(async databaseContext =>
{
job = new Job { Id = job.Id };
var updatedJob = new Job { Id = job.Id };
databaseContext.Jobs.Attach(job);
user = new User { Id = user.Id };
var attachedUser = new User { Id = user.Id };
databaseContext.Users.Attach(user);
job.CancelledBy = user;
updatedJob.CancelledBy = attachedUser;
// let either startup or cancellation set job.cancelled
await databaseContext.Save(cancellationToken).ConfigureAwait(false);
job.CancelledBy = user;
}).ConfigureAwait(false);
if (blocking)
await handler.Wait(cancellationToken).ConfigureAwait(false);
+1
View File
@@ -48,6 +48,7 @@ namespace Tgstation.Server.Host.Models
CancelRightsType = CancelRightsType,
Description = Description,
ExceptionDetails = ExceptionDetails,
ErrorCode = ErrorCode,
StartedBy = StartedBy.ToApi(false)
};
}
@@ -103,15 +103,12 @@
<ItemGroup>
<Content Remove="ClientApp\package-lock.json" />
<Content Remove="ClientApp\package.json" />
<Content Remove="ClientApp\public\manifest.json" />
<Content Remove="ClientApp\tsconfig.json" />
<Content Remove="ClientApp\tslint.json" />
<None Include="ClientApp\package-lock.json" />
<None Include="ClientApp\package.json" />
<None Include="ClientApp\public\manifest.json" />
<None Include="ClientApp\tsconfig.json" />
<None Include="ClientApp\tslint.json" />
<ClientApp Include="ClientApp\src\**\*;ClientApp\public\**\*;ClientApp\tsconfig.json;ClientApp\tslint.json;ClientApp\package.json;ClientApp\package-lock.json" />
<ClientApp Include="ClientApp\src\**\*;ClientApp\public\**\*;ClientApp\tsconfig.json;ClientApp\package.json;ClientApp\package-lock.json" />
<AdditionalFiles Include="../../build/stylecop.json" />
</ItemGroup>
@@ -7,5 +7,5 @@
#define TGS_INFO_LOG(message) world.log << "Info: [##message]"
#define TGS_WARNING_LOG(message) world.log << "Warn: [##message]"
#define TGS_ERROR_LOG(message) world.log << "Err: [##message]"
#define TGS_NOTIFY_ADMINS(event) message_admins(event)
#define TGS_CLIENT_COUNT clients.len
#define TGS_NOTIFY_ADMINS(event)
#define TGS_CLIENT_COUNT 0
@@ -1,5 +1,10 @@
/world/New()
TgsNew()
StartAsync()
/proc/StartAsync()
set waitfor = FALSE
sleep(100)
TgsInitializationComplete()
/world/Topic(T, Addr, Master, Keys)
@@ -12,7 +12,6 @@
// BEGIN_INCLUDE
#include "Config.dm"
#include "..\..\src\DMAPI\tgs.dm"
#include "..\..\src\DMAPI\tgs\includes.dm"
#include "..\tgs_include.dm"
#include "Test.dm"
// END_INCLUDE
+2
View File
@@ -0,0 +1,2 @@
#include "..\..\src\DMAPI\tgs.dm"
#include "..\..\src\DMAPI\tgs\includes.dm"
@@ -7,21 +7,32 @@ using Tgstation.Server.Client.Components;
namespace Tgstation.Server.Tests.Instance
{
sealed class ByondTest
sealed class ByondTest : JobsRequiredTest
{
readonly IByondClient byondClient;
readonly IJobsClient jobsClient;
public ByondTest(IByondClient byondClient, IJobsClient jobsClient)
: base(jobsClient)
{
this.byondClient = byondClient ?? throw new ArgumentNullException(nameof(byondClient));
this.jobsClient = jobsClient ?? throw new ArgumentNullException(nameof(jobsClient));
}
public async Task Run(CancellationToken cancellationToken)
{
await TestNoVersion(cancellationToken).ConfigureAwait(false);
await TestInstall511(cancellationToken).ConfigureAwait(false);
await TestInstallFakeVersion(cancellationToken).ConfigureAwait(false);
}
async Task TestInstallFakeVersion(CancellationToken cancellationToken)
{
var newModel = new Api.Models.Byond
{
Version = new Version(5011, 1385)
};
var test = await byondClient.SetActiveVersion(newModel, cancellationToken).ConfigureAwait(false);
Assert.IsNotNull(test.InstallJob);
await WaitForJob(test.InstallJob, 60, true, cancellationToken).ConfigureAwait(false);
}
async Task TestInstall511(CancellationToken cancellationToken)
@@ -33,24 +44,7 @@ namespace Tgstation.Server.Tests.Instance
var test = await byondClient.SetActiveVersion(newModel, cancellationToken).ConfigureAwait(false);
Assert.IsNotNull(test.InstallJob);
Assert.IsNull(test.Version);
var job = test.InstallJob;
var maxWait = 60; //it's 10MB max give me a break
do
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
job = await jobsClient.GetId(job, cancellationToken).ConfigureAwait(false);
--maxWait;
}
while (!job.StoppedAt.HasValue && maxWait > 0);
if (!job.StoppedAt.HasValue)
{
await jobsClient.Cancel(job, cancellationToken).ConfigureAwait(false);
Assert.Fail("Byond installation job timed out!");
}
if (job.ExceptionDetails != null)
Assert.Fail(job.ExceptionDetails);
var job = await WaitForJob(test.InstallJob, 60, false, cancellationToken).ConfigureAwait(false);
var currentShit = await byondClient.ActiveVersion(cancellationToken).ConfigureAwait(false);
Assert.AreEqual(newModel.Version.Semver(), currentShit.Version);
}
@@ -22,12 +22,17 @@ namespace Tgstation.Server.Tests.Instance
var byondTest = new ByondTest(instanceClient.Byond, instanceClient.Jobs);
var chatTest = new ChatTest(instanceClient.ChatBots, instanceManagerClient, instanceClient.Metadata.CloneMetadata());
var configTest = new ConfigurationTest(instanceClient.Configuration, instanceClient.Metadata);
var repoTest = new RepositoryTest(instanceClient.Repository, instanceClient.Jobs);
var repoTests = repoTest.RunPreWatchdog(cancellationToken);
var byondTests = byondTest.Run(cancellationToken);
var chatTests = chatTest.Run(cancellationToken);
await configTest.Run(cancellationToken).ConfigureAwait(false);
await byondTests.ConfigureAwait(false);
await chatTests.ConfigureAwait(false);
await repoTests;
await repoTest.RunPostWatchdog(cancellationToken);
}
}
}
@@ -0,0 +1,68 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Client.Components;
namespace Tgstation.Server.Tests.Instance
{
abstract class JobsRequiredTest
{
protected IJobsClient JobsClient { get; }
protected JobsRequiredTest(IJobsClient jobsClient)
{
this.JobsClient = jobsClient;
}
protected async Task<Job> WaitForJob(Job originalJob, int timeout, bool expectFailure, CancellationToken cancellationToken)
{
var job = originalJob;
do
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
job = await JobsClient.GetId(job, cancellationToken).ConfigureAwait(false);
--timeout;
}
while (!job.StoppedAt.HasValue && timeout > 0);
if (!job.StoppedAt.HasValue)
{
await JobsClient.Cancel(job, cancellationToken).ConfigureAwait(false);
Assert.Fail($"Job ID {job.Id} \"{job.Description}\" timed out!");
}
if (expectFailure ^ job.ExceptionDetails != null)
Assert.Fail(job.ExceptionDetails ?? $"Expected job \"{job.Id}\" \"{job.Description}\" to fail but it didn't");
return job;
}
protected async Task<Job> WaitForJobProgressThenCancel(Job originalJob, int timeout, CancellationToken cancellationToken)
{
var job = originalJob;
do
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
job = await JobsClient.GetId(job, cancellationToken).ConfigureAwait(false);
--timeout;
}
while (!job.Progress.HasValue && timeout > 0);
if (job.StoppedAt.HasValue)
{
await JobsClient.Cancel(job, cancellationToken).ConfigureAwait(false);
Assert.Fail($"Job ID {job.Id} \"{job.Description}\" completed when we wanted it to just progress!");
}
if (job.ExceptionDetails != null)
Assert.Fail(job.ExceptionDetails);
await JobsClient.Cancel(job, cancellationToken);
return await WaitForJob(job, timeout, false, cancellationToken).ConfigureAwait(false);
}
}
}
@@ -0,0 +1,208 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Client;
using Tgstation.Server.Client.Components;
namespace Tgstation.Server.Tests.Instance
{
sealed class RepositoryTest : JobsRequiredTest
{
readonly IRepositoryClient repositoryClient;
public RepositoryTest(IRepositoryClient repositoryClient, IJobsClient jobsClient)
: base(jobsClient)
{
this.repositoryClient = repositoryClient ?? throw new ArgumentNullException(nameof(repositoryClient));
}
public async Task RunPreWatchdog(CancellationToken cancellationToken)
{
// Clone ourselves
var workingBranch = Environment.GetEnvironmentVariable("TGS4_TEST_BRANCH");
if (String.IsNullOrWhiteSpace(workingBranch))
workingBranch = Environment.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH");
if (String.IsNullOrWhiteSpace(workingBranch))
workingBranch = Environment.GetEnvironmentVariable("TRAVIS_BRANCH");
if (String.IsNullOrWhiteSpace(workingBranch))
workingBranch = "master";
var initalRepo = await repositoryClient.Read(cancellationToken);
Assert.IsNotNull(initalRepo);
Assert.IsNull(initalRepo.Origin);
Assert.IsNull(initalRepo.Reference);
Assert.IsNull(initalRepo.RevisionInformation);
Assert.IsNull(initalRepo.ActiveJob);
const string Origin = "https://github.com/tgstation/tgstation-server";
initalRepo.Origin = Origin;
initalRepo.Reference = workingBranch;
var clone = await repositoryClient.Clone(initalRepo, cancellationToken).ConfigureAwait(false);
Assert.IsNotNull(clone);
Assert.AreEqual(Origin, clone.Origin);
Assert.AreEqual(workingBranch, clone.Reference);
Assert.IsNull(clone.RevisionInformation);
Assert.IsNotNull(clone.ActiveJob);
await WaitForJobProgressThenCancel(clone.ActiveJob, 20, cancellationToken).ConfigureAwait(false);
var secondRead = await repositoryClient.Read(cancellationToken).ConfigureAwait(false);
Assert.IsNotNull(secondRead);
Assert.IsNull(secondRead.ActiveJob);
clone = await repositoryClient.Clone(initalRepo, cancellationToken).ConfigureAwait(false);
await WaitForJob(clone.ActiveJob, 120, false, cancellationToken).ConfigureAwait(false);
var cloned = await repositoryClient.Read(cancellationToken);
Assert.AreEqual(Origin, cloned.Origin);
Assert.AreEqual(workingBranch, cloned.Reference);
Assert.IsNotNull(cloned.RevisionInformation);
Assert.IsNotNull(cloned.RevisionInformation.ActiveTestMerges);
Assert.AreEqual(0, cloned.RevisionInformation.ActiveTestMerges.Count);
Assert.IsNotNull(cloned.RevisionInformation.CommitSha);
Assert.IsNotNull(cloned.RevisionInformation.OriginCommitSha);
Assert.IsNotNull(cloned.RevisionInformation.CompileJobs);
Assert.AreEqual(0, cloned.RevisionInformation.CompileJobs.Count);
Assert.IsNotNull(cloned.RevisionInformation.OriginCommitSha);
Assert.IsNull(cloned.RevisionInformation.PrimaryTestMerge);
Assert.AreEqual(cloned.RevisionInformation.CommitSha, cloned.RevisionInformation.OriginCommitSha);
cloned.Origin = "https://github.com/tgstation/tgstation";
await ApiAssert.ThrowsException<ApiConflictException>(() => repositoryClient.Update(cloned, cancellationToken), ErrorCode.RepoCantChangeOrigin);
cloned.Origin = Origin;
// checkout V3 and back
cloned.Reference = "V3";
var updated = await Checkout(cloned, false, true, cancellationToken);
// Specific SHA
updated.CheckoutSha = "f43f5bd";
await ApiAssert.ThrowsException<ApiConflictException>(() => Checkout(updated, false, false, cancellationToken), ErrorCode.RepoMismatchShaAndReference);
updated.Reference = null;
updated = await Checkout(updated, false, false, cancellationToken);
// Fake SHA
updated.Reference = null;
updated.CheckoutSha = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
updated = await Checkout(updated, true, false, cancellationToken);
// Fake ref
updated.Reference = "Tgs4IntegrationTestFakeBranchNeverNameABranchThis";
updated = await Checkout(updated, true, true, cancellationToken);
// Back
updated.Reference = workingBranch;
updated = await Checkout(updated, false, true, cancellationToken);
var testPRString = Environment.GetEnvironmentVariable("TGS4_TEST_PULL_REQUEST_NUMBER");
if (String.IsNullOrWhiteSpace(testPRString))
testPRString = Environment.GetEnvironmentVariable("APPVEYOR_PULL_REQUEST_NUMBER");
if (String.IsNullOrWhiteSpace(testPRString))
testPRString = Environment.GetEnvironmentVariable("TRAVIS_PULL_REQUEST");
if (!String.IsNullOrWhiteSpace(testPRString))
{
if (!int.TryParse(testPRString, out var prNumber))
Assert.Inconclusive($"Invalid PR #: {testPRString}");
await TestMergeTests(updated, prNumber, cancellationToken);
}
}
async Task<Repository> Checkout(Repository updated, bool expectFailure, bool isRef, CancellationToken cancellationToken)
{
var newRef = isRef ? updated.Reference : updated.CheckoutSha;
var checkingOut = await repositoryClient.Update(updated, cancellationToken);
Assert.IsNotNull(checkingOut.ActiveJob);
await WaitForJob(checkingOut.ActiveJob, 30, expectFailure, cancellationToken);
var result = await repositoryClient.Read(cancellationToken);
if (!expectFailure)
if (isRef)
Assert.AreEqual(newRef, result.Reference);
else
Assert.IsTrue(result.RevisionInformation.CommitSha.StartsWith(newRef, StringComparison.OrdinalIgnoreCase));
Assert.AreEqual(result.RevisionInformation.CommitSha, result.RevisionInformation.OriginCommitSha);
return result;
}
async Task TestMergeTests(Repository repository, int prNumber, CancellationToken cancellationToken)
{
repository.NewTestMerges = new List<TestMergeParameters>
{
new TestMergeParameters
{
Number = prNumber
}
};
var orignCommit = repository.RevisionInformation.OriginCommitSha;
var numberOnlyMerging = await repositoryClient.Update(repository, cancellationToken);
Assert.IsNotNull(numberOnlyMerging.ActiveJob);
Assert.IsTrue(numberOnlyMerging.ActiveJob.Description.Contains(prNumber.ToString()));
await WaitForJob(numberOnlyMerging.ActiveJob, 20, false, cancellationToken);
var withMerge = await repositoryClient.Read(cancellationToken);
Assert.AreEqual(repository.Reference, withMerge.Reference);
Assert.AreEqual(1, withMerge.RevisionInformation.ActiveTestMerges.Count);
Assert.AreEqual(prNumber, withMerge.RevisionInformation.ActiveTestMerges.First().Number);
Assert.AreEqual(prNumber, withMerge.RevisionInformation.PrimaryTestMerge.Number);
var prRevision = withMerge.RevisionInformation.PrimaryTestMerge.PullRequestRevision;
Assert.IsNotNull(prRevision);
Assert.IsNotNull(withMerge.RevisionInformation.PrimaryTestMerge.MergedBy);
Assert.IsNotNull(withMerge.RevisionInformation.PrimaryTestMerge.MergedAt);
Assert.IsNotNull(withMerge.RevisionInformation.PrimaryTestMerge.Author);
Assert.IsNull(withMerge.RevisionInformation.PrimaryTestMerge.Comment);
Assert.IsNotNull(withMerge.RevisionInformation.PrimaryTestMerge.TitleAtMerge);
Assert.IsNotNull(withMerge.RevisionInformation.PrimaryTestMerge.BodyAtMerge);
Assert.AreEqual($"https://github.com/tgstation/tgstation-server/pull/{prNumber}", withMerge.RevisionInformation.PrimaryTestMerge.Url);
Assert.AreEqual(orignCommit, withMerge.RevisionInformation.OriginCommitSha);
Assert.AreNotEqual(orignCommit, withMerge.RevisionInformation.CommitSha);
// Reset, do it again with a comment and specific sha
withMerge.UpdateFromOrigin = true;
withMerge.Reference = repository.Reference;
withMerge.NewTestMerges = new List<TestMergeParameters>
{
new TestMergeParameters
{
Number = prNumber,
Comment = "asdffdsa",
PullRequestRevision = prRevision
}
};
var mergingAgain = await repositoryClient.Update(withMerge, cancellationToken);
Assert.IsNotNull(mergingAgain.ActiveJob);
await WaitForJob(mergingAgain.ActiveJob, 30, false, cancellationToken);
var final = await repositoryClient.Read(cancellationToken);
Assert.AreEqual("asdffdsa", final.RevisionInformation.PrimaryTestMerge.Comment);
Assert.AreEqual(prNumber, final.RevisionInformation.PrimaryTestMerge.Number);
Assert.AreEqual(prRevision, final.RevisionInformation.PrimaryTestMerge.PullRequestRevision);
}
public async Task RunPostWatchdog(CancellationToken cancellationToken)
{
var deleting = await repositoryClient.Delete(cancellationToken);
Assert.IsNotNull(deleting.ActiveJob);
await WaitForJob(deleting.ActiveJob, 60, false, cancellationToken).ConfigureAwait(false);
var deleted = await repositoryClient.Read(cancellationToken).ConfigureAwait(false);
Assert.IsNull(deleted.Origin);
Assert.IsNull(deleted.Reference);
Assert.IsNull(deleted.RevisionInformation);
}
}
}
@@ -125,11 +125,11 @@ namespace Tgstation.Server.Tests
Path = initialPath
}, cancellationToken), ErrorCode.InstanceRelocateOnline).ConfigureAwait(false);
var testSuite1 = new InstanceTest(instanceManagerClient.CreateClient(firstTest), instanceManagerClient);
var instanceClient = instanceManagerClient.CreateClient(firstTest);
var testSuite1 = new InstanceTest(instanceClient, instanceManagerClient);
await testSuite1.RunTests(cancellationToken).ConfigureAwait(false);
//can regain permissions on instance without instance user
var instanceClient = instanceManagerClient.CreateClient(firstTest);
var ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);
await instanceClient.Users.Delete(ourInstanceUser, cancellationToken).ConfigureAwait(false);
@@ -146,6 +146,10 @@ namespace Tgstation.Server.Tests
firstTest.Online = false;
firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
// TODO: Re-enable the rest of these tests once https://github.com/tgstation/tgstation-server/issues/860 is dealt with
return;
await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
var instanceAttachFileName = (string)typeof(InstanceController).GetField("InstanceAttachFileName", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
@@ -232,6 +232,11 @@ namespace Tgstation.Server.Tests
await new InstanceManagerTest(adminClient.Instances, server.Directory).Run(cancellationToken).ConfigureAwait(false);
}
}
catch (Exception ex)
{
Console.WriteLine($"TEST ERROR: {ex.GetType()} in flight!");
throw;
}
finally
{
serverCts.Cancel();
@@ -60,6 +60,19 @@ namespace Tgstation.Server.Tests
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void TestClientVersionFollowingApiVersion()
{
var versionString = versionsPropertyGroup.Element(xmlNamespace + "TgsApiVersion").Value + ".0";
Assert.IsNotNull(versionString);
Assert.IsTrue(Version.TryParse(versionString, out var apiVersion));
versionString = versionsPropertyGroup.Element(xmlNamespace + "TgsClientVersion").Value + ".0";
Assert.IsNotNull(versionString);
Assert.IsTrue(Version.TryParse(versionString, out var clientVersion));
Assert.IsTrue(clientVersion >= apiVersion);
}
[TestMethod]
public void TestWatchdogVersion()
{
+10
View File
@@ -76,11 +76,16 @@ namespace ReleaseNotes
var releaseDictionary = new Dictionary<int, List<string>>();
var authorizedUsers = new Dictionary<long, Task<bool>>();
bool hasSqliteFuckage = false;
async Task GetReleaseNotesFromPR(Issue pullRequest)
{
//need to check it was merged
var fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
if (fullPR.Labels.Any(x => x.Name.Equals("SQLite Unmigratable")))
hasSqliteFuckage = true;
async Task<Milestone> GetMilestone()
{
if (fullPR.Milestone == null)
@@ -242,6 +247,11 @@ namespace ReleaseNotes
var hostWatchdogVersion = Version.Parse(versionsPropertyGroup.Element(xmlNamespace + "TgsHostWatchdogVersion").Value);
prefix = $"#### Component Versions\nCore: {coreVersion}\nHTTP API: {apiVersion}\nDreamMaker API: {dmApiVersion}\n[Web Control Panel](https://github.com/tgstation/tgstation-server-control-panel): {webControlVersion}\nHost Watchdog: {hostWatchdogVersion}";
//hasSqliteFuckage = hasSqliteFuckage && version != new Version(4, 1, 0);
if (hasSqliteFuckage)
prefix = $"{prefix}{Environment.NewLine}{Environment.NewLine}#### THIS VERSION IS INCOMPATIBLE WITH PREVIOUS SQLITE DATABASES!";
break;
case 3:
prefix = "The /tg/station server suite";