Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tests] Add support for running tests on helix #1917

Merged
merged 17 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<BuildArch Condition=" '$(BuildArch)' == '' ">amd64</BuildArch>
<DcpDir>$(NuGetPackageRoot)microsoft.developercontrolplane.$(BuildOs)-$(BuildArch)/$(MicrosoftDeveloperControlPlanedarwinamd64PackageVersion)/tools/</DcpDir>

<TestArchiveTestsDir>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'helix', 'tests'))</TestArchiveTestsDir>
<!-- TODO: Need to figure out we can automatically detect target framework here. This property
is specified to support dashboard path metadata generation on the inner loop. -->
<AspireDashboardDir>$(MSBuildThisFileDirectory)/artifacts/bin/Aspire.Dashboard/$(Configuration)/net8.0/</AspireDashboardDir>
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
<ItemGroup Condition="'$(ReadMeExists)' == 'true'">
<None Include="$(ReadMePath)" Pack="true" PackagePath="\" />
</ItemGroup>

</Project>
6 changes: 3 additions & 3 deletions eng/pipelines/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ stages:
jobs:

- job: windows
timeoutInMinutes: 30
timeoutInMinutes: 45
Copy link
Member

Choose a reason for hiding this comment

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

😞

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, 30 mins was already pretty low and super close to the time it actually takes to build the repo in AzDO, so we were going to have to do this sooner rather than later.

Copy link
Member

Choose a reason for hiding this comment

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

image

that's from a recent CI run.


pool:
${{ if eq(variables['System.TeamProject'], 'public') }}:
Expand Down Expand Up @@ -131,7 +131,7 @@ stages:

- ${{ if eq(variables._RunAsPublic, True) }}:
- job: linux
timeoutInMinutes: 30
timeoutInMinutes: 45

pool:
${{ if eq(variables['System.TeamProject'], 'public') }}:
Expand Down Expand Up @@ -167,7 +167,7 @@ stages:
# ----------------------------------------------------------------
- stage: codecoverage
displayName: CodeCoverage
dependsOn:
dependsOn:
- build
condition: succeeded('build')
variables:
Expand Down
33 changes: 31 additions & 2 deletions eng/pipelines/templates/BuildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,45 @@ steps:
- script: ${{ parameters.buildScript }}
-restore -build
-configuration ${{ parameters.buildConfig }}
/p:ArchiveTests=true
/bl:${{ parameters.repoLogPath }}/build.binlog
$(_OfficialBuildIdArgs)
displayName: Build

- ${{ if ne(parameters.skipTests, 'true') }}:
- script: ${{ parameters.dotnetScript }} dotnet-coverage collect
--settings $(Build.SourcesDirectory)/eng/CodeCoverage.config
--output ${{ parameters.repoTestResultsPath }}/NonHelixTests.cobertura.xml
"${{ parameters.buildScript }} -testnobuild -test -configuration ${{ parameters.buildConfig }} /bl:${{ parameters.repoLogPath }}/tests.binlog $(_OfficialBuildIdArgs)"
displayName: Run non-helix tests
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to run the non-helix tests and the helix tests in parallel? There shouldn't be a reason to serialize them, and that could speed up our CI legs.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could add a wrapper project that builds both in parallel from msbuild. Should that be in a follow up PR?

Copy link
Member

Choose a reason for hiding this comment

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

Why would we need to build them in parallel? I'm talking about running them in parallel.

Why would we need a wrapper project? Does azdo allow for running 2 pipeline tasks at the same time?

Copy link
Member Author

Choose a reason for hiding this comment

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

By "build" in parallel I meant run the Test, and send-to-helix targets in parallel.

Copy link
Member Author

Choose a reason for hiding this comment

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

Does azdo allow for running 2 pipeline tasks at the same time?

AFAIK, this isn't supported.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, the thing that is allowed is to run two jobs or stages at the same time, but not steps within a job AFAIK. While I do think that could speed up things a bit, I also think it might be overkill to gain 9 mins or so that it takes in average to run the non helix tests first. I propose keeping things as is, and then perhaps look in the future here to see if this is something we need to invest on.


- template: /eng/pipelines/templates/send-to-helix.yml
parameters:
HelixProjectPath: '$(Build.SourcesDirectory)/tests/send-to-helix.proj'
HelixProjectArguments: /p:RunWithCodeCoverage=true /p:RepoTestResultsPath=${{ parameters.repoTestResultsPath }}
joperezr marked this conversation as resolved.
Show resolved Hide resolved

${{ if eq(parameters.isWindows, 'true') }}:
HelixTargetQueues: Windows.11.Amd64.Client.Open
joperezr marked this conversation as resolved.
Show resolved Hide resolved
${{ if ne(parameters.isWindows, 'true') }}:
HelixTargetQueues: Ubuntu.2204.Amd64.Open

IsWindows: ${{ parameters.isWindows }}
Creator: $(Build.DefinitionName)
HelixBuild: $(Build.BuildNumber)
HelixAccessToken: $(HelixApiAccessToken)

- task: CopyFiles@2
inputs:
Contents: '${{ parameters.repoTestResultsPath }}/**/*.cobertura.xml'
TargetFolder: '${{ parameters.repoTestResultsPath }}/collected'
flattenFolders: true
displayName: Gather coverage results (cobertura.xml)

- script: $(Build.SourcesDirectory)/.dotnet/dotnet dotnet-coverage merge
${{ parameters.repoTestResultsPath }}/collected/*.cobertura.xml
--output-format cobertura
--output ${{ parameters.repoTestResultsPath }}/$(Agent.Os)_$(Agent.JobName).cobertura.xml
"${{ parameters.buildScript }} -test -configuration ${{ parameters.buildConfig }} /bl:${{ parameters.repoLogPath }}/tests.binlog $(_OfficialBuildIdArgs)"
displayName: Run tests
displayName: Merge code coverage reports

- task: PublishBuildArtifacts@1
inputs:
Expand Down
95 changes: 95 additions & 0 deletions eng/pipelines/templates/send-to-helix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# This is a modified copy of eng/common/templates/steps/send-to-helix.yml
# Please remember to update the documentation if you make changes to these parameters!
Copy link
Member

Choose a reason for hiding this comment

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

Loved the docs :).

Did we get these from some other repo? Mainly asking to see if we need to try to keep in sync.

Copy link
Member Author

Choose a reason for hiding this comment

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

The template is from eng/common/templates/steps/send-to-helix.yml, slightly modified here.

Copy link
Member

Choose a reason for hiding this comment

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

mmm I see, is there a way to instead use that template file and pass in some parameters to accommodate for our small modifications? If possible, I'd love to reduce the amount of yaml that we have to maintain.

Copy link
Member Author

Choose a reason for hiding this comment

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

This eng/common/templates/steps/send-to-helix.yml is a sample template from arcade, and it's not used directly. But I can make changes in that file itself.

Copy link
Member

Choose a reason for hiding this comment

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

Not sure what you mean when you say a "sample template". Tipically the templates under eng\common\templates are there so that repos can use them if they want/need as part of their build process. I don't want to block this PR on this, but I do want to make sure this is fixed. Can we at least log a tracking bug so that we go and add the necessary hooks in dotnet/arcade repo so that we can later ingest those changes here, and remove this file entirely so that we instead leverage the files from eng\common?

Copy link
Member Author

Choose a reason for hiding this comment

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

parameters:
HelixSource: 'pr/default' # required -- sources must start with pr/, official/, prodcon/, or agent/
HelixType: 'tests/default/' # required -- Helix telemetry which identifies what type of data this is; should include "test" for clarity and must end in '/'
HelixBuild: $(Build.BuildNumber) # required -- the build number Helix will use to identify this -- automatically set to the AzDO build number
HelixTargetQueues: '' # required -- semicolon-delimited list of Helix queues to test on; see https://helix.dot.net/ for a list of queues
HelixAccessToken: '' # required -- access token to make Helix API requests; should be provided by the appropriate variable group
HelixProjectPath: '' # required -- path to the project file to build
HelixProjectArguments: '' # optional -- arguments passed to the build command
HelixConfiguration: '' # optional -- additional property attached to a job
HelixPreCommands: '' # optional -- commands to run before Helix work item execution
HelixPostCommands: '' # optional -- commands to run after Helix work item execution
WorkItemDirectory: '' # optional -- a payload directory to zip up and send to Helix; requires WorkItemCommand; incompatible with XUnitProjects
WorkItemCommand: '' # optional -- a command to execute on the payload; requires WorkItemDirectory; incompatible with XUnitProjects
WorkItemTimeout: '' # optional -- a timeout in TimeSpan.Parse-ready value (e.g. 00:02:00) for the work item command; requires WorkItemDirectory; incompatible with XUnitProjects
CorrelationPayloadDirectory: '' # optional -- a directory to zip up and send to Helix as a correlation payload
XUnitProjects: '' # optional -- semicolon-delimited list of XUnitProjects to parse and send to Helix; requires XUnitRuntimeTargetFramework, XUnitPublishTargetFramework, XUnitRunnerVersion, and IncludeDotNetCli=true
XUnitWorkItemTimeout: '' # optional -- the workitem timeout in seconds for all workitems created from the xUnit projects specified by XUnitProjects
XUnitPublishTargetFramework: '' # optional -- framework to use to publish your xUnit projects
XUnitRuntimeTargetFramework: '' # optional -- framework to use for the xUnit console runner
XUnitRunnerVersion: '' # optional -- version of the xUnit nuget package you wish to use on Helix; required for XUnitProjects
IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion
DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json
DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json
WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget."
IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set
HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting https://helix.int-dot.net )
Creator: '' # optional -- if the build is external, use this to specify who is sending the job
DisplayNamePrefix: 'Run helix tests' # optional -- rename the beginning of the displayName of the steps in AzDO
IsWindows: false # optional
condition: succeeded() # optional -- condition for step to execute; defaults to succeeded()
continueOnError: false # optional -- determines whether to continue the build if the step errors; defaults to false

steps:
- ${{ if and(parameters.condition, eq(parameters.IsWindows, 'true')) }}:
- powershell: 'powershell "$env:BUILD_SOURCESDIRECTORY\eng\common\msbuild.ps1 ${{ parameters.HelixProjectPath }} ${{ parameters.HelixProjectArguments }} /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$env:BUILD_SOURCESDIRECTORY\artifacts\log\$env:BuildConfig\SendToHelix.binlog"'
displayName: ${{ parameters.DisplayNamePrefix }}
env:
BuildConfig: $(_BuildConfig)
HelixSource: ${{ parameters.HelixSource }}
HelixType: ${{ parameters.HelixType }}
HelixBuild: ${{ parameters.HelixBuild }}
HelixConfiguration: ${{ parameters.HelixConfiguration }}
HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixPreCommands: ${{ parameters.HelixPreCommands }}
HelixPostCommands: ${{ parameters.HelixPostCommands }}
WorkItemDirectory: ${{ parameters.WorkItemDirectory }}
WorkItemCommand: ${{ parameters.WorkItemCommand }}
WorkItemTimeout: ${{ parameters.WorkItemTimeout }}
CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }}
XUnitProjects: ${{ parameters.XUnitProjects }}
XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }}
XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }}
XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }}
XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }}
IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }}
DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }}
DotNetCliVersion: ${{ parameters.DotNetCliVersion }}
WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }}
HelixBaseUri: ${{ parameters.HelixBaseUri }}
Creator: ${{ parameters.Creator }}
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
continueOnError: ${{ parameters.continueOnError }}
- ${{ if and(parameters.condition, ne(parameters.IsWindows, 'true')) }}:
- script: $BUILD_SOURCESDIRECTORY/eng/common/msbuild.sh ${{ parameters.HelixProjectPath }} ${{ parameters.HelixProjectArguments }} /restore /p:TreatWarningsAsErrors=false /t:Test /bl:$BUILD_SOURCESDIRECTORY/artifacts/log/$BuildConfig/SendToHelix.binlog
displayName: ${{ parameters.DisplayNamePrefix }}
env:
BuildConfig: $(_BuildConfig)
HelixSource: ${{ parameters.HelixSource }}
HelixType: ${{ parameters.HelixType }}
HelixBuild: ${{ parameters.HelixBuild }}
HelixConfiguration: ${{ parameters.HelixConfiguration }}
HelixTargetQueues: ${{ parameters.HelixTargetQueues }}
HelixAccessToken: ${{ parameters.HelixAccessToken }}
HelixPreCommands: ${{ parameters.HelixPreCommands }}
HelixPostCommands: ${{ parameters.HelixPostCommands }}
WorkItemDirectory: ${{ parameters.WorkItemDirectory }}
WorkItemCommand: ${{ parameters.WorkItemCommand }}
WorkItemTimeout: ${{ parameters.WorkItemTimeout }}
CorrelationPayloadDirectory: ${{ parameters.CorrelationPayloadDirectory }}
XUnitProjects: ${{ parameters.XUnitProjects }}
XUnitWorkItemTimeout: ${{ parameters.XUnitWorkItemTimeout }}
XUnitPublishTargetFramework: ${{ parameters.XUnitPublishTargetFramework }}
XUnitRuntimeTargetFramework: ${{ parameters.XUnitRuntimeTargetFramework }}
XUnitRunnerVersion: ${{ parameters.XUnitRunnerVersion }}
IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }}
DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }}
DotNetCliVersion: ${{ parameters.DotNetCliVersion }}
WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }}
HelixBaseUri: ${{ parameters.HelixBaseUri }}
Creator: ${{ parameters.Creator }}
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
continueOnError: ${{ parameters.continueOnError }}
23 changes: 23 additions & 0 deletions eng/testing/.runsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<!-- Timeout in ms, 5 minutes -->
<TestSessionTimeout>300000</TestSessionTimeout>
<!-- Filter out failing (wrong framework, platform, runtime or activeissue) tests -->
<TestCaseFilter>category!=failing</TestCaseFilter>
</RunConfiguration>
<LoggerRunSettings>
<Loggers>
<Logger friendlyName="trx">
<Configuration>
<LogFileName>TestResults.trx</LogFileName>
</Configuration>
</Logger>
<Logger friendlyName="console">
<Configuration>
<Verbosity>normal</Verbosity>
</Configuration>
</Logger>
</Loggers>
</LoggerRunSettings>
</RunSettings>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
<IsTestSupportProject>true</IsTestSupportProject>
radical marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions tests/Aspire.Dashboard.Tests/Aspire.Dashboard.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>

<!-- Temporary - just to have at least one helix only project for now -->
<RunTestsOnHelix>true</RunTestsOnHelix>
</PropertyGroup>

<ItemGroup>
Expand Down
22 changes: 22 additions & 0 deletions tests/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project>
<Import Project="..\Directory.Build.targets" />
<PropertyGroup>
<DeployRunSettingsFile Condition="'$(DeployRunSettingsFile)' == ''">true</DeployRunSettingsFile>

<RunTestsOnHelix Condition="'$(RunTestsOnHelix)' == ''">false</RunTestsOnHelix>
<SkipTests Condition="'$(SkipTests)' == '' and ('$(IsTestSupportProject)' == 'true' or '$(RunTestsOnHelix)' == 'true')">true</SkipTests>
</PropertyGroup>

<ItemGroup>
<None Include="$(RepositoryEngineeringDir)testing\.runsettings" CopyToOutputDirectory="PreserveNewest" Condition="'$(DeployRunSettingsFile)' == 'true'" />
</ItemGroup>

<Target Name="ZipTestArchive" AfterTargets="Build" Condition="'$(ArchiveTests)' == 'true' and '$(RunTestsOnHelix)' == 'true'">
<Error Condition="'$(TestArchiveTestsDir)' == ''" Text="TestArchiveTestsDir property to archive the test folder must be set." />

<MakeDir Directories="$(TestArchiveTestsDir)" />
<ZipDirectory SourceDirectory="$(OutDir)"
joperezr marked this conversation as resolved.
Show resolved Hide resolved
DestinationFile="$([MSBuild]::NormalizePath('$(TestArchiveTestsDir)', '$(MSBuildProjectName).zip'))"
Overwrite="true" />
</Target>
</Project>
Loading