Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions azure-pipelines-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ stages:
/p:Test=false
displayName: Unix Build / Publish

- job: MacOS
pool:
vmImage: macOS-latest
strategy:
matrix:
Build_Debug:
_BuildConfig: Debug
preSteps:
- checkout: self
clean: true
steps:
- script: eng/common/cibuild.sh
--configuration $(_BuildConfig)
--prepareMachine
/p:Test=false
displayName: MacOS Build / Publish

- stage: Test
dependsOn: build
jobs:
Expand Down Expand Up @@ -208,6 +225,36 @@ stages:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
HelixAccessToken: ''

- job: MacOs
timeoutInMinutes: 90
pool:
vmimage: macOS-latest
strategy:
matrix:
Build_Debug:
_BuildConfig: Debug
variables:
- _Testing: Helix
preSteps:
- checkout: self
clean: true
steps:
- script: eng/common/build.sh
--configuration $(_BuildConfig)
--prepareMachine
--ci
--restore
--test
--warnAsError false
--projects $(System.DefaultWorkingDirectory)/tests/UnitTests.proj
/v:normal
/bl:$(System.DefaultWorkingDirectory)/artifacts/log/$(_BuildConfig)/Helix.binlog
/p:RestoreUsingNuGetTargets=false
displayName: Run Helix Tests
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
HelixAccessToken: ''

- stage: Test_XHarness
displayName: Test XHarness SDK
dependsOn: build
Expand Down
62 changes: 62 additions & 0 deletions src/Microsoft.DotNet.Helix/Sdk/AzureDevOpsTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
Expand All @@ -21,6 +23,11 @@ namespace Microsoft.DotNet.Helix.AzureDevOps
{
public abstract class AzureDevOpsTask : BaseTask
{
/// <summary>
/// Timeout in seconds for HTTP requests. Default is 180 seconds.
/// </summary>
public int Timeout { get; set; } = 180;

private bool InAzurePipeline => !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDNUMBER"));

protected string GetEnvironmentVariable(string name)
Expand All @@ -44,6 +51,57 @@ protected string GetEnvironmentVariable(string name)

protected abstract Task ExecuteCoreAsync(HttpClient client);

private ActivityListener CreateHttpActivityListener()
{
var listener = new ActivityListener
{
ShouldListenTo = source => source.Name == "System.Net.Http",
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllDataAndRecorded,
ActivityStarted = activity =>
{
Log.LogMessage(MessageImportance.Low,
$"[System.Net.Http] {activity.OperationName} started - {activity.DisplayName}");

// Log tags which contain request details
foreach (var tag in activity.Tags)
{
Log.LogMessage(MessageImportance.Low, $" {tag.Key}: {tag.Value}");
}
},
ActivityStopped = activity =>
{
var status = activity.Status == ActivityStatusCode.Error ? "ERROR" : "OK";
Log.LogMessage(MessageImportance.Low,
$"[System.Net.Http] {activity.OperationName} stopped - Duration: {activity.Duration.TotalMilliseconds:F2}ms, Status: {status}");

if (activity.Status == ActivityStatusCode.Error && !string.IsNullOrEmpty(activity.StatusDescription))
{
Log.LogMessage(MessageImportance.Normal,
$"[System.Net.Http] Error: {activity.StatusDescription}");
}

// Log response tags (status code, etc.)
foreach (var tag in activity.Tags)
{
Log.LogMessage(MessageImportance.Low, $" {tag.Key}: {tag.Value}");
}

// Log events (connection established, request/response headers sent/received, etc.)
foreach (var evt in activity.Events)
{
var tagsStr = string.Join(", ", evt.Tags);
Log.LogMessage(MessageImportance.Low,
$" Event: {evt.Name} at {evt.Timestamp:O}" +
(string.IsNullOrEmpty(tagsStr) ? "" : $" ({tagsStr})"));
}
}
};

ActivitySource.AddActivityListener(listener);
Log.LogMessage(MessageImportance.Low, "System.Net.Http ActivityListener registered");
return listener;
}

public override bool Execute()
=> ExecuteAsync().GetAwaiter().GetResult();

Expand All @@ -57,6 +115,9 @@ private async Task<bool> ExecuteAsync()
}
else
{
// Set up HTTP activity listener for diagnostics - only active during this task execution
using var httpActivityListener = CreateHttpActivityListener();

// Configure the cert revocation check in a fail-open state to avoid intermittent failures
// on Mac if the endpoint is not available. This is only available on .NET Core, but has only been
// observed on Mac anyway.
Expand Down Expand Up @@ -96,6 +157,7 @@ private async Task<bool> ExecuteAsync()
})
#endif
{
Timeout = Timeout > 0 ? TimeSpan.FromSeconds(Timeout) : System.Threading.Timeout.InfiniteTimeSpan,
DefaultRequestHeaders =
{
Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes("unused:" + AccessToken))),
Expand Down
8 changes: 6 additions & 2 deletions src/Microsoft.DotNet.Helix/Sdk/FindDotNetCliPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ public class FindDotNetCliPackage : MSBuildTaskBase

public override void ConfigureServices(IServiceCollection collection)
{
_httpMessageHandler = new HttpClientHandler { CheckCertificateRevocationList = true };
bool isOSX = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX);
_httpMessageHandler = new HttpClientHandler
{
CheckCertificateRevocationList = !isOSX // Disable on macOS
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also figure out why this hangs instead of falls with an exception

collection.TryAddSingleton(_httpMessageHandler);
collection.TryAddSingleton(Log);
}
Expand Down Expand Up @@ -245,7 +249,7 @@ await _retry.RunAsync(async attempt =>
}
catch (Exception toLog)
{
Log.LogMessage(MessageImportance.Low, $"Hit exception in GetAsync(); will retry up to 10 times ({SanitizeString(toLog.Message)})");
Log.LogMessage(MessageImportance.Low, $"Hit exception in GetAsync(); will retry up to 10 times ({SanitizeString(toLog.ToString())})");
return false;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<_CurrentTestRunName Condition="'$(_CurrentTestRunName)' == ''">$(TestRunNamePrefix)$(_CurrentTargetQueue)$(TestRunNameSuffix)</_CurrentTestRunName>
</PropertyGroup>
<Message Text="Starting Azure Pipelines Test Run $(_CurrentTestRunName)" Importance="High"/>
<StartAzurePipelinesTestRun TestRunName="$(_CurrentTestRunName)">
<StartAzurePipelinesTestRun TestRunName="$(_CurrentTestRunName)" Timeout="$(AzurePipelinesTimeout)">
<Output TaskParameter="TestRunId" PropertyName="TestRunId"/>
</StartAzurePipelinesTestRun>
<ItemGroup>
Expand All @@ -29,13 +29,13 @@

<Target Name="CreateTestsForWorkItems"
BeforeTargets="StopTestRuns">
<CreateTestsForWorkItems WorkItems="@(CompletedWorkItem)"/>
<CreateTestsForWorkItems WorkItems="@(CompletedWorkItem)" Timeout="$(AzurePipelinesTimeout)"/>
</Target>

<Target Name="StopTestRuns"
AfterTargets="CoreTest"
Outputs="%(HelixTargetQueue.Identity)">
<StopAzurePipelinesTestRun TestRunId="%(HelixTargetQueue.TestRunId)" TestRunName="%(HelixTargetQueue.TestRunName)"/>
<StopAzurePipelinesTestRun TestRunId="%(HelixTargetQueue.TestRunId)" TestRunName="%(HelixTargetQueue.TestRunName)" Timeout="$(AzurePipelinesTimeout)"/>
</Target>

<Target Name="CheckTestResults"
Expand All @@ -46,6 +46,7 @@
EnableFlakyTestSupport="$(AzurePipelinesEnableFlakyTestSupport)"
TestRunIds="@(HelixTargetQueue -> '%(TestRunId)')"
WorkItems="@(CompletedWorkItem)"
Timeout="$(AzurePipelinesTimeout)"
/>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<PropertyGroup>
<AzurePipelinesAvailable Condition="'$(SYSTEM_ACCESSTOKEN)' != ''">true</AzurePipelinesAvailable>
<AzurePipelinesAvailable Condition="'$(AzurePipelinesAvailable)' != 'true'">false</AzurePipelinesAvailable>
<AzurePipelinesTimeout Condition="'$(AzurePipelinesTimeout)' == ''">180</AzurePipelinesTimeout>
</PropertyGroup>

<!-- We default the azure pipelines reporter to ON if we are running inside Azure Pipelines -->
Expand All @@ -13,7 +14,7 @@
</PropertyGroup>

<PropertyGroup Condition="!$(AzurePipelinesAvailable)">
<EnableAzurePipelinesReporter Condition="'$(EnableAzurePipelinesReporter)' != 'true'">false</EnableAzurePipelinesReporter>
<EnableAzurePipelinesReporter Condition="'$(EnableAzurePipelineAzurePipelinesTimeoutsReporter)' != 'true'">false</EnableAzurePipelinesReporter>
<FailOnTestFailure Condition="'$(FailOnTestFailure)' != 'false'">true</FailOnTestFailure>
</PropertyGroup>

Expand Down
8 changes: 2 additions & 6 deletions tests/UnitTests.proj
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@
</ItemGroup>

<ItemGroup Condition=" '$(HelixAccessToken)' != '' ">
<HelixTargetQueue Include="(AlmaLinux.9.Amd64)[email protected]/dotnet-buildtools/prereqs:almalinux-9-helix-amd64"/>
<HelixTargetQueue Include="Windows.10.Amd64"/>
<HelixTargetQueue Include="(Debian.13.Amd64)[email protected]/dotnet-buildtools/prereqs:debian-13-helix-amd64"/>
<HelixTargetQueue Include="OSX.13.Amd64.Open"/>
</ItemGroup>

<PropertyGroup Condition=" '$(HelixAccessToken)' == '' ">
Expand All @@ -72,9 +70,7 @@
</PropertyGroup>

<ItemGroup Condition=" '$(HelixAccessToken)' == '' ">
<HelixTargetQueue Include="(AlmaLinux.9.Amd64.Open)[email protected]/dotnet-buildtools/prereqs:almalinux-9-helix-amd64"/>
<HelixTargetQueue Include="Windows.10.Amd64.Open"/>
<HelixTargetQueue Include="(Debian.13.Amd64.Open)[email protected]/dotnet-buildtools/prereqs:debian-13-helix-amd64"/>
<HelixTargetQueue Include="OSX.13.Amd64.Open"/>
</ItemGroup>

<PropertyGroup Condition="!$(HelixTargetQueue.StartsWith('Windows'))">
Expand Down
Loading