mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-23 21:16:52 +01:00
@@ -64,7 +64,6 @@ For the full CI gambit, the following repository configuration must be set:
|
||||

|
||||
- 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.
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user