Merge pull request #1783 from tgstation/EnvFiles

Env files
This commit is contained in:
Jordan Dominion
2024-01-31 22:25:22 -05:00
committed by GitHub
26 changed files with 182 additions and 53 deletions
-1
View File
@@ -64,7 +64,6 @@ For the full CI gambit, the following repository configuration must be set:
![image](https://github.com/tgstation/tgstation-server/assets/8171642/ab17fa74-364f-4e66-b7c4-b9bb24c6a599)
- Label `CI Cleared`: To allow PRs from forks to run CI with secrets after approval.
- Integration [CodeCov](https://github.com/apps/codecov): Enables CodeCov status checks.
- Secret `CI_STATUSES_TOKEN`: A GitHub token with read access to the repository's contents/actions and write access to the repository's checks/security events. Used to create CI completion statuses.
- Secret `CODECOV_TOKEN`: A CodeCov repo token to work around https://github.com/codecov/codecov-action/issues/837.
- Secret `LIVE_TESTS_TOKEN`: A GitHub token with read access to the repository and write access to https://github.com/Cyberboss/common_core (TODO: Make the target repository here configurable). Despite it's name, it may be used across the entire test suite.
- Secret `TGS_TEST_DISCORD_TOKEN`: See above note about test environment variables.
+21 -10
View File
@@ -85,6 +85,10 @@ jobs:
name: Code Scanning
needs: start-ci-run-gate
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
if: (!(cancelled() || failure()) && needs.start-ci-run-gate.result == 'success')
steps:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
@@ -92,14 +96,20 @@ jobs:
dotnet-version: '${{ env.TGS_DOTNET_VERSION }}.0.x'
dotnet-quality: ${{ env.TGS_DOTNET_QUALITY }}
- name: Checkout
- name: Checkout (Branch)
uses: actions/checkout@v4
if: github.event_name == 'push' || github.event_name == 'schedule'
- name: Checkout (PR Merge)
uses: actions/checkout@v4
if: github.event_name != 'push' && github.event_name != 'schedule'
with:
ref: "refs/pull/${{ github.event.number }}/merge"
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: csharp
token: ${{ secrets.CI_STATUSES_TOKEN }}
- name: Build
run: dotnet build -c ReleaseNoWindows -p:TGS_HOST_NO_WEBPANEL=true
@@ -108,8 +118,6 @@ jobs:
uses: github/codeql-action/analyze@v3
with:
category: "/language:csharp"
token: ${{ secrets.CI_STATUSES_TOKEN }}
dmapi-build:
name: Build DMAPI
@@ -610,7 +618,7 @@ jobs:
path: C:/tgs_api.json
- name: Package Server Service
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }}
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' && matrix.database-type == 'PostgresSql' }}
run: |
cd src/Tgstation.Server.Host.Service
dotnet publish -c ${{ matrix.configuration }} -o ../../artifacts/Service
@@ -622,14 +630,14 @@ jobs:
build/RemoveUnsupportedServiceRuntimes.ps1 artifacts/Service
- name: Store Server Service
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }}
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' && matrix.database-type == 'PostgresSql' }}
uses: actions/upload-artifact@v4
with:
name: ServerService
path: artifacts/Service/
- name: Install Code Signing Certificate
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }}
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' && matrix.database-type == 'PostgresSql' }}
shell: powershell
run: |
$pfxBytes = [convert]::FromBase64String("${{ secrets.CODE_SIGNING_BASE64 }}")
@@ -639,7 +647,7 @@ jobs:
rm tg_codesigning.pfx
- name: Test Sign Service .exe
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' }}
if: ${{ matrix.configuration == 'Release' && matrix.watchdog-type == 'Basic' && matrix.database-type == 'PostgresSql' }}
shell: powershell
run: Set-AuthenticodeSignature artifacts/Service/Tgstation.Server.Host.Service.exe -Certificate (Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Thumbprint -eq "${{ vars.CODE_SIGNING_THUMBPRINT }}" }) -TimestampServer "http://timestamp.digicert.com"
@@ -1373,12 +1381,15 @@ jobs:
name: CI Completion Gate
needs: [ pages-build, docker-build, build-deb, build-msi, validate-openapi-spec, upload-code-coverage, check-winget-pr-template, code-scanning ]
runs-on: ubuntu-latest
if: (!(cancelled() || failure()) && needs.pages-build.result == 'success' && needs.docker-build.result == 'success' && needs.build-deb.result == 'success' && needs.build-msi.result == 'success' && needs.validate-openapi-spec.result == 'success' && needs.upload-code-coverage.result == 'success' && needs.check-winget-pr-template.result == 'success')
permissions:
checks: write
contents: read
if: (!(cancelled() || failure()) && needs.pages-build.result == 'success' && needs.docker-build.result == 'success' && needs.build-deb.result == 'success' && needs.build-msi.result == 'success' && needs.validate-openapi-spec.result == 'success' && needs.upload-code-coverage.result == 'success' && needs.check-winget-pr-template.result == 'success' && needs.code-scanning.result == 'success')
steps:
- name: Create Completion Check
uses: LouisBrunner/checks-action@6b626ffbad7cc56fd58627f774b9067e6118af23
with:
token: ${{ secrets.CI_STATUSES_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
name: CI Completion
conclusion: success
output: |
+3 -1
View File
@@ -12,7 +12,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Merge master into dev
uses: robotology/gh-action-nightly-merge@22f5e45d028f22837d617fa07512925457eec184 #v1.3.3
+5 -1
View File
@@ -539,7 +539,11 @@ Manual operations on the repository while an instance is running may lead to git
#### Byond
The `Byond` folder contains installations of [BYOND](https://www.byond.com/) versions. The version which is used by your game code can be changed on a whim (Note that only versions >= 511.1385 have been thouroughly tested. Lower versions should work but if one doesn't function, please open an issue report) and the server will take care of installing it.
The `Byond` folder contains installations of [BYOND](https://www.byond.com/) or [OpenDream](https://github.com/OpenDreamProject/OpenDream) versions. The version which is used by your game code can be changed on a whim (Note that only versions >= 511.1385 have been thouroughly tested. Lower versions should work but if one doesn't function, please open an issue report) and the server will take care of installing it.
##### Environment Variables
You can specify additional environment variables to launch your server/compiler with by adding `server.env`/`compiler.env` to your engine installation directory (i.e. `<instance>/Byond/515.1530/server.env`). These are [.env](https://hexdocs.pm/dotenvy/dotenv-file-format.html) files.
#### Compiler
+2 -2
View File
@@ -18,9 +18,9 @@
<!-- Pinned: Be VERY careful about updating https://github.com/moq/moq/issues/1372 -->
<PackageReference Include="Moq" Version="4.20.70" />
<!-- Usage: MSTest execution -->
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
<!-- Usage: MSTest asserts etc... -->
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
</ItemGroup>
</Project>
@@ -27,7 +27,7 @@
<!-- Usage: HTTP constants reference -->
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<!-- Usage: Decoding the 'nbf' property of JWTs -->
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.1.2" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.3.0" />
<!-- Usage: Primary JSON library -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Usage: Data model annotating -->
@@ -852,6 +852,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in <see langword="true"/> if compilation succeeded, <see langword="false"/> otherwise.</returns>
async ValueTask<bool> RunDreamMaker(IEngineExecutableLock engineLock, Models.CompileJob job, CancellationToken cancellationToken)
{
var environment = await engineLock.LoadEnv(logger, true, cancellationToken);
var arguments = engineLock.FormatCompilerArguments($"{job.DmeName}.{DmeExtension}");
await using var dm = processExecutor.LaunchProcess(
@@ -859,6 +860,7 @@ namespace Tgstation.Server.Host.Components.Deployment
ioManager.ResolvePath(
job.DirectoryName!.Value.ToString()),
arguments,
environment,
readStandardHandles: true,
noShellExecute: true);
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Deployment;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Components.Engine
{
@@ -75,6 +76,7 @@ namespace Tgstation.Server.Host.Components.Engine
/// <summary>
/// Initializes a new instance of the <see cref="ByondInstallation"/> class.
/// </summary>
/// <param name="installationIOManager">The <see cref="IIOManager"/> for the <see cref="EngineInstallationBase"/>.</param>
/// <param name="installationTask">The value of <see cref="InstallationTask"/>.</param>
/// <param name="version">The value of <see cref="Version"/>.</param>
/// <param name="dreamDaemonPath">The value of <see cref="ServerExePath"/>.</param>
@@ -82,12 +84,14 @@ namespace Tgstation.Server.Host.Components.Engine
/// <param name="supportsCli">If a CLI application is being used.</param>
/// <param name="supportsMapThreads">The value of <see cref="supportsMapThreads"/>.</param>
public ByondInstallation(
IIOManager installationIOManager,
Task installationTask,
EngineVersion version,
string dreamDaemonPath,
string dreamMakerPath,
bool supportsCli,
bool supportsMapThreads)
: base(installationIOManager)
{
InstallationTask = installationTask ?? throw new ArgumentNullException(nameof(installationTask));
ArgumentNullException.ThrowIfNull(version);
@@ -88,21 +88,22 @@ namespace Tgstation.Server.Host.Components.Engine
{
CheckVersionValidity(version);
var binPathForVersion = IOManager.ConcatPath(path, ByondBinPath);
var installationIOManager = new ResolvingIOManager(IOManager, path);
var supportsMapThreads = version.Version >= MapThreadsVersion;
return new ByondInstallation(
installationIOManager,
installationTask,
version,
IOManager.ResolvePath(
IOManager.ConcatPath(
binPathForVersion,
installationIOManager.ResolvePath(
installationIOManager.ConcatPath(
ByondBinPath,
GetDreamDaemonName(
version.Version!,
out var supportsCli))),
IOManager.ResolvePath(
IOManager.ConcatPath(
binPathForVersion,
installationIOManager.ResolvePath(
installationIOManager.ConcatPath(
ByondBinPath,
DreamMakerName)),
supportsCli,
supportsMapThreads);
@@ -62,5 +62,9 @@ namespace Tgstation.Server.Host.Components.Engine
accessIdentifier,
port,
cancellationToken);
/// <inheritdoc />
public ValueTask<Dictionary<string, string>?> LoadEnv(ILogger logger, bool forCompiler, CancellationToken cancellationToken)
=> Instance.LoadEnv(logger, forCompiler, cancellationToken);
}
}
@@ -1,15 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using DotEnv.Core;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Deployment;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.Components.Engine
@@ -38,6 +42,11 @@ namespace Tgstation.Server.Host.Components.Engine
/// <inheritdoc />
public abstract Task InstallationTask { get; }
/// <summary>
/// The <see cref="IIOManager"/> pointing to the installation directory.
/// </summary>
protected IIOManager InstallationIOManager { get; }
/// <summary>
/// Encode given parameters for passing as world.params on the command line.
/// </summary>
@@ -56,6 +65,15 @@ namespace Tgstation.Server.Host.Components.Engine
return parametersString;
}
/// <summary>
/// Initializes a new instance of the <see cref="EngineInstallationBase"/> class.
/// </summary>
/// <param name="installationIOManager">The value of <see cref="InstallationIOManager"/>.</param>
public EngineInstallationBase(IIOManager installationIOManager)
{
InstallationIOManager = installationIOManager ?? throw new ArgumentNullException(nameof(installationIOManager));
}
/// <inheritdoc />
public abstract string FormatCompilerArguments(string dmePath);
@@ -69,10 +87,45 @@ namespace Tgstation.Server.Host.Components.Engine
/// <inheritdoc />
public virtual async ValueTask StopServerProcess(ILogger logger, IProcess process, string accessIdentifier, ushort port, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(logger);
cancellationToken.ThrowIfCancellationRequested();
logger.LogTrace("Terminating engine server process...");
process.Terminate();
await process.Lifetime;
}
/// <inheritdoc />
public async ValueTask<Dictionary<string, string>?> LoadEnv(ILogger logger, bool forCompiler, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(logger);
var envFile = forCompiler
? "compiler.env"
: "server.env";
if (!await InstallationIOManager.FileExists(envFile, cancellationToken))
{
logger.LogTrace("No {envFile} present in engine installation {version}", envFile, Version);
return null;
}
logger.LogDebug("Loading {envFile} for engine installation {version}...", envFile, Version);
var fileBytes = await InstallationIOManager.ReadAllBytes(envFile, cancellationToken);
var fileContents = Encoding.UTF8.GetString(fileBytes);
var parser = new EnvParser();
try
{
var variables = parser.Parse(fileContents);
return variables.ToDictionary();
}
catch (Exception ex)
{
logger.LogWarning(ex, "Unable to parse {envFile}!", envFile);
return null;
}
}
}
}
@@ -82,5 +82,14 @@ namespace Tgstation.Server.Host.Components.Engine
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="ValueTask"/> representing the running operation.</returns>
ValueTask StopServerProcess(ILogger logger, IProcess process, string accessIdentifier, ushort port, CancellationToken cancellationToken);
/// <summary>
/// Loads the environment settings for either the server or compiler.
/// </summary>
/// <param name="logger">The <see cref="ILogger"/> to write to.</param>
/// <param name="forCompiler">If <see langword="false"/> server.env will be loaded. If <see langword="true"/> compiler.env will be loaded.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
/// <returns>A <see cref="ValueTask{TResult}"/> resulting in the environment <see cref="Dictionary{TKey, TValue}"/> or <see langword="null"/> if the target environment file doesn't exist.</returns>
ValueTask<Dictionary<string, string>?> LoadEnv(ILogger logger, bool forCompiler, CancellationToken cancellationToken);
}
}
@@ -47,11 +47,6 @@ namespace Tgstation.Server.Host.Components.Engine
/// <inheritdoc />
public override Task InstallationTask { get; }
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="OpenDreamInstallation"/>.
/// </summary>
readonly IIOManager ioManager;
/// <summary>
/// The <see cref="IAsyncDelayer"/> for the <see cref="OpenDreamInstallation"/>.
/// </summary>
@@ -65,7 +60,7 @@ namespace Tgstation.Server.Host.Components.Engine
/// <summary>
/// Initializes a new instance of the <see cref="OpenDreamInstallation"/> class.
/// </summary>
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
/// <param name="installationIOManager">The <see cref="IIOManager"/> for the <see cref="EngineInstallationBase"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="httpClientFactory">The value of <see cref="httpClientFactory"/>.</param>
/// <param name="serverExePath">The value of <see cref="ServerExePath"/>.</param>
@@ -73,15 +68,15 @@ namespace Tgstation.Server.Host.Components.Engine
/// <param name="installationTask">The value of <see cref="InstallationTask"/>.</param>
/// <param name="version">The value of <see cref="Version"/>.</param>
public OpenDreamInstallation(
IIOManager ioManager,
IIOManager installationIOManager,
IAsyncDelayer asyncDelayer,
IAbstractHttpClientFactory httpClientFactory,
string serverExePath,
string compilerExePath,
Task installationTask,
EngineVersion version)
: base(installationIOManager)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
ServerExePath = serverExePath ?? throw new ArgumentNullException(nameof(serverExePath));
@@ -109,7 +104,7 @@ namespace Tgstation.Server.Host.Components.Engine
var parametersString = EncodeParameters(parameters, launchParameters);
var arguments = $"--cvar {(logFilePath != null ? $"log.path=\"{ioManager.GetDirectoryName(logFilePath)}\" --cvar log.format=\"{ioManager.GetFileName(logFilePath)}\"" : "log.enabled=false")} --cvar watchdog.token={accessIdentifier} --cvar log.runtimelog=false --cvar net.port={launchParameters.Port!.Value} --cvar opendream.topic_port=0 --cvar opendream.world_params=\"{parametersString}\" --cvar opendream.json_path=\"./{dmbProvider.DmbName}\"";
var arguments = $"--cvar {(logFilePath != null ? $"log.path=\"{InstallationIOManager.GetDirectoryName(logFilePath)}\" --cvar log.format=\"{InstallationIOManager.GetFileName(logFilePath)}\"" : "log.enabled=false")} --cvar watchdog.token={accessIdentifier} --cvar log.runtimelog=false --cvar net.port={launchParameters.Port!.Value} --cvar opendream.topic_port=0 --cvar opendream.world_params=\"{parametersString}\" --cvar opendream.json_path=\"./{dmbProvider.DmbName}\"";
return arguments;
}
@@ -125,6 +120,8 @@ namespace Tgstation.Server.Host.Components.Engine
ushort port,
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(logger);
const int MaximumTerminationSeconds = 5;
logger.LogTrace("Attempting Robust.Server graceful exit (Timeout: {seconds}s)...", MaximumTerminationSeconds);
@@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Components.Engine
CheckVersionValidity(version);
GetExecutablePaths(path, out var serverExePath, out var compilerExePath);
return new OpenDreamInstallation(
IOManager,
new ResolvingIOManager(IOManager, path),
asyncDelayer,
httpClientFactory,
serverExePath,
@@ -258,6 +258,7 @@ namespace Tgstation.Server.Host.Components.Engine
shortenedPath,
$"run -c Release --project OpenDreamPackageTool -- --tgs -o {shortenedDeployPath}",
null,
null,
!GeneralConfiguration.OpenDreamSuppressInstallOutput,
!GeneralConfiguration.OpenDreamSuppressInstallOutput);
@@ -490,6 +490,7 @@ namespace Tgstation.Server.Host.Components.Session
CancellationToken cancellationToken)
{
// important to run on all ports to allow port changing
var environment = await engineLock.LoadEnv(logger, false, cancellationToken);
var arguments = engineLock.FormatServerArguments(
dmbProvider,
new Dictionary<string, string>
@@ -507,6 +508,7 @@ namespace Tgstation.Server.Host.Components.Session
engineLock.ServerExePath,
dmbProvider.Directory,
arguments,
environment,
logFilePath,
engineLock.HasStandardOutput,
true);
@@ -1,4 +1,6 @@
namespace Tgstation.Server.Host.System
using System.Collections.Generic;
namespace Tgstation.Server.Host.System
{
/// <summary>
/// For launching <see cref="IProcess"/>'.
@@ -11,6 +13,7 @@
/// <param name="fileName">The full path to the executable file.</param>
/// <param name="workingDirectory">The working directory for the <see cref="IProcess"/>.</param>
/// <param name="arguments">The arguments for the <see cref="IProcess"/>.</param>
/// <param name="environment">A <see cref="IReadOnlyDictionary{TKey, TValue}"/> of environment variables to set.</param>
/// <param name="fileRedirect">File to write process output and error streams to. Requires <paramref name="readStandardHandles"/> to be <see langword="true"/>.</param>
/// <param name="readStandardHandles">If the process output and error streams should be read.</param>
/// <param name="noShellExecute">If shell execute should not be used. Must be set if <paramref name="readStandardHandles"/> is set.</param>
@@ -19,6 +22,7 @@
string fileName,
string workingDirectory,
string arguments,
IReadOnlyDictionary<string, string>? environment = null,
string? fileRedirect = null,
bool readStandardHandles = false,
bool noShellExecute = false);
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Channels;
@@ -107,6 +109,7 @@ namespace Tgstation.Server.Host.System
string fileName,
string workingDirectory,
string arguments,
IReadOnlyDictionary<string, string>? environment,
string? fileRedirect,
bool readStandardHandles,
bool noShellExecute)
@@ -115,24 +118,33 @@ namespace Tgstation.Server.Host.System
ArgumentNullException.ThrowIfNull(workingDirectory);
ArgumentNullException.ThrowIfNull(arguments);
var enviromentLogLines = environment == null
? String.Empty
: String.Concat(environment.Select(kvp => $"{Environment.NewLine}\t- {kvp.Key}={kvp.Value}"));
if (noShellExecute)
logger.LogDebug(
"Launching process in {workingDirectory}: {exe} {arguments}",
"Launching process in {workingDirectory}: {exe} {arguments}{environment}",
workingDirectory,
fileName,
arguments);
arguments,
enviromentLogLines);
else
logger.LogDebug(
"Shell launching process in {workingDirectory}: {exe} {arguments}",
"Shell launching process in {workingDirectory}: {exe} {arguments}{environment}",
workingDirectory,
fileName,
arguments);
arguments,
enviromentLogLines);
var handle = new global::System.Diagnostics.Process();
try
{
handle.StartInfo.FileName = fileName;
handle.StartInfo.Arguments = arguments;
if (environment != null)
foreach (var kvp in environment)
handle.StartInfo.Environment.Add(kvp!);
handle.StartInfo.WorkingDirectory = workingDirectory;
handle.StartInfo.UseShellExecute = !noShellExecute;
@@ -69,6 +69,8 @@
<PackageReference Include="Cyberboss.AspNetCore.AsyncInitializer" Version="1.2.0" />
<!-- Usage: IRC interop -->
<PackageReference Include="Cyberboss.SmartIrc4net.Standard" Version="0.4.7" />
<!-- Usage: .env file parsing -->
<PackageReference Include="DotEnv.Core" Version="3.0.0" />
<!-- Usage: Text formatter for Elasticsearch logging plugin -->
<PackageReference Include="Elastic.CommonSchema.Serilog" Version="8.6.1" />
<!-- Usage: GitLab interop -->
@@ -98,7 +100,7 @@
<!-- Usage: PostgresSQL ORM plugin -->
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<!-- Usage: GitHub.com interop -->
<PackageReference Include="Octokit" Version="9.1.0" />
<PackageReference Include="Octokit" Version="9.1.1" />
<!-- Usage: MYSQL/MariaDB ORM plugin -->
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2" />
<!-- Usage: Discord interop -->
@@ -124,7 +126,7 @@
<!-- Usage: Temporary resolution to compatibility issues with EFCore 7 and .NET 8 -->
<PackageReference Include="System.Security.Permissions" Version="8.0.0" />
<!-- Usage: .DeleteAsync() support for IQueryable<T>s -->
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="8.101.1.3" />
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="8.101.2.1" />
</ItemGroup>
<ItemGroup>
@@ -0,0 +1,4 @@
cd /D "%~dp0"
cd ../../Byond/%1
echo # Comment > server.env
echo NOTA=Real Comment>> server.env
@@ -0,0 +1,7 @@
#!/bin/bash
set -e
cd "../../Byond/$1"
echo -e '# This is a comment\nNOTA=Real Comment\n\n\n' > server.env
@@ -69,6 +69,7 @@ namespace Tgstation.Server.Host.System.Tests
pathToSignalTestApp,
$"run -c {CurrentConfig} --no-build",
null,
null,
true,
true);
@@ -118,18 +118,24 @@ namespace Tgstation.Server.Tests.Live.Instance
await using var memoryStream2 = new MemoryStream(Encoding.UTF8.GetBytes("bbb"));
await configurationClient.Write(staticFile2, memoryStream2, cancellationToken);
var shellScriptExtension = new PlatformIdentifier().IsWindows ? ".bat" : ".sh";
var scriptName = $"PreCompile-GenerateRandomResource{shellScriptExtension}";
var resourcingScript = new ConfigurationFileRequest
async ValueTask UploadScript(string scriptId)
{
Path = $"/EventScripts/{scriptName}"
};
var shellScriptExtension = new PlatformIdentifier().IsWindows ? ".bat" : ".sh";
var scriptName = $"{scriptId}{shellScriptExtension}";
var resourcingScript = new ConfigurationFileRequest
{
Path = $"/EventScripts/{scriptName}"
};
await using var readStream = ioManager.GetFileStream($"../../../../DMAPI/LongRunning/{scriptName}", false);
await configurationClient.Write(
resourcingScript,
readStream,
cancellationToken);
await using var readStream = ioManager.GetFileStream($"../../../../DMAPI/LongRunning/{scriptName}", false);
await configurationClient.Write(
resourcingScript,
readStream,
cancellationToken);
}
await UploadScript("PreCompile-GenerateRandomResource");
await UploadScript("EngineActiveVersionChange-SetupEnv");
}
return ValueTaskExtensions.WhenAll(
@@ -1105,6 +1105,7 @@ namespace Tgstation.Server.Tests.Live
repoPath,
args,
null,
null,
true,
true);
@@ -28,7 +28,7 @@ namespace Tgstation.Server.Tests
Mock.Of<ILogger<ProcessExecutor>>(),
loggerFactory);
await using var process = processExecutor.LaunchProcess("test." + platformIdentifier.ScriptFileExtension, ".", string.Empty, null, true, true);
await using var process = processExecutor.LaunchProcess("test." + platformIdentifier.ScriptFileExtension, ".", string.Empty, null, null, true, true);
using var cts = new CancellationTokenSource();
cts.CancelAfter(3000);
var exitCode = await process.Lifetime.WaitAsync(cts.Token);
@@ -63,7 +63,7 @@ namespace Tgstation.Server.Tests
File.Delete(tempFile);
try
{
await using (var process = processExecutor.LaunchProcess("test." + platformIdentifier.ScriptFileExtension, ".", string.Empty, tempFile, true, true))
await using (var process = processExecutor.LaunchProcess("test." + platformIdentifier.ScriptFileExtension, ".", string.Empty, null, tempFile, true, true))
{
using var cts = new CancellationTokenSource();
cts.CancelAfter(3000);
@@ -503,6 +503,7 @@ namespace Tgstation.Server.Tests
Environment.CurrentDirectory,
"fake.dmb -map-threads 3 -close",
null,
null,
true,
true);
+3 -1
View File
@@ -155,6 +155,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LongRunning", "LongRunning", "{EB1DDE8C-CA6F-4BE3-947B-597CA8EABEA5}"
ProjectSection(SolutionItems) = preProject
tests\DMAPI\LongRunning\Config.dm = tests\DMAPI\LongRunning\Config.dm
tests\DMAPI\LongRunning\EngineActiveVersionChange-SetupEnv.bat = tests\DMAPI\LongRunning\EngineActiveVersionChange-SetupEnv.bat
tests\DMAPI\LongRunning\EngineActiveVersionChange-SetupEnv.sh = tests\DMAPI\LongRunning\EngineActiveVersionChange-SetupEnv.sh
tests\DMAPI\LongRunning\long_running_test.dme = tests\DMAPI\LongRunning\long_running_test.dme
tests\DMAPI\LongRunning\long_running_test_copy.dme = tests\DMAPI\LongRunning\long_running_test_copy.dme
tests\DMAPI\LongRunning\long_running_test_rooted.dme = tests\DMAPI\LongRunning\long_running_test_rooted.dme
@@ -171,8 +173,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiFree", "ApiFree", "{7B8F
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BasicOperation", "BasicOperation", "{F32B9514-AAD9-429D-841A-ED810FC2598C}"
ProjectSection(SolutionItems) = preProject
tests\DMAPI\BasicOperation\Config.dm = tests\DMAPI\BasicOperation\Config.dm
tests\DMAPI\BasicOperation\basic operation_test.dme = tests\DMAPI\BasicOperation\basic operation_test.dme
tests\DMAPI\BasicOperation\Config.dm = tests\DMAPI\BasicOperation\Config.dm
tests\DMAPI\BasicOperation\Test.dm = tests\DMAPI\BasicOperation\Test.dm
EndProjectSection
EndProject