diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransferRetriesTimeout.cs b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransferRetriesTimeout.cs index d2e5784d1..10e1ca10f 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransferRetriesTimeout.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransferRetriesTimeout.cs @@ -2,18 +2,18 @@ using System.Collections; using System.Diagnostics; using System.IO; +using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Halibut; using NUnit.Framework; +using Octopus.Client.Extensions; using Octopus.Tentacle.CommonTestUtils.Diagnostics; using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; -using Octopus.Tentacle.Tests.Integration.Support.ExtensionMethods; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; -using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Util.TcpTentacleHelpers; using Octopus.TestPortForwarder; @@ -33,6 +33,10 @@ public class ClientFileTransferRetriesTimeout : IntegrationTest [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None, additionalParameterTypes: new object[] { typeof(StopPortForwarderAfterFirstCallValues) })] public async Task WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled(TentacleConfigurationTestCase tentacleConfigurationTestCase, bool stopPortForwarderAfterFirstCall) { + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + PortForwarder portForwarder = null!; await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateBuilder() // Set a short retry duration so we cancel fairly quickly @@ -73,6 +77,7 @@ public async Task WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled(T .Build(CancellationToken); portForwarder = clientAndTentacle.PortForwarder; + Logger.Information($"WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled Available Disk space after clientAndTentacle.PortForwarder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var inMemoryLog = new InMemoryLog(); @@ -83,6 +88,8 @@ public async Task WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled(T var duration = Stopwatch.StartNew(); var executeScriptTask = clientAndTentacle.TentacleClient.UploadFile(remotePath, dataStream, CancellationToken, inMemoryLog); + Logger.Information($"WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled Available Disk space after TentacleClient.UploadFile: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + var expectedException = new ExceptionContractAssertionBuilder(FailureScenario.ConnectionFaulted, tentacleConfigurationTestCase.TentacleType, clientAndTentacle).Build(); await AssertionExtensions.Should(async () => await executeScriptTask).ThrowExceptionContractAsync(expectedException); @@ -90,6 +97,8 @@ public async Task WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled(T methodUsages.For(nameof(IAsyncClientFileTransferService.UploadFileAsync)).Started.Should().BeGreaterOrEqualTo(2); methodUsages.For(nameof(IAsyncClientFileTransferService.DownloadFileAsync)).Started.Should().Be(0); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled Available Disk space after assertion: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); // Ensure we actually waited and retried until the timeout policy kicked in duration.Elapsed.Should().BeGreaterOrEqualTo(clientAndTentacle.RpcRetrySettings.RetryDuration - retryIfRemainingDurationAtLeastBuffer - retryBackoffBuffer); @@ -100,7 +109,12 @@ public async Task WhenRpcRetriesTimeOut_DuringUploadFile_TheRpcCallIsCancelled(T [Test] [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None)] public async Task WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut(TentacleConfigurationTestCase tentacleConfigurationTestCase) - { + { + + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + Logger.Information($"WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + var retryDuration = TimeSpan.FromSeconds(15); await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateBuilder() @@ -131,11 +145,14 @@ public async Task WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCall var executeScriptTask = clientAndTentacle.TentacleClient.UploadFile(remotePath, dataStream, CancellationToken, inMemoryLog); var expectedException = new ExceptionContractAssertionBuilder(FailureScenario.ConnectionFaulted, tentacleConfigurationTestCase.TentacleType, clientAndTentacle).Build(); + Logger.Information($"WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space after expectedException: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); await AssertionExtensions.Should(async () => await executeScriptTask).ThrowExceptionContractAsync(expectedException); methodUsages.For(nameof(IAsyncClientFileTransferService.UploadFileAsync)).Started.Should().Be(1); methodUsages.For(nameof(IAsyncClientFileTransferService.DownloadFileAsync)).Started.Should().Be(0); + + Logger.Information($"WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space after assertions: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); inMemoryLog.ShouldHaveLoggedRetryFailureAndNoRetryAttempts(); } @@ -144,6 +161,10 @@ public async Task WhenUploadFileFails_AndTakesLongerThanTheRetryDuration_TheCall [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None, additionalParameterTypes: new object[] { typeof(StopPortForwarderAfterFirstCallValues) })] public async Task WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled(TentacleConfigurationTestCase tentacleConfigurationTestCase, bool stopPortForwarderAfterFirstCall) { + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + PortForwarder portForwarder = null!; await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateBuilder() // Set a short retry duration so we cancel fairly quickly @@ -185,14 +206,18 @@ public async Task WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled .Build(CancellationToken); portForwarder = clientAndTentacle.PortForwarder; + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space after CreateLegacyBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); using var tempFile = new RandomTemporaryFileBuilder().Build(); + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space after RandomTemporaryFileBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var inMemoryLog = new InMemoryLog(); - + // Start the script which will wait for a file to exist var duration = Stopwatch.StartNew(); var executeScriptTask = clientAndTentacle.TentacleClient.DownloadFile(tempFile.File.FullName, CancellationToken, inMemoryLog); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space after TentacleClient.DownloadFile: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var expectedException = new ExceptionContractAssertionBuilder(FailureScenario.ConnectionFaulted, tentacleConfigurationTestCase.TentacleType, clientAndTentacle).Build(); @@ -202,6 +227,8 @@ public async Task WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled recordedUsages.For(nameof(IAsyncClientFileTransferService.DownloadFileAsync)).Started.Should().BeGreaterOrEqualTo(2); recordedUsages.For(nameof(IAsyncClientFileTransferService.UploadFileAsync)).Started.Should().Be(0); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space after recordedUsages: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); // Ensure we actually waited and retried until the timeout policy kicked in duration.Elapsed.Should().BeGreaterOrEqualTo(clientAndTentacle.RpcRetrySettings.RetryDuration - retryIfRemainingDurationAtLeastBuffer - retryBackoffBuffer); @@ -213,6 +240,10 @@ public async Task WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None)] public async Task WhenDownloadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut(TentacleConfigurationTestCase tentacleConfigurationTestCase) { + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + Logger.Information($"WhenDownloadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + var retryDuration = TimeSpan.FromSeconds(15); await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateBuilder() @@ -238,14 +269,20 @@ public async Task WhenDownloadFileFails_AndTakesLongerThanTheRetryDuration_TheCa .Build(CancellationToken); using var tempFile = new RandomTemporaryFileBuilder().Build(); + Logger.Information($"WhenDownloadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space after RandomTemporaryFileBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + var inMemoryLog = new InMemoryLog(); var executeScriptTask = clientAndTentacle.TentacleClient.DownloadFile(tempFile.File.FullName, CancellationToken, inMemoryLog); + + Logger.Information($"WhenRpcRetriesTimeOut_DuringDownloadFile_TheRpcCallIsCancelled Available Disk space after TentacleClient.DownloadFile: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); Func> action = async () => await executeScriptTask; await action.Should().ThrowAsync(); recordedUsages.For(nameof(IAsyncClientFileTransferService.DownloadFileAsync)).Started.Should().Be(1); recordedUsages.For(nameof(IAsyncClientFileTransferService.UploadFileAsync)).Started.Should().Be(0); + + Logger.Information($"WhenDownloadFileFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut Available Disk space after recordedUsages: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); inMemoryLog.ShouldHaveLoggedRetryFailureAndNoRetryAttempts(); } diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreNotRetriedWhenRetriesAreDisabled.cs b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreNotRetriedWhenRetriesAreDisabled.cs index b8ebd1261..921ade73f 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreNotRetriedWhenRetriesAreDisabled.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreNotRetriedWhenRetriesAreDisabled.cs @@ -7,6 +7,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Util.TcpTentacleHelpers; diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreRetriedWhenRetriesAreEnabled.cs b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreRetriedWhenRetriesAreEnabled.cs index df282f0fd..e1db7b2be 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreRetriedWhenRetriesAreEnabled.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientFileTransfersAreRetriedWhenRetriesAreEnabled.cs @@ -10,6 +10,7 @@ using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; using Octopus.Tentacle.Tests.Integration.Support.ExtensionMethods; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Util.TcpTentacleHelpers; diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientGathersRpcCallMetrics.cs b/source/Octopus.Tentacle.Tests.Integration/ClientGathersRpcCallMetrics.cs index 5975f8ded..c06b15995 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientGathersRpcCallMetrics.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientGathersRpcCallMetrics.cs @@ -12,6 +12,7 @@ using Octopus.Tentacle.Contracts.ScriptServiceV2; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -22,6 +23,7 @@ public class ClientGathersRpcCallMetrics : IntegrationTest { [Test] [TentacleConfigurations(testCommonVersions: true)] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public async Task ExecuteScriptShouldGatherMetrics_WhenSucceeds(TentacleConfigurationTestCase tentacleConfigurationTestCase) { // Arrange diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreDisabled.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreDisabled.cs index 91aedbf7e..b72258302 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreDisabled.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreDisabled.cs @@ -16,6 +16,7 @@ using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators.Proxies; using Octopus.Tentacle.Tests.Integration.Support; using Octopus.Tentacle.Tests.Integration.Support.ExtensionMethods; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -30,6 +31,7 @@ namespace Octopus.Tentacle.Tests.Integration /// These tests make sure that we can cancel the ExecuteScript operation when using Tentacle Client with RPC retries disabled. /// [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionCanBeCancelledWhenRetriesAreDisabled : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreEnabled.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreEnabled.cs index 693adbd07..2483b92eb 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreEnabled.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanBeCancelledWhenRetriesAreEnabled.cs @@ -18,6 +18,7 @@ using Octopus.Tentacle.Tests.Integration.Support; using Octopus.Tentacle.Tests.Integration.Support.ExtensionMethods; using Octopus.Tentacle.Tests.Integration.Support.PendingRequestQueueFactories; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -32,6 +33,7 @@ namespace Octopus.Tentacle.Tests.Integration /// These tests make sure that we can cancel the ExecuteScript operation when using Tentacle Client with RPC retries enabled. /// [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionCanBeCancelledWhenRetriesAreEnabled : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanRecoverFromNetworkIssues.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanRecoverFromNetworkIssues.cs index 4f0afb1b6..2a488356d 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanRecoverFromNetworkIssues.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionCanRecoverFromNetworkIssues.cs @@ -13,6 +13,7 @@ using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; using Octopus.Tentacle.Tests.Integration.Support.ExtensionMethods; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -22,6 +23,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionCanRecoverFromNetworkIssues : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionRetriesTimeout.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionRetriesTimeout.cs index edfb8893e..96e82e3ad 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionRetriesTimeout.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionRetriesTimeout.cs @@ -8,6 +8,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -20,6 +21,7 @@ namespace Octopus.Tentacle.Tests.Integration /// from RPC calls when they are being retried and the rpc timeout period elapses. /// [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionRetriesTimeout : IntegrationTest { readonly TimeSpan retryIfRemainingDurationAtLeastBuffer = TimeSpan.FromSeconds(1); @@ -217,6 +219,7 @@ public async Task WhenRpcRetriesTimeOut_DuringStartScript_TheRpcCallIsCancelled( [Test] [TentacleConfigurations] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public async Task WhenStartScriptFails_AndTakesLongerThanTheRetryDuration_TheCallIsNotRetried_AndTimesOut(TentacleConfigurationTestCase tentacleConfigurationTestCase) { var retryDuration = TimeSpan.FromSeconds(15); diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptFilesAreSent.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptFilesAreSent.cs index 181ceeef0..22a3daf7b 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptFilesAreSent.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptFilesAreSent.cs @@ -6,12 +6,14 @@ using Octopus.Tentacle.CommonTestUtils.Builders; using Octopus.Tentacle.Contracts; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + // [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionScriptFilesAreSent : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceNonV1IsNotRetriedWhenRetriesAreDisabled.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceNonV1IsNotRetriedWhenRetriesAreDisabled.cs index 2986460e6..a75a8dbf3 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceNonV1IsNotRetriedWhenRetriesAreDisabled.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceNonV1IsNotRetriedWhenRetriesAreDisabled.cs @@ -10,6 +10,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -18,6 +19,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionScriptServiceNonV1IsNotRetriedWhenRetriesAreDisabled : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceV1IsNotRetried.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceV1IsNotRetried.cs index 4d117c972..adf290337 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceV1IsNotRetried.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionScriptServiceV1IsNotRetried.cs @@ -9,6 +9,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -17,6 +18,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionScriptServiceV1IsNotRetried : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionWorksWithMultipleVersions.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionWorksWithMultipleVersions.cs index a28ed3bde..eb56e9088 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionWorksWithMultipleVersions.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutionWorksWithMultipleVersions.cs @@ -5,12 +5,14 @@ using Octopus.Tentacle.CommonTestUtils.Builders; using Octopus.Tentacle.Contracts; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + // [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ClientScriptExecutionWorksWithMultipleVersions : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutorObservesScriptObserverBackoffStrategy.cs b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutorObservesScriptObserverBackoffStrategy.cs index b61e5aeb0..949d586ae 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutorObservesScriptObserverBackoffStrategy.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ClientScriptExecutorObservesScriptObserverBackoffStrategy.cs @@ -6,6 +6,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -13,6 +14,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class ClientScriptExecutorObservesScriptObserverBackoffStrategy : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/FileTransferServiceTests.cs b/source/Octopus.Tentacle.Tests.Integration/FileTransferServiceTests.cs index bce59c8cc..de5f41b6d 100644 --- a/source/Octopus.Tentacle.Tests.Integration/FileTransferServiceTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/FileTransferServiceTests.cs @@ -1,11 +1,14 @@ using System; using System.IO; +using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Halibut; using NUnit.Framework; +using Octopus.Client.Extensions; using Octopus.Tentacle.CommonTestUtils; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; namespace Octopus.Tentacle.Tests.Integration @@ -17,10 +20,17 @@ public class FileTransferServiceTests : IntegrationTest [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None)] public async Task UploadFileSuccessfully(TentacleConfigurationTestCase tentacleConfigurationTestCase) { + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + Logger.Information($"UploadFileSuccessfully Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + using var fileToUpload = new RandomTemporaryFileBuilder().Build(); + Logger.Information($"UploadFileSuccessfully Available Disk space before CreateLegacyBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateLegacyBuilder().Build(CancellationToken); + Logger.Information($"UploadFileSuccessfully Available Disk space after CreateLegacyBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + var dataStream = new DataStream( fileToUpload.File.Length, async (stream, ct) => @@ -28,14 +38,20 @@ public async Task UploadFileSuccessfully(TentacleConfigurationTestCase tentacleC using var fileStream = File.OpenRead(fileToUpload.File.FullName); await fileStream.CopyToAsync(stream); }); + + Logger.Information($"UploadFileSuccessfully Available Disk after creating a DataStream: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var uploadResult = await clientAndTentacle.TentacleClient.FileTransferService.UploadFileAsync("the_remote_uploaded_file", dataStream, new(CancellationToken)); + + Logger.Information($"UploadFileSuccessfully Available Disk space after UploadFileAsync: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); Console.WriteLine($"Source: {fileToUpload.File.FullName}"); Console.WriteLine($"Destination: {uploadResult.FullPath}"); var sourceBytes = File.ReadAllBytes(fileToUpload.File.FullName); var destinationBytes = File.ReadAllBytes(uploadResult.FullPath); + + Logger.Information($"UploadFileSuccessfully Available Disk space after assertion: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); sourceBytes.Should().BeEquivalentTo(destinationBytes); } @@ -43,19 +59,27 @@ public async Task UploadFileSuccessfully(TentacleConfigurationTestCase tentacleC [Test] [TentacleConfigurations(scriptServiceToTest: ScriptServiceVersionToTest.None)] public async Task DownloadFileSuccessfully(TentacleConfigurationTestCase tentacleConfigurationTestCase) - { + { + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + using var fileToDownload = new RandomTemporaryFileBuilder().Build(); + Logger.Information($"DownloadFileSuccessfully Available Disk space before RandomTemporaryFileBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); await using var clientAndTentacle = await tentacleConfigurationTestCase.CreateLegacyBuilder().Build(CancellationToken); + Logger.Information($"DownloadFileSuccessfully Available Disk space after CreateLegacyBuilder: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var downloadedData = await clientAndTentacle.TentacleClient.FileTransferService.DownloadFileAsync( fileToDownload.File.FullName, new(CancellationToken)); + Logger.Information($"DownloadFileSuccessfully Available Disk space after DownloadFileAsync: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); var sourceBytes = File.ReadAllBytes(fileToDownload.File.FullName); var destinationBytes = await downloadedData.ToBytes(CancellationToken); + Logger.Information($"DownloadFileSuccessfully Available Disk space after downloadedData: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); destinationBytes.Should().BeEquivalentTo(sourceBytes); + Logger.Information($"DownloadFileSuccessfully Available Disk space after assertion: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + } } } diff --git a/source/Octopus.Tentacle.Tests.Integration/MachineConfigurationHomeDirectoryTests.cs b/source/Octopus.Tentacle.Tests.Integration/MachineConfigurationHomeDirectoryTests.cs index aabcde625..f6c672102 100644 --- a/source/Octopus.Tentacle.Tests.Integration/MachineConfigurationHomeDirectoryTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/MachineConfigurationHomeDirectoryTests.cs @@ -5,11 +5,13 @@ using NUnit.Framework; using Octopus.Tentacle.CommonTestUtils; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Variables; namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + // [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class MachineConfigurationHomeDirectoryTests : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ScriptServiceTests.cs b/source/Octopus.Tentacle.Tests.Integration/ScriptServiceTests.cs index b855caeb9..1ecbe7a55 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ScriptServiceTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ScriptServiceTests.cs @@ -8,10 +8,12 @@ using Octopus.Tentacle.Contracts; using Octopus.Tentacle.Tests.Integration.Support; using Octopus.Tentacle.Tests.Integration.Support.Legacy; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + // [SkipOnEnvironmentsWithKnownPerformanceIssues("we keep facing issues with disk space running out")] public class ScriptServiceTests : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/ScriptServiceV2IntegrationTest.cs b/source/Octopus.Tentacle.Tests.Integration/ScriptServiceV2IntegrationTest.cs index 4fb62eb72..8b7723f69 100644 --- a/source/Octopus.Tentacle.Tests.Integration/ScriptServiceV2IntegrationTest.cs +++ b/source/Octopus.Tentacle.Tests.Integration/ScriptServiceV2IntegrationTest.cs @@ -9,6 +9,7 @@ using Octopus.Tentacle.Contracts.ClientServices; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -16,6 +17,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + // [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class ScriptServiceV2IntegrationTest : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/Support/ClientAndTentacle.cs b/source/Octopus.Tentacle.Tests.Integration/Support/ClientAndTentacle.cs index 9d4e9a523..9ed091e42 100644 --- a/source/Octopus.Tentacle.Tests.Integration/Support/ClientAndTentacle.cs +++ b/source/Octopus.Tentacle.Tests.Integration/Support/ClientAndTentacle.cs @@ -1,8 +1,10 @@ using System; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; using Halibut; +using Octopus.Client.Extensions; using Octopus.Tentacle.Client; using Octopus.Tentacle.Client.Retries; using Octopus.Tentacle.CommonTestUtils; @@ -53,6 +55,11 @@ public ClientAndTentacle(IHalibutRuntime halibutRuntime, public async ValueTask DisposeAsync() { + + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + + logger.Information($"DisposeAsync() Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + SafelyMoveTentacleLogFileToSharedLocation(); var banner = new StringBuilder(); diff --git a/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTest.cs b/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTest.cs index 79c83541d..1e6cd61ce 100644 --- a/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTest.cs +++ b/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTest.cs @@ -1,9 +1,11 @@ using System; using System.IO; +using System.Linq; using System.Threading; using Halibut.Util; using NUnit.Framework; using NUnit.Framework.Interfaces; +using Octopus.Client.Extensions; using Octopus.Tentacle.Tests.Integration.Util; using Serilog; @@ -20,7 +22,8 @@ public abstract class IntegrationTest : IDisposable public void SetUp() { Logger = new SerilogLoggerBuilder().Build().ForContext(GetType()); - Logger.Information("Test started"); + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + Logger.Information($"Test started. Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); // Time out the cancellation token so we cancel the test if it takes too long // The IntegrationTestTimeout attribute will also cancel the test if it takes too long, but nunit will not call TearDown on the test @@ -40,7 +43,9 @@ public void TearDown() Logger.Information("Disposing CancellationTokenSource"); cancellationTokenSource?.Dispose(); cancellationTokenSource = null; - Logger.Information("Finished Test Tearing Down"); + var driveInfos = DriveInfo.GetDrives().Where(d => d.IsReady); + Logger.Information($"Finished Test Tearing Down. Available Disk space before starting: {driveInfos.Select(d => $"{d.Name}: {d.AvailableFreeSpace}").ToList().StringJoin(", ")}"); + } void WriteTentacleLogToOutputIfTestHasFailed() diff --git a/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTestTimeout.cs b/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTestTimeout.cs index be3b7079a..c42709be1 100644 --- a/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTestTimeout.cs +++ b/source/Octopus.Tentacle.Tests.Integration/Support/IntegrationTestTimeout.cs @@ -21,7 +21,17 @@ public static int TestTimeoutInMilliseconds() return (int)TimeSpan.FromHours(1).TotalMilliseconds; } - return (int)TimeSpan.FromMinutes(2).TotalMilliseconds; + return GetTimeoutFromEnvironmentVariable() ?? (int)TimeSpan.FromMinutes(2).TotalMilliseconds; + } + + static int? GetTimeoutFromEnvironmentVariable() + { + if (int.TryParse(Environment.GetEnvironmentVariable("IntegrationTest_Timeout_Minutes"), out var timeoutFromEnv)) + { + return (int)TimeSpan.FromMinutes(timeoutFromEnv).TotalMilliseconds; + } + + return null; } } } \ No newline at end of file diff --git a/source/Octopus.Tentacle.Tests.Integration/Support/TestAttributes/SkipOnEnvironmentsWithKnownPerformanceIssuesAttribute.cs b/source/Octopus.Tentacle.Tests.Integration/Support/TestAttributes/SkipOnEnvironmentsWithKnownPerformanceIssuesAttribute.cs new file mode 100644 index 000000000..9a36ab6c5 --- /dev/null +++ b/source/Octopus.Tentacle.Tests.Integration/Support/TestAttributes/SkipOnEnvironmentsWithKnownPerformanceIssuesAttribute.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq; +using NUnit.Framework; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; +using Octopus.Tentacle.Util; + +namespace Octopus.Tentacle.Tests.Integration.Support.TestAttributes +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class SkipOnEnvironmentsWithKnownPerformanceIssuesAttribute : NUnitAttribute, IApplyToTest + { + string Reason { get; } + + public SkipOnEnvironmentsWithKnownPerformanceIssuesAttribute(string reason) + { + Reason = reason; + } + + public void ApplyToTest(Test test) + { + if (test.RunState == RunState.NotRunnable || test.RunState == RunState.Ignored) + return; + + if (bool.TryParse(Environment.GetEnvironmentVariable("Has_NET8_Compatibility_Issues"), out _)) + { + test.RunState = RunState.Skipped; + test.Properties.Add("_SKIPREASON", $"This test does not run on environments with .NET 8 performance issues because {Reason}"); + } + } + } +} \ No newline at end of file diff --git a/source/Octopus.Tentacle.Tests.Integration/TentacleClientObserver.cs b/source/Octopus.Tentacle.Tests.Integration/TentacleClientObserver.cs index bbc2955a9..e1746c7a5 100644 --- a/source/Octopus.Tentacle.Tests.Integration/TentacleClientObserver.cs +++ b/source/Octopus.Tentacle.Tests.Integration/TentacleClientObserver.cs @@ -10,12 +10,14 @@ using Octopus.Tentacle.Contracts.Observability; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class TentacleClientObserver : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/TentacleCommandLineTests.cs b/source/Octopus.Tentacle.Tests.Integration/TentacleCommandLineTests.cs index fba7ceedb..42adb51d8 100644 --- a/source/Octopus.Tentacle.Tests.Integration/TentacleCommandLineTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/TentacleCommandLineTests.cs @@ -28,6 +28,7 @@ namespace Octopus.Tentacle.Tests.Integration /// Please review any changes to the assertions made by these tests carefully. /// [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("we don't expect customers to execute it in this environment in a situation where it needs to behave within a reasonable timeframe.")] public class TentacleCommandLineTests : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/TentacleStartupAndShutdownTests.cs b/source/Octopus.Tentacle.Tests.Integration/TentacleStartupAndShutdownTests.cs index 7cd833c4f..7edfd79a0 100644 --- a/source/Octopus.Tentacle.Tests.Integration/TentacleStartupAndShutdownTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/TentacleStartupAndShutdownTests.cs @@ -16,6 +16,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class TentacleStartupAndShutdownTests : IntegrationTest { [Test] diff --git a/source/Octopus.Tentacle.Tests.Integration/Util/SilentProcessRunnerFixture.cs b/source/Octopus.Tentacle.Tests.Integration/Util/SilentProcessRunnerFixture.cs index 8169263a4..2e481578d 100644 --- a/source/Octopus.Tentacle.Tests.Integration/Util/SilentProcessRunnerFixture.cs +++ b/source/Octopus.Tentacle.Tests.Integration/Util/SilentProcessRunnerFixture.cs @@ -10,6 +10,7 @@ namespace Octopus.Tentacle.Tests.Integration.Util { [TestFixture] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class SilentProcessRunnerFixture : IntegrationTest { const int SIG_TERM = 143; diff --git a/source/Octopus.Tentacle.Tests.Integration/WorkspaceCleanerTests.cs b/source/Octopus.Tentacle.Tests.Integration/WorkspaceCleanerTests.cs index 8eb83f876..71ca628e8 100644 --- a/source/Octopus.Tentacle.Tests.Integration/WorkspaceCleanerTests.cs +++ b/source/Octopus.Tentacle.Tests.Integration/WorkspaceCleanerTests.cs @@ -8,6 +8,7 @@ using Octopus.Tentacle.Scripts; using Octopus.Tentacle.Tests.Integration.Common.Builders.Decorators; using Octopus.Tentacle.Tests.Integration.Support; +using Octopus.Tentacle.Tests.Integration.Support.TestAttributes; using Octopus.Tentacle.Tests.Integration.Util; using Octopus.Tentacle.Tests.Integration.Util.Builders; using Octopus.Tentacle.Tests.Integration.Util.Builders.Decorators; @@ -15,6 +16,7 @@ namespace Octopus.Tentacle.Tests.Integration { [IntegrationTestTimeout] + [SkipOnEnvironmentsWithKnownPerformanceIssues("it relies on timing, which may be inconsistent within the environment")] public class WorkspaceCleanerTests : IntegrationTest { [Test]