Skip to content

Commit

Permalink
[tests] Restructure helix project, and targets to work better (#3622)
Browse files Browse the repository at this point in the history
Currently, `tests/send-to-helix.proj` builds once and constructs various
`@(HelixWorkItem)`s for end-to-end tests, and basic tests that don't
need a workload.

Because of the way Helix SDK works, this ends up sharing some stuff like
`HelixPreCommand`, and `HelixPostCommand`. But the different kinds of
tests don't need the same pre/post commands, and the targets need to be
careful not to step on each other's items/properties.

To avoid all this, and keep it clean a new top-level project
`tests/send-to-helix-ci.proj` is added which essentially builds the
existing project multiple times, once for each test type (called Test
Category here).

Thus you have:

```
send-to-helix-ci.proj runs the following in parallel:
    => send-to-helix-inner.proj testCategory=basictests
        -> send, and wait for the helix jobs
    => send-to-helix-inner.proj testCategory=endtoendtests
        -> send, and wait for the helix jobs
```

Co-authored-by: Ankit Jain <radical@gmail.com>
  • Loading branch information
github-actions[bot] and radical authored Apr 12, 2024
1 parent e45c89a commit 4976389
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 67 deletions.
4 changes: 2 additions & 2 deletions eng/pipelines/templates/BuildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ steps:
# downloaded to <repo root>/artifacts/helixresults folder.
- template: /eng/pipelines/templates/send-to-helix.yml
parameters:
HelixProjectPath: '$(Build.SourcesDirectory)/tests/send-to-helix.proj'
HelixProjectArguments: /p:Configuration=${{ parameters.buildConfig }} /p:RunWithCodeCoverage=true /p:RepoTestResultsPath=${{ parameters.repoTestResultsPath }}
HelixProjectPath: '$(Build.SourcesDirectory)/tests/helix/send-to-helix-ci.proj'
HelixProjectArguments: /m /p:Configuration=${{ parameters.buildConfig }} /p:RunWithCodeCoverage=true /p:RepoTestResultsPath=${{ parameters.repoTestResultsPath }}

${{ if eq(parameters.isWindows, 'true') }}:
${{ if eq(variables['System.TeamProject'], 'public') }}:
Expand Down
6 changes: 6 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Helix

The helix CI job builds `tests/helix/send-to-helix-ci.proj`, which in turns builds the `Test` target on `tests/helix/send-to-helix-inner.proj`. This inner project uses the Helix SDK to construct `@(HelixWorkItem)`s, and send them to helix to run.

- `tests/helix/send-to-helix-basic-tests.targets` - this prepares all the tests that don't need special preparation
- `tests/helix/send-to-helix-workload-tests.targets` - this is for tests that require a sdk+workload installed
35 changes: 35 additions & 0 deletions tests/helix/send-to-helix-basic-tests.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project>

<PropertyGroup>
<WorkItemArchiveWildCard>$(TestArchiveTestsDir)**/*.zip</WorkItemArchiveWildCard>
<BuildHelixWorkItemsDependsOn>$(BuildHelixWorkItemsDependsOn);BuildHelixWorkItemsForDefaultTests</BuildHelixWorkItemsDependsOn>
</PropertyGroup>

<Target Name="BuildHelixWorkItemsForDefaultTests" DependsOnTargets="_StageDependenciesForHelix">
<PropertyGroup>
<_TestRunCommand Condition="'$(RunWithCodeCoverage)' == 'true'">@(_TestCoverageCommand, ' ') &quot;@(_TestRunCommandArguments, ' ')&quot;</_TestRunCommand>
<_TestRunCommand Condition="'$(RunWithCodeCoverage)' != 'true'">@(_TestRunCommandArguments, ' ')</_TestRunCommand>
</PropertyGroup>

<Error Condition="'$(_DotNetCoverageToolPath)' == '' or !Exists($(_DotNetCoverageToolPath))"
Text="Could not find dotnet-coverage tool. %24(_DotNetCoverageToolPath)=$(_DotNetCoverageToolPath)" />

<ItemGroup>
<_DefaultWorkItems Include="$(WorkItemArchiveWildCard)" />

<HelixWorkItem Include="@(_DefaultWorkItems -> '%(FileName)')">
<PayloadArchive>%(Identity)</PayloadArchive>
<PreCommands Condition="'$(OS)' == 'Windows_NT'">set &quot;TEST_NAME=%(FileName)&quot;</PreCommands>
<PreCommands Condition="'$(OS)' != 'Windows_NT'">export &quot;TEST_NAME=%(FileName)&quot;</PreCommands>
<Command>$(_TestRunCommand)</Command>
<Timeout>$(_workItemTimeout)</Timeout>

<!-- Download results file so coverage files can be extracted -->
<DownloadFilesFromResults>logs/%(FileName).cobertura.xml</DownloadFilesFromResults>
</HelixWorkItem>
</ItemGroup>

<Message Text="HelixCorrelationPayload: %(HelixCorrelationPayload.Identity)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
<Message Text="HelixWorkItem: %(HelixWorkItem.Identity), Command: %(HelixWorkItem.Command), PreCommands: %(HelixWorkItem.PreCommands) with PayloadArchive: %(HelixWorkItem.PayloadArchive)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
</Target>
</Project>
17 changes: 17 additions & 0 deletions tests/helix/send-to-helix-ci.proj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project>
<Target Name="Test">
<ItemGroup>
<TestCategory Include="basictests" />
<TestCategory Condition="'$(OS)' != 'Windows_NT'" Include="endtoendtests" />

<_ProjectsToBuild Include="send-to-helix-inner.proj"
Condition="'%(TestCategory.Identity)' != ''"
AdditionalProperties="TestCategory=%(TestCategory.Identity);Configuration=$(Configuration)" />
</ItemGroup>

<!-- Invoke MSBuild once for each Category (because of the grouping defined in "_ProjectsToBuild").
Create the Helix work items and start the jobs. This is done by invoking the "Test" Helix target.
-->
<MSBuild Projects="@(_ProjectsToBuild)" Targets="Test" BuildInParallel="true" StopOnFirstFailure="false" />
</Target>
</Project>
60 changes: 31 additions & 29 deletions tests/send-to-helix.proj → tests/helix/send-to-helix-inner.proj
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
<Project Sdk="Microsoft.DotNet.Helix.Sdk" InitialTargets="BuildHelixWorkItems" DefaultTargets="Test">
<Project Sdk="Microsoft.DotNet.Helix.Sdk" InitialTargets="BuildHelixWorkItems">
<!-- this project is built multiple times, once per test-category. For example: basictests, endtoendtests. -->

<PropertyGroup>
<Language>msbuild</Language>

<_workItemTimeout>00:20:00</_workItemTimeout>
<WorkItemArchiveWildCard>$(TestArchiveTestsDir)**/*.zip</WorkItemArchiveWildCard>

<IncludeDotNetCli>true</IncludeDotNetCli>
<DotNetCliPackageType>sdk</DotNetCliPackageType>

<GlobalJsonContent>$([System.IO.File]::ReadAllText('$(RepoRoot)global.json'))</GlobalJsonContent>
<DotNetCliVersion>$([System.Text.RegularExpressions.Regex]::Match($(GlobalJsonContent), '(%3F&lt;="dotnet": ").*(%3F=")'))</DotNetCliVersion>

<BuildHelixWorkItemsDependsOn>BuildHelixWorkItemsForDefaultTests</BuildHelixWorkItemsDependsOn>
<_SupportDataStagingDir>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'helix', 'support-data'))</_SupportDataStagingDir>
<BuildHelixWorkItemsDependsOn>_StageDependenciesForHelix</BuildHelixWorkItemsDependsOn>
</PropertyGroup>

<PropertyGroup>
<_SupportDataStagingDir>$([MSBuild]::NormalizeDirectory($(ArtifactsDir), 'helix', 'support-data'))</_SupportDataStagingDir>
<_HelixLogsPath Condition="'$(OS)' != 'Windows_NT'">$HELIX_WORKITEM_UPLOAD_ROOT/logs</_HelixLogsPath>
<_HelixLogsPath Condition="'$(OS)' == 'Windows_NT'">%HELIX_WORKITEM_UPLOAD_ROOT%/logs</_HelixLogsPath>

Expand Down Expand Up @@ -49,35 +49,36 @@
<_TestRunCommandArguments Include="full" />
</ItemGroup>

<Import Project="$(MSBuildThisFileDirectory)send-to-helix-workload-tests.targets" />
<Import Project="$(MSBuildThisFileDirectory)send-to-helix-basic-tests.targets" Condition="'$(TestCategory)' == 'basictests'" />
<Import Project="$(MSBuildThisFileDirectory)send-to-helix-workload-tests.targets" Condition="'$(TestCategory)' == 'EndToEndTests'" />

<Target Name="BuildHelixWorkItemsForDefaultTests" DependsOnTargets="_StageDependenciesForHelix">
<PropertyGroup>
<_TestRunCommand Condition="'$(RunWithCodeCoverage)' == 'true'">@(_TestCoverageCommand, ' ') &quot;@(_TestRunCommandArguments, ' ')&quot;</_TestRunCommand>
<_TestRunCommand Condition="'$(RunWithCodeCoverage)' != 'true'">@(_TestRunCommandArguments, ' ')</_TestRunCommand>
</PropertyGroup>
<ItemGroup Condition="'$(NeedsWorkload)' == 'true'">
<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set PATH=%HELIX_CORRELATION_PAYLOAD%\dotnet-latest;%PATH%" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export PATH=$HELIX_CORRELATION_PAYLOAD/dotnet-latest:$PATH" />

<Error Condition="'$(_DotNetCoverageToolPath)' == '' or !Exists($(_DotNetCoverageToolPath))"
Text="Could not find dotnet-coverage tool. %24(_DotNetCoverageToolPath)=$(_DotNetCoverageToolPath)" />
<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set SDK_DIR_NAME=dotnet-latest" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export SDK_DIR_NAME=dotnet-latest" />

<ItemGroup>
<_DefaultWorkItems Include="$(WorkItemArchiveWildCard)" />

<HelixWorkItem Include="@(_DefaultWorkItems -> '%(FileName)')">
<PayloadArchive>%(Identity)</PayloadArchive>
<PreCommands Condition="'$(OS)' == 'Windows_NT'">set &quot;TEST_NAME=%(FileName)&quot;</PreCommands>
<PreCommands Condition="'$(OS)' != 'Windows_NT'">export &quot;TEST_NAME=%(FileName)&quot;</PreCommands>
<Command>$(_TestRunCommand)</Command>
<Timeout>$(_workItemTimeout)</Timeout>

<!-- Download results file so coverage files can be extracted -->
<DownloadFilesFromResults>logs/%(FileName).cobertura.xml</DownloadFilesFromResults>
</HelixWorkItem>
</ItemGroup>
<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set SDK_FOR_WORKLOAD_TESTING_PATH=%HELIX_CORRELATION_PAYLOAD%\%SDK_DIR_NAME%" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export SDK_FOR_WORKLOAD_TESTING_PATH=$HELIX_CORRELATION_PAYLOAD/$SDK_DIR_NAME" />

<Message Text="HelixCorrelationPayload: %(HelixCorrelationPayload.Identity)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
<Message Text="HelixWorkItem: %(HelixWorkItem.Identity), Command: %(HelixWorkItem.Command), PreCommands: %(HelixWorkItem.PreCommands) with PayloadArchive: %(HelixWorkItem.PayloadArchive)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
</Target>
<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set TestsRunningOutsideOfRepo=true" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export TestsRunningOutsideOfRepo=true" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set BUILT_NUGETS_PATH=%HELIX_CORRELATION_PAYLOAD%\built-nugets" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export BUILT_NUGETS_PATH=$HELIX_CORRELATION_PAYLOAD/built-nugets" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set TEST_LOG_PATH=%HELIX_WORKITEM_UPLOAD_ROOT%/logs" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export TEST_LOG_PATH=$HELIX_WORKITEM_UPLOAD_ROOT/logs" />

<HelixPreCommand Include="docker info" />
<HelixPreCommand Include="docker ps" />
<HelixPreCommand Include="docker container ls --all" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="docker ps -aq | xargs docker stop | xargs docker rm" />

<HelixPostCommand Include="docker container ls --all" />
<HelixPostCommand Condition="'$(OS)' != 'Windows_NT'" Include="docker ps -aq | xargs docker stop | xargs docker rm" />
</ItemGroup>

<Target Name="_StageDependenciesForHelix">
<PropertyGroup>
Expand Down Expand Up @@ -109,6 +110,7 @@
</Target>

<Target Name="BuildHelixWorkItems" DependsOnTargets="$(BuildHelixWorkItemsDependsOn)">
<Message Text="Building for TestCategory=$(TestCategory)" Importance="High" />
<Message Text="HelixCorrelationPayload: %(HelixCorrelationPayload.Identity)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
<Message Text="HelixWorkItem: %(HelixWorkItem.Identity), Command: %(HelixWorkItem.Command), PreCommands: %(HelixWorkItem.PreCommands) with PayloadArchive: %(HelixWorkItem.PayloadArchive)" Condition="'$(HelixDryRun)' == 'true' and @(HelixWorkItem->Count()) > 0" Importance="High" />
<Error Text="Stopping the build for dry run" Condition="'$(HelixDryRun)' == 'true'" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
<Project>

<PropertyGroup>
<WorkItemArchiveWildCardWorkloadTests>$(TestArchiveTestsDirForWorkloadTests)**/*.zip</WorkItemArchiveWildCardWorkloadTests>
<_E2ETestsArchivePath>$(TestArchiveTestsDirForEndToEndTests)Aspire.EndToEnd.Tests.zip</_E2ETestsArchivePath>

<BuildHelixWorkItemsDependsOn>$(BuildHelixWorkItemsDependsOn);BuildHelixWorkItemsForEnd2EndTests</BuildHelixWorkItemsDependsOn>
</PropertyGroup>

<ItemGroup>
<_DefaultWorkItemsWorkloadTests Include="$(WorkItemArchiveWildCardWorkloadTests)" />
</ItemGroup>

<ItemGroup>
<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set PATH=%HELIX_CORRELATION_PAYLOAD%\dotnet-latest;%PATH%" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export PATH=$HELIX_CORRELATION_PAYLOAD/dotnet-latest:$PATH" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set SDK_DIR_NAME=dotnet-latest" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export SDK_DIR_NAME=dotnet-latest" />
<NeedsWorkload>true</NeedsWorkload>

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set SDK_FOR_WORKLOAD_TESTING_PATH=%HELIX_CORRELATION_PAYLOAD%\%SDK_DIR_NAME%" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export SDK_FOR_WORKLOAD_TESTING_PATH=$HELIX_CORRELATION_PAYLOAD/$SDK_DIR_NAME" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set TestsRunningOutsideOfRepo=true" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export TestsRunningOutsideOfRepo=true" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set BUILT_NUGETS_PATH=%HELIX_CORRELATION_PAYLOAD%\built-nugets" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export BUILT_NUGETS_PATH=$HELIX_CORRELATION_PAYLOAD/built-nugets" />

<HelixPreCommand Condition="'$(OS)' == 'Windows_NT'" Include="set TEST_LOG_PATH=%HELIX_WORKITEM_UPLOAD_ROOT%/logs" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="export TEST_LOG_PATH=$HELIX_WORKITEM_UPLOAD_ROOT/logs" />

<HelixPreCommand Include="docker info" />
<HelixPreCommand Include="docker ps" />
<HelixPreCommand Include="docker container ls --all" />
<HelixPreCommand Condition="'$(OS)' != 'Windows_NT'" Include="docker ps -aq | xargs docker stop | xargs docker rm" />
</PropertyGroup>

<HelixPostCommand Include="docker container ls --all" />
<HelixPostCommand Condition="'$(OS)' != 'Windows_NT'" Include="docker ps -aq | xargs docker stop | xargs docker rm" />
</ItemGroup>
<Target Name="BuildHelixWorkItemsForEnd2EndTests">
<Error Condition="'$(_E2ETestsArchivePath)' == '' or !Exists($(_E2ETestsArchivePath))"
Text="Could not find EndToEnd tests at %24(_E2ETestsArchivePath)=$(_E2ETestsArchivePath)" />

<Target Name="BuildHelixWorkItemsForEnd2EndTests" Condition="'$(_E2ETestsArchivePath)' != '' and Exists($(_E2ETestsArchivePath))">
<PropertyGroup>
<_TestScenarioEnvVar Condition="'$(OS)' == 'Windows_NT'">%TEST_SCENARIO%</_TestScenarioEnvVar>
<_TestScenarioEnvVar Condition="'$(OS)' != 'Windows_NT'">${TEST_SCENARIO}</_TestScenarioEnvVar>
Expand All @@ -50,7 +21,6 @@
</ItemGroup>

<PropertyGroup>
<_WorkItemTimeoutForEndToEndTests>00:20:00</_WorkItemTimeoutForEndToEndTests>
<_WorkItemName>$([System.IO.Path]::GetFileNameWithoutExtension($(_E2ETestsArchivePath)))</_WorkItemName>

<HelixPreCommands>$(HelixPreCommands);@(HelixPreCommand)</HelixPreCommands>
Expand All @@ -75,7 +45,7 @@
<PreCommands Condition="'$(OS)' == 'Windows_NT'">set &quot;TEST_NAME=$(_WorkItemName)&quot; &amp; set TEST_SCENARIO=%(Identity) &amp; set &quot;CODE_COV_FILE_SUFFIX=-%(Identity)&quot;</PreCommands>
<PreCommands Condition="'$(OS)' != 'Windows_NT'">export &quot;TEST_NAME=$(_WorkItemName)&quot; &amp;&amp; export TEST_SCENARIO=%(Identity) &amp;&amp; export &quot;CODE_COV_FILE_SUFFIX=-%(Identity)&quot;</PreCommands>
<Command>$(_TestRunCommand)</Command>
<Timeout>$(_WorkItemTimeoutForEndToEndTests)</Timeout>
<Timeout>$(_workItemTimeout)</Timeout>

<!-- Download results file so coverage files can be extracted -->
<DownloadFilesFromResults>logs/Aspire.EndToEnd.Tests-%(Identity).cobertura.xml</DownloadFilesFromResults>
Expand Down

0 comments on commit 4976389

Please sign in to comment.