[ci] Enable Linux Android integration tests with workload and KVM support#34046
[ci] Enable Linux Android integration tests with workload and KVM support#34046rmarinho merged 4 commits intofix-android-run-linuxfrom
Conversation
On Linux, we should install the maui-android workload instead of the full maui workload to avoid iOS/macOS dependencies that cannot be installed on Linux. This matches the pattern used in _InstallWorkloadPacks target where iOS/macOS workloads are excluded on Linux. Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
|
/azp run maui-pr |
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
|
@copilot can you also check seems we need to enable KVM , we have a script for that somewhere |
Android emulators require KVM to be enabled on Linux hosts. This adds the KVM enablement step to the setup-test-env.yml template, which is used by the integration tests stage. The script creates udev rules to allow KVM access and reloads the udev rules. This matches the pattern used in device-tests-steps.yml and ui-tests-steps.yml. Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com>
I've enabled KVM for Android integration tests on Linux by adding the KVM enablement step to The script creates udev rules to allow KVM access and is conditionally executed only on Linux agents. Commit: ba58555 |
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Enable KVM for Android integration tests on Linux ·
|
| Commenter | Comment | Action Taken |
|---|---|---|
| rmarinho | Initial PR #33997 failure: "Can't install maui on linux" | Spawned PR #34046 (Copilot) |
| rmarinho | "@copilot can you also check seems we need to enable KVM" | Copilot added KVM step in commit ba58555 |
No disagreements. rmarinho requested KVM enablement, which was added.
Files Changed
eng/pipelines/arcade/setup-test-env.yml(+10): Added KVM enablement step for Linux Android testssrc/DotNet/DotNet.csproj(+2, -1): Conditional workload installation (maui-android on Linux, maui elsewhere)
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34046 | Conditional maui-android workload on Linux + KVM enablement step |
⏳ PENDING (Gate) | DotNet.csproj (+2), setup-test-env.yml (+10) |
CI-only change, no functional code tests |
Important Notes
- This is a CI infrastructure-only change — no functional code, no UI tests, no integration test cases to run locally
- The Gate phase will need to assess differently since there are no tests to verify fail/pass behavior
- The fix follows established patterns in the codebase
🚦 Gate — Test Verification
📝 Review Session — Enable KVM for Android integration tests on Linux · ba58555
Result: ⏳ SKIPPED (CI Infrastructure Change)
Platform: N/A
Mode: N/A
Reason for Skip
This PR is a CI infrastructure-only change. It modifies:
eng/pipelines/arcade/setup-test-env.yml— Azure DevOps pipeline YAMLsrc/DotNet/DotNet.csproj— MSBuild workload installation target
There are no functional code changes and no UI/integration tests associated with this PR. The changes can only be verified by running the actual CI pipeline on Linux Azure DevOps agents, which is not possible locally.
Verification Notes
- No test files exist matching this PR (
*34046*,*33997*) - The fix is a CI pipeline/build system change that cannot be reproduced locally
- Gate verification (fail-without-fix / pass-with-fix) is not applicable to CI infrastructure PRs
- The correctness of the changes was assessed via code review only
Gate Result
Gate:
🔧 Fix — Analysis & Comparison
📝 Review Session — Enable KVM for Android integration tests on Linux · ba58555
Fix Candidates
Phase 3 (try-fix) SKIPPED — This is a CI infrastructure change with no functional code tests.
The PR modifies Azure DevOps pipeline YAML and MSBuild targets. There are no unit tests, UI tests, or integration tests that can be run locally to verify fail-without-fix / pass-with-fix behavior. The correctness can only be validated by running the actual CI pipeline on Linux agents.
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34046 | Conditional maui-android workload on Linux + KVM enablement step |
DotNet.csproj (+2), setup-test-env.yml (+10) |
CI infrastructure only |
Exhausted: N/A (CI infrastructure change - try-fix not applicable)
Selected Fix: PR's fix — The approach is correct, follows established patterns in the codebase, and directly addresses both failure modes identified in issue #33997.
📋 Report — Final Recommendation
📝 Review Session — Enable KVM for Android integration tests on Linux · ba58555
✅ Final Recommendation: APPROVE
Summary
PR #34046 fixes two CI infrastructure issues that prevented Android integration tests from running on Linux agents (introduced by PR #33997 which moved the mac_runandroid_tests stage to Linux pools):
-
Workload installation failure: On Linux, the
Installtarget was trying to install the fullmauiworkload (which includes iOS/macOS dependencies). Fixed by conditionally installingmaui-androidon Linux andmauion other platforms. -
Missing KVM support: Android emulators need KVM for hardware acceleration on Linux. The KVM enablement step was already present in
device-tests-steps.ymlandui-tests-steps.yml, but was missing fromsetup-test-env.yml(used by integration tests). Added it with the same pattern.
Root Cause
The CI migration from macOS to Linux pools (PR #33997) didn't account for two Linux-specific requirements:
- The
mauiworkload includes iOS/macOS workloads that cannot be installed on Linux - Linux Android emulators require explicit KVM permission setup via udev rules
Code Review
src/DotNet/DotNet.csproj ✅
- Conditional uses
$([MSBuild]::IsOSPlatform('linux'))— the same API used elsewhere in this file (lines 186-189, 245, 261, 277, 293) for identical iOS/macOS exclusions - Comment clearly explains the reason
- Pattern is consistent with the existing
_InstallWorkloadPackstarget approach - No concerns
eng/pipelines/arcade/setup-test-env.yml ✅
- KVM step matches the exact same script used in
device-tests-steps.ymlandui-tests-steps.yml - Uses runtime condition
and(succeeded(), eq(variables['Agent.OS'], 'Linux'))rather than a template-time${{ if }}guard — this is acceptable; it means the step appears in all job definitions but is a no-op on non-Linux agents - In the other files, the step uses
${{ if eq(parameters.platform, 'android') }}at template-time. That conditional isn't available insetup-test-env.yml(no platform parameter), but the runtime Linux condition is sufficient since the step is safe to run on Linux regardless - No concerns
Minor Observation (Non-blocking)
The mac_runandroid_tests stage in ci.yml (from PR #33997) has both branches of an ${{ if }} pointing to AndroidPoolLinux:
${{ if eq(variables['Build.DefinitionName'], 'maui-pr') }}:
pool: ${{ parameters.AndroidPoolLinux }}
${{ else }}:
pool: ${{ parameters.AndroidPoolLinux }}This is redundant but harmless. It could be simplified to just pool: ${{ parameters.AndroidPoolLinux }}, but this is from the parent PR #33997 and not in scope for PR #34046.
Fix Quality
The fix is minimal, correct, and follows established patterns. Both changes have clear precedent in the codebase. No alternative approaches were explored (not applicable for CI infrastructure changes).
PR Title Accuracy: ✅ Accurate — "Enable Linux Android integration tests with workload and KVM support" correctly describes both changes.
PR Description Accuracy: ✅ Accurate — Correctly explains the problem and solution, references the existing patterns.
📋 Expand PR Finalization Review
Title: ✅ Good
Current: [ci] Enable Linux Android integration tests with workload and KVM support
Description: ✅ Good
Description needs updates. See details below.
✨ Suggested PR Description
[!NOTE]
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
The mac_runandroid_tests stage was moved to Linux pools but failed due to two issues: workload installation attempted to install the full maui workload (which includes iOS/macOS dependencies unavailable on Linux), and KVM was not enabled for Android emulator support.
Changes:
- Modified
src/DotNet/DotNet.csprojInstalltarget to conditionally installmaui-androidon Linux,mauion other platforms- Aligns with existing pattern in
_InstallWorkloadPackstarget where iOS/macOS workloads are excluded on Linux
- Aligns with existing pattern in
- Added KVM enablement step to
eng/pipelines/arcade/setup-test-env.ymlfor Android integration tests on Linux- Creates udev rules to allow KVM access for Android emulators
- Matches pattern used in
device-tests-steps.ymlandui-tests-steps.yml
<_LocalWorkloadIds Include="maui-android" Condition="$([MSBuild]::IsOSPlatform('linux'))" />
<_LocalWorkloadIds Include="maui" Condition="!$([MSBuild]::IsOSPlatform('linux'))" />Issues Fixed
Fixes #33997
Code Review: ✅ Passed
Code Review — PR #34046
✅ No Critical Issues
The implementation is minimal, correct, and follows established patterns in the codebase.
File: src/DotNet/DotNet.csproj
✅ Conditional workload installation
<!-- On Linux, install maui-android instead of maui to avoid iOS/macOS dependencies -->
<_LocalWorkloadIds Include="maui-android" Condition="$([MSBuild]::IsOSPlatform('linux'))" />
<_LocalWorkloadIds Include="maui" Condition="!$([MSBuild]::IsOSPlatform('linux'))" />- Pattern consistency: ✅ Uses the exact same
$([MSBuild]::IsOSPlatform('linux'))API already used at lines 186–189, 245, 261, 277, 293 of this file for identical iOS/macOS exclusions in_InstallWorkloadPacks. - Comment: ✅ Clear and explains the "why."
- Correctness: ✅
maui-androidis the correct workload ID for Linux-only Android support.
File: eng/pipelines/arcade/setup-test-env.yml
✅ KVM enablement step
- bash: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
displayName: Enable KVM
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))- Pattern consistency: ✅ Identical script to
device-tests-steps.ymlandui-tests-steps.yml. Verified in codebase. - Condition style: ℹ️ Uses runtime condition
eq(variables['Agent.OS'], 'Linux')rather than template-time${{ if eq(parameters.platform, 'android') }}used in the other files. This is acceptable because:setup-test-env.ymlhas noplatformparameter to guard on at template-time- The runtime Linux condition is sufficient — the step is a no-op if not on Linux and is safe to run on any Linux agent
- The step appears in the job definition for all agents but is skipped at runtime on non-Linux agents (minor cost)
- No security concerns: The udev rules grant group-based KVM access, which is standard practice for Android emulator CI setups.
🟡 Minor Observations (Non-blocking)
-
Condition style difference (noted above): Runtime vs. template-time Linux condition. Functionally correct but slightly less efficient than a template-time guard. Acceptable for this use case.
-
maui-androidworkload completeness: Ensuremaui-androidincludes everything needed for the integration tests being run. This appears to be correct based on existing patterns in_InstallWorkloadPacks, but can only be fully validated by running the actual CI pipeline on Linux.
✅ Looks Good
- Minimal change, targeted fix
- Both changes have direct precedent in the codebase
- Follows the established Linux exclusion pattern throughout
DotNet.csproj - KVM script is byte-for-byte identical to the working script in other pipeline files
- No functional code changes — CI infrastructure only
|
@copilot Also when "Install dotnet preview workloads from PackageArtifacts" we need to make sure if we are on linux to only install maui-android workload |
|
@copilot Also when "Install dotnet preview workloads from PackageArtifacts" we need to make sure if we are on linux to only install maui-android workload |
This change was already implemented in commit 1c9bc98. The The logic uses
This change was already implemented in commit 1c9bc98. The The logic uses |
On Linux, only the maui-android workload is installed. Previous .NET templates (e.g., net9.0) may not have the Linux OS condition to exclude iOS/macOS target frameworks from the csproj. This causes NETSDK1178 errors during restore because the iOS workload packs are not available. After template creation, strip non-Android TFMs from the generated csproj when running on Linux so builds succeed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…port (#34046) The `mac_runandroid_tests` stage was moved to Linux pools but failed due to two issues: workload installation attempted to install the full `maui` workload (which includes iOS/macOS dependencies unavailable on Linux), and KVM was not enabled for Android emulator support. **Changes:** - Modified `src/DotNet/DotNet.csproj` `Install` target to conditionally install `maui-android` on Linux, `maui` on other platforms - Aligns with existing pattern in `_InstallWorkloadPacks` target where iOS/macOS workloads are excluded on Linux - Added KVM enablement step to `eng/pipelines/arcade/setup-test-env.yml` for Android integration tests on Linux - Creates udev rules to allow KVM access for Android emulators - Matches pattern used in `device-tests-steps.yml` and `ui-tests-steps.yml` ```xml <ItemGroup> <!-- On Linux, install maui-android instead of maui to avoid iOS/macOS dependencies --> <_LocalWorkloadIds Include="maui-android" Condition="$([MSBuild]::IsOSPlatform('linux'))" /> <_LocalWorkloadIds Include="maui" Condition="!$([MSBuild]::IsOSPlatform('linux'))" /> </ItemGroup> ``` <!-- START COPILOT CODING AGENT TIPS -->
The
mac_runandroid_testsstage was moved to Linux pools but failed due to two issues: workload installation attempted to install the fullmauiworkload (which includes iOS/macOS dependencies unavailable on Linux), and KVM was not enabled for Android emulator support.Changes:
src/DotNet/DotNet.csprojInstalltarget to conditionally installmaui-androidon Linux,mauion other platforms_InstallWorkloadPackstarget where iOS/macOS workloads are excluded on Linuxeng/pipelines/arcade/setup-test-env.ymlfor Android integration tests on Linuxdevice-tests-steps.ymlandui-tests-steps.yml💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.