diff --git a/.github/workflows/ci-suite.yml b/.github/workflows/ci-suite.yml
index 1e33654d09..3358498148 100644
--- a/.github/workflows/ci-suite.yml
+++ b/.github/workflows/ci-suite.yml
@@ -31,7 +31,7 @@ jobs:
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
- sudo apt-get install -y libc6-i386 libstdc++6:i386
+ sudo apt-get install -y -o APT::Immediate-Configure=0 libc6-i386 libstdc++6:i386
- name: Install BYOND
if: steps.cache-byond.outputs.cache-hit != 'true'
@@ -315,7 +315,7 @@ jobs:
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
- sudo apt-get install -y libc6-i386 libstdc++6:i386 gdb
+ sudo apt-get install -y -o APT::Immediate-Configure=0 libc6-i386 libstdc++6:i386 gdb
- name: Install Node 12.X
uses: actions/setup-node@v1
diff --git a/README.md b/README.md
index a7e467f3d3..f9cd540fdd 100644
--- a/README.md
+++ b/README.md
@@ -452,7 +452,7 @@ Should you end up with a lost database for some reason or want to reattach a det
## Troubleshooting
-Feel free to ask for help at the coderbus discord in \#hosting-questions: https://discord.gg/Vh8TJp9. Cyberboss#0016 can answer most questions.
+Feel free to ask for help [on the discussions page](https://github.com/tgstation/tgstation-server/discussions).
## Contributing
diff --git a/build/Version.props b/build/Version.props
index f63b1c518b..1eb3527d2a 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -3,7 +3,7 @@
- 4.8.1
+ 4.8.2
2.3.0
8.3.0
9.2.0
diff --git a/src/Tgstation.Server.Host/Controllers/SwarmController.cs b/src/Tgstation.Server.Host/Controllers/SwarmController.cs
index 1c2409dd8a..473df47a38 100644
--- a/src/Tgstation.Server.Host/Controllers/SwarmController.cs
+++ b/src/Tgstation.Server.Host/Controllers/SwarmController.cs
@@ -235,7 +235,7 @@ namespace Tgstation.Server.Host.Controllers
return;
}
- logger.LogDebug("Starting swarm request processing...");
+ logger.LogTrace("Starting swarm request processing...");
await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
}
}
diff --git a/src/Tgstation.Server.Host/Core/GitHubClientFactory.cs b/src/Tgstation.Server.Host/Core/GitHubClientFactory.cs
index 218a19bf4f..b77f48478c 100644
--- a/src/Tgstation.Server.Host/Core/GitHubClientFactory.cs
+++ b/src/Tgstation.Server.Host/Core/GitHubClientFactory.cs
@@ -1,5 +1,7 @@
using System;
+using Microsoft.Extensions.Options;
using Octokit;
+using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.Core
@@ -12,35 +14,43 @@ namespace Tgstation.Server.Host.Core
///
readonly IAssemblyInformationProvider assemblyInformationProvider;
+ ///
+ /// The for the .
+ ///
+ readonly GeneralConfiguration generalConfiguration;
+
///
/// Construct a
///
- /// The value of
- public GitHubClientFactory(IAssemblyInformationProvider assemblyInformationProvider)
+ /// The value of .
+ /// The containing the value of .
+ public GitHubClientFactory(IAssemblyInformationProvider assemblyInformationProvider, IOptions generalConfigurationOptions)
{
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
+ generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
}
///
- /// Create a
+ /// Create a .
///
+ /// Optional access token to use as credentials.
/// A new
- GitHubClient CreateBaseClient() => new GitHubClient(
- new ProductHeaderValue(
- assemblyInformationProvider.ProductInfoHeaderValue.Product.Name,
- assemblyInformationProvider.ProductInfoHeaderValue.Product.Version));
-
- ///
- public IGitHubClient CreateClient() => CreateBaseClient();
-
- ///
- public IGitHubClient CreateClient(string accessToken)
+ GitHubClient CreateClientImpl(string accessToken)
{
- if (accessToken == null)
- throw new ArgumentNullException(nameof(accessToken));
- var result = CreateBaseClient();
- result.Credentials = new Credentials(accessToken);
- return result;
+ var client = new GitHubClient(
+ new ProductHeaderValue(
+ assemblyInformationProvider.ProductInfoHeaderValue.Product.Name,
+ assemblyInformationProvider.ProductInfoHeaderValue.Product.Version));
+ if (accessToken != null)
+ client.Credentials = new Credentials(accessToken);
+
+ return client;
}
+
+ ///
+ public IGitHubClient CreateClient() => CreateClientImpl(generalConfiguration.GitHubAccessToken);
+
+ ///
+ public IGitHubClient CreateClient(string accessToken) => CreateClientImpl(accessToken ?? throw new ArgumentNullException(nameof(accessToken)));
}
}
diff --git a/src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs b/src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs
index 68cf07d9e7..d91962bf50 100644
--- a/src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs
+++ b/src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs
@@ -8,7 +8,7 @@ namespace Tgstation.Server.Host.Core
public interface IGitHubClientFactory
{
///
- /// Create a client with anonymous authentication or general authentica. Low rate limit. Attempts to use the server's token to bypass this.
+ /// Create a client. Low rate limit unless the server's GitHubAccessToken is set to bypass it.
///
/// A new .
IGitHubClient CreateClient();
diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
index ed94445764..1b11dd58b1 100644
--- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs
+++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
@@ -535,6 +535,11 @@ namespace Tgstation.Server.Host.Swarm
return false;
}
}
+ else
+ {
+ logger.LogTrace("No need to re-initiate update as it originated here on the swarm controller");
+ updateCommitTcs = new TaskCompletionSource();
+ }
logger.LogDebug("Prepared for update to version {0}", version);
}
diff --git a/tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs b/tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs
index 7a8c565f6b..6c3b29c467 100644
--- a/tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs
+++ b/tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs
@@ -1,9 +1,11 @@
+using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Octokit;
using System;
using System.Net.Http.Headers;
using System.Threading.Tasks;
+using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.Core.Tests
@@ -12,7 +14,11 @@ namespace Tgstation.Server.Host.Core.Tests
public sealed class TestGitHubClientFactory
{
[TestMethod]
- public void TestContruction() => Assert.ThrowsException(() => new GitHubClientFactory(null));
+ public void TestContruction()
+ {
+ Assert.ThrowsException(() => new GitHubClientFactory(Mock.Of(), null));
+ Assert.ThrowsException(() => new GitHubClientFactory(null, null));
+ }
[TestMethod]
public async Task TestCreateBasicClient()
@@ -20,7 +26,12 @@ namespace Tgstation.Server.Host.Core.Tests
var mockApp = new Mock();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
- var factory = new GitHubClientFactory(mockApp.Object);
+ var mockOptions = new Mock>();
+
+ var gc = new GeneralConfiguration();
+ Assert.IsNull(gc.GitHubAccessToken);
+ mockOptions.SetupGet(x => x.Value).Returns(gc);
+ var factory = new GitHubClientFactory(mockApp.Object, mockOptions.Object);
var client = factory.CreateClient();
Assert.IsNotNull(client);
@@ -28,6 +39,12 @@ namespace Tgstation.Server.Host.Core.Tests
Assert.AreEqual(AuthenticationType.Anonymous, credentials.AuthenticationType);
+ gc.GitHubAccessToken = "asdfasdfasdfasdfasdfasdf";
+ client = factory.CreateClient();
+ Assert.IsNotNull(client);
+ credentials = await client.Connection.CredentialStore.GetCredentials().ConfigureAwait(false);
+
+ Assert.AreEqual(AuthenticationType.Oauth, credentials.AuthenticationType);
mockApp.VerifyAll();
}
@@ -38,7 +55,9 @@ namespace Tgstation.Server.Host.Core.Tests
var mockApp = new Mock();
mockApp.SetupGet(x => x.ProductInfoHeaderValue).Returns(new ProductInfoHeaderValue("TGSTests", "1.2.3")).Verifiable();
- var factory = new GitHubClientFactory(mockApp.Object);
+ var mockOptions = new Mock>();
+ mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration());
+ var factory = new GitHubClientFactory(mockApp.Object, mockOptions.Object);
Assert.ThrowsException(() => factory.CreateClient(null));
diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs
index 83b09adc0f..7353aab914 100644
--- a/tests/Tgstation.Server.Tests/IntegrationTest.cs
+++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs
@@ -257,7 +257,7 @@ namespace Tgstation.Server.Tests
await Assert.ThrowsExceptionAsync(() => node1Client.Instances.GetId(controllerInstance, cancellationToken));
// test update
- var testUpdateVersion = new Version(4, 6, 2);
+ var testUpdateVersion = new Version(4, 8, 1);
await node1Client.Administration.Update(
new Administration
{
@@ -276,11 +276,36 @@ namespace Tgstation.Server.Tests
var updatedAssemblyVersion = FileVersionInfo.GetVersionInfo(updatedAssemblyPath);
Assert.AreEqual(testUpdateVersion, Version.Parse(updatedAssemblyVersion.FileVersion).Semver());
+ Directory.Delete(server.UpdatePath, true);
}
CheckServerUpdated(controller);
CheckServerUpdated(node1);
CheckServerUpdated(node2);
+
+ // regression: test it also works from the controller
+ serverTask = Task.WhenAll(
+ node1.Run(cancellationToken),
+ node2.Run(cancellationToken),
+ controller.Run(cancellationToken));
+
+ using var controllerClient2 = await CreateAdminClient(controller.Url, cancellationToken);
+ using var node1Client2 = await CreateAdminClient(node1.Url, cancellationToken);
+ using var node2Client2 = await CreateAdminClient(node2.Url, cancellationToken);
+
+ await controllerClient2.Administration.Update(
+ new Administration
+ {
+ NewVersion = testUpdateVersion
+ },
+ cancellationToken);
+
+ await Task.WhenAny(Task.Delay(TimeSpan.FromMinutes(2)), serverTask);
+ Assert.IsTrue(serverTask.IsCompleted);
+
+ CheckServerUpdated(controller);
+ CheckServerUpdated(node1);
+ CheckServerUpdated(node2);
}
finally
{