-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Add PR category detection for UI tests #33176
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
base: main
Are you sure you want to change the base?
Changes from all commits
a7e4e33
fdbc7cb
068e0e8
d252f7c
3a1df7b
0104024
3903280
6179f0e
a3843b5
9c51137
f6e8f5f
f2ffe5f
e6e4542
f060cc5
07df240
7e2ca94
599710f
d5d2dde
f9ec697
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,23 +15,82 @@ parameters: | |
| checkoutDirectory: $(System.DefaultWorkingDirectory) | ||
|
|
||
| steps: | ||
| # EARLY CHECK: Determine if this category group should run tests | ||
| # This runs FIRST to avoid wasting time on provisioning if no tests will run | ||
| - pwsh: | | ||
| $testFilterParam = $env:CATEGORY_GROUP | ||
| $testFilterFallback = $env:TEST_FILTER_PARAM | ||
| $detectedCategories = $env:DETECTED_CATEGORIES | ||
| $isPR = $env:BUILD_REASON -eq "PullRequest" | ||
|
|
||
| Write-Host "=== Early Category Check ===" | ||
| Write-Host "Build Reason: $env:BUILD_REASON" | ||
| Write-Host "Category Group (from matrix): '$testFilterParam'" | ||
| Write-Host "Test Filter (from parameter): '$testFilterFallback'" | ||
| Write-Host "Detected Categories: '$detectedCategories'" | ||
|
|
||
| # Use testFilter parameter as fallback when CATEGORYGROUP is not set or not expanded | ||
| # When CATEGORYGROUP variable doesn't exist, it shows as literal '$(CATEGORYGROUP)' | ||
| $categoryGroupNotSet = [string]::IsNullOrWhiteSpace($testFilterParam) -or $testFilterParam -eq '$(CATEGORYGROUP)' | ||
| if ($categoryGroupNotSet -and -not [string]::IsNullOrWhiteSpace($testFilterFallback)) { | ||
| $testFilterParam = $testFilterFallback | ||
| Write-Host "Using testFilter parameter as category: '$testFilterParam'" | ||
| } | ||
|
|
||
| $shouldRun = $true | ||
|
|
||
| # For PRs with detected categories, check if this category group has any matches | ||
| if ($isPR -and -not [string]::IsNullOrWhiteSpace($detectedCategories) -and -not [string]::IsNullOrWhiteSpace($testFilterParam)) { | ||
| $categoryList = $testFilterParam -split "," | ||
| $detectedList = $detectedCategories -split "," | ||
| $hasMatch = $false | ||
|
|
||
| foreach ($cat in $categoryList) { | ||
| $cat = $cat.Trim() | ||
| foreach ($det in $detectedList) { | ||
| $det = $det.Trim() | ||
| if ($cat -eq $det) { | ||
| $hasMatch = $true | ||
| Write-Host "Match found: '$cat'" | ||
| break | ||
| } | ||
| } | ||
| if ($hasMatch) { break } | ||
| } | ||
|
|
||
| if (-not $hasMatch) { | ||
| $shouldRun = $false | ||
| Write-Host "##[warning]No matching categories - SKIPPING all steps for this job" | ||
| Write-Host "Category group '$testFilterParam' does not contain any detected categories: $detectedCategories" | ||
| } | ||
| } | ||
|
|
||
| Write-Host "Should run tests: $shouldRun" | ||
| Write-Host "##vso[task.setvariable variable=SHOULD_RUN_TESTS]$shouldRun" | ||
|
Comment on lines
+20
to
+69
|
||
| displayName: 'Check if category should run' | ||
| env: | ||
| CATEGORY_GROUP: $(CATEGORYGROUP) | ||
| TEST_FILTER_PARAM: ${{ parameters.testFilter }} | ||
| DETECTED_CATEGORIES: $(DETECTED_CATEGORIES) | ||
| BUILD_REASON: $(Build.Reason) | ||
|
|
||
| - task: DownloadPipelineArtifact@2 | ||
| condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'Mono')) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'Mono')) | ||
| inputs: | ||
| artifact: ui-tests-samples | ||
|
|
||
| - task: DownloadPipelineArtifact@2 | ||
| condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'NativeAOT')) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'NativeAOT')) | ||
| inputs: | ||
| artifact: ui-tests-samples-nativeaot | ||
|
|
||
| - task: DownloadPipelineArtifact@2 | ||
| condition: and(ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'CoreCLR')) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), ne('${{ parameters.platform }}' , 'windows'), eq('${{ parameters.runtimeVariant }}' , 'CoreCLR')) | ||
| inputs: | ||
| artifact: ui-tests-samples-coreclr | ||
|
|
||
| - task: DownloadPipelineArtifact@2 | ||
| condition: eq('${{ parameters.platform }}' , 'windows') | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), eq('${{ parameters.platform }}' , 'windows')) | ||
| inputs: | ||
| artifact: ui-tests-samples-windows | ||
|
|
||
|
|
@@ -40,6 +99,7 @@ steps: | |
| chmod +x $(System.DefaultWorkingDirectory)/eng/scripts/clean-bot.sh | ||
| $(System.DefaultWorkingDirectory)/eng/scripts/clean-bot.sh | ||
| displayName: 'Clean bot' | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| continueOnError: true | ||
| timeoutInMinutes: 60 | ||
|
|
||
|
|
@@ -50,13 +110,14 @@ steps: | |
| sudo udevadm control --reload-rules | ||
| sudo udevadm trigger --name-match=kvm | ||
| displayName: Enable KVM | ||
| condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), eq(variables['Agent.OS'], 'Linux')) | ||
|
|
||
| - ${{ if eq(parameters.platform, 'catalyst')}}: | ||
| - bash: | | ||
| chmod +x $(System.DefaultWorkingDirectory)/eng/scripts/disable-notification-center.sh | ||
| $(System.DefaultWorkingDirectory)/eng/scripts/disable-notification-center.sh | ||
| displayName: 'Disable Notification Center' | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| continueOnError: true | ||
| timeoutInMinutes: 60 | ||
|
|
||
|
|
@@ -80,7 +141,7 @@ steps: | |
| openSslArgs: '' # Do not use legacy openssl for Catalyst builds | ||
|
|
||
| - task: PowerShell@2 | ||
| condition: and(ne('${{ parameters.platform }}', 'windows'), ne('${{ parameters.platform }}', 'android')) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), ne('${{ parameters.platform }}', 'windows'), ne('${{ parameters.platform }}', 'android')) | ||
| inputs: | ||
| targetType: 'inline' | ||
| script: | | ||
|
|
@@ -92,22 +153,25 @@ steps: | |
|
|
||
| - pwsh: ./build.ps1 --target=dotnet --configuration="${{ parameters.configuration }}" --verbosity=diagnostic | ||
| displayName: 'Install .NET' | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| retryCountOnTaskFailure: 2 | ||
| env: | ||
| DOTNET_TOKEN: $(dotnetbuilds-internal-container-read-token) | ||
| PRIVATE_BUILD: $(PrivateBuild) | ||
|
|
||
| - pwsh: echo "##vso[task.prependpath]$(DotNet.Dir)" | ||
| displayName: 'Add .NET to PATH' | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
|
|
||
| # AzDO hosted agents default to 1024x768; set something bigger for Windows UI tests | ||
| - pwsh: | | ||
| $scriptPath = Join-Path "$(System.DefaultWorkingDirectory)" "eng" "scripts" "Set-ScreenResolution.ps1" | ||
| & $scriptPath -Width 1920 -Height 1080 | ||
| condition: eq('${{ parameters.platform }}' , 'windows') | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True'), eq('${{ parameters.platform }}' , 'windows')) | ||
| displayName: "Set screen resolution" | ||
|
|
||
| - task: UseNode@1 | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| inputs: | ||
| version: "20.3.1" | ||
| displayName: "Install node" | ||
|
|
@@ -116,6 +180,7 @@ steps: | |
| $skipAppiumDoctor = if ($IsMacOS -or $IsLinux) { "true" } else { "false" } | ||
| dotnet build ./src/Provisioning/Provisioning.csproj -t:ProvisionAppium -p:SkipAppiumDoctor="$skipAppiumDoctor" -bl:"$(LogDirectory)/provision-appium.binlog" | ||
| displayName: "Install Appium" | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| continueOnError: false | ||
| retryCountOnTaskFailure: 2 | ||
| timeoutInMinutes: 10 | ||
|
|
@@ -131,12 +196,50 @@ steps: | |
|
|
||
| $testFilter = "" | ||
| $testConfigrationArgs = "${{ parameters.testConfigurationArgs }}" | ||
|
|
||
| "${{ parameters.testFilter }}".Split(",") | ForEach { | ||
| $testFilter += "TestCategory=" + $_ + "|" | ||
|
|
||
| # Get test filter from environment variable (passed from matrix via env block) | ||
| $testFilterParam = $env:CATEGORY_GROUP | ||
| $detectedCategories = $env:DETECTED_CATEGORIES | ||
| $isPR = $env:BUILD_REASON -eq "PullRequest" | ||
|
|
||
| Write-Host "Category Group from matrix: '$testFilterParam'" | ||
| Write-Host "Detected Categories: '$detectedCategories'" | ||
|
|
||
| # Fallback to parameter for non-matrix builds | ||
| if (-not $testFilterParam) { | ||
| $testFilterParam = "${{ parameters.testFilter }}" | ||
| Write-Host "Using testFilter parameter: '$testFilterParam'" | ||
| } | ||
|
|
||
| # For PRs with detected categories, use only matching categories | ||
| if ($isPR -and -not [string]::IsNullOrWhiteSpace($detectedCategories) -and -not [string]::IsNullOrWhiteSpace($testFilterParam)) { | ||
| $categoryList = $testFilterParam -split "," | ||
| $detectedList = $detectedCategories -split "," | ||
| $matchingCategories = @() | ||
|
|
||
| foreach ($cat in $categoryList) { | ||
| $cat = $cat.Trim() | ||
| foreach ($det in $detectedList) { | ||
| $det = $det.Trim() | ||
| if ($cat -eq $det) { | ||
| $matchingCategories += $cat | ||
| break | ||
| } | ||
| } | ||
|
Comment on lines
+220
to
+228
|
||
| } | ||
|
|
||
| $testFilterParam = $matchingCategories -join "," | ||
| Write-Host "Running matching categories: $testFilterParam" | ||
| } | ||
|
|
||
| Write-Host "Final test filter: '$testFilterParam'" | ||
|
|
||
| if ($testFilterParam) { | ||
| $testFilterParam.Split(",") | ForEach { | ||
| $testFilter += "TestCategory=" + $_ + "|" | ||
| } | ||
| $testFilter = $testFilter.TrimEnd("|") | ||
| } | ||
|
|
||
| $testFilter = $testFilter.TrimEnd("|") | ||
|
|
||
|
Comment on lines
196
to
243
|
||
| # Cake does not allow empty parameters, so check if our filter is empty before adding it | ||
| if ($testConfigrationArgs) { | ||
|
|
@@ -155,10 +258,14 @@ steps: | |
|
|
||
| Invoke-Expression $command | ||
| displayName: $(Agent.JobName) | ||
| condition: and(succeeded(), eq(variables['SHOULD_RUN_TESTS'], 'True')) | ||
| ${{ if ne(parameters.platform, 'android')}}: | ||
| retryCountOnTaskFailure: 1 | ||
| env: | ||
| APPIUM_HOME: $(APPIUM_HOME) | ||
| CATEGORY_GROUP: $(CATEGORYGROUP) | ||
| DETECTED_CATEGORIES: $(DETECTED_CATEGORIES) | ||
| BUILD_REASON: $(Build.Reason) | ||
|
|
||
| - bash: | | ||
| cat ${BASH_SOURCE[0]} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The category comparison at lines 52 and 224 uses case-sensitive string equality (
$cat -eq $det). However, the HashSet used for collecting categories in the PowerShell detection script uses case-insensitive comparison (line 57:[System.StringComparer]::OrdinalIgnoreCase). This inconsistency could cause matching failures if category names differ in case between the detection script output and the matrix CATEGORYGROUP values. Use case-insensitive comparison here as well with-ieqor.ToLower()for consistency.