Skip to content
Open
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
12 changes: 12 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ Major test projects:

Find all tests: `find . -name "*.UnitTests.csproj"`

### CI Pipelines (Azure DevOps)

When referencing or triggering CI pipelines, use these current pipeline names:

| Pipeline | Name | Purpose |
|----------|------|---------|
| Overall CI | `maui-pr` | Full PR validation build |
| Device Tests | `maui-pr-devicetests` | Helix-based device tests |
| UI Tests | `maui-pr-uitests` | Appium-based UI tests |

**⚠️ Old pipeline names** (e.g., `MAUI-UITests-public`, `MAUI-public`) are **outdated** and should NOT be used. Always use the names above.

### Code Formatting

Always format code before committing:
Expand Down
11 changes: 11 additions & 0 deletions .github/instructions/uitests.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,17 @@ cat /tmp/ios_crash.log | grep -A 20 -B 5 "Exception"
5. **Check for platform-specific issues** - iOS version compatibility, permissions, etc.
6. If you can't determine the fix, **ask for guidance** with the full exception details

### Dangerous System Commands (Never Run)

**🚨 NEVER run these commands — they cause destructive system-wide side effects:**

- **`tccutil reset`** — Wipes ALL macOS permissions (Accessibility, Camera, etc.) system-wide. This breaks Appium/WebDriverAgent, Xcode, and other tools. Once reset, permissions must be manually re-granted through System Settings.
- **`csrutil disable`** — Disables System Integrity Protection
- **`networksetup`** — Modifies network configuration
- **`defaults delete`** on system domains — Resets system preferences

**General rule:** Do not run commands that modify macOS system-level privacy, security, or permission settings. If you need to check permissions, read them — never reset or modify them.

## Before Committing

Verify the following checklist before committing UI tests:
Expand Down
4 changes: 3 additions & 1 deletion .github/scripts/BuildAndRunHostApp.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,9 @@ if ($Platform -eq "catalyst") {
& chmod +x $executablePath
}

Write-Success "MacCatalyst app prepared (Appium will launch with test name)"
# Set MAC_APP_PATH so Appium mac2 driver can launch the app directly
$env:MAC_APP_PATH = $appPath
Write-Success "MacCatalyst app prepared (MAC_APP_PATH=$appPath)"
} else {
Write-Warn "MacCatalyst app not found at: $appPath"
Write-Warn "Test may use wrong app bundle if another version is registered"
Expand Down
24 changes: 17 additions & 7 deletions .github/scripts/shared/Start-Emulator.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
.DESCRIPTION
Handles device detection and startup for both Android and iOS platforms.
- Android: Automatically selects and starts emulator with priority: API 30 Nexus > API 30 > Nexus > First available
- iOS: Automatically selects iPhone Xs with iOS 18.5 by default
- iOS: Automatically selects iPhone Xs with iOS 18.x (or iPhone 11 Pro with iOS 26.x) to match CI
.PARAMETER Platform
Target platform: "android" or "ios"
Expand Down Expand Up @@ -344,10 +344,17 @@ if ($Platform -eq "android") {
Write-Info "Auto-detecting iOS simulator..."
$simList = xcrun simctl list devices available --json | ConvertFrom-Json

# Preferred devices in order of priority
$preferredDevices = @("iPhone 16 Pro", "iPhone 15 Pro", "iPhone 14 Pro", "iPhone Xs")
# Preferred iOS versions in order (stable preferred, beta fallback)
$preferredVersions = @("iOS-18", "iOS-17", "iOS-26")
# Preferred devices per iOS version to match CI configuration:
# iOS 18.x → iPhone Xs (matches CI default in UITest.cs)
# iOS 26.x → iPhone 11 Pro (matches CI visual test requirement)
# iOS 17.x → iPhone Xs (fallback)
$preferredDevicesPerVersion = @{
"iOS-18" = @("iPhone Xs", "iPhone 16 Pro", "iPhone 15 Pro", "iPhone 14 Pro")
"iOS-17" = @("iPhone Xs", "iPhone 15 Pro", "iPhone 14 Pro")
"iOS-26" = @("iPhone 11 Pro", "iPhone 16 Pro", "iPhone 15 Pro")
}

$selectedDevice = $null
$selectedVersion = $null
Expand All @@ -356,13 +363,16 @@ if ($Platform -eq "android") {
foreach ($version in $preferredVersions) {
if ($selectedDevice) { break }

# Get all runtimes matching this version prefix
# Get all runtimes matching this version prefix, sorted by version descending
# so the latest minor version is preferred (e.g., iOS-18-5 before iOS-18-3)
$matchingRuntimes = $simList.devices.PSObject.Properties |
Where-Object { $_.Name -match $version }
Where-Object { $_.Name -match $version } |
Sort-Object { $_.Name } -Descending

if ($matchingRuntimes) {
# Try each preferred device
foreach ($deviceName in $preferredDevices) {
# Try each preferred device for this version
$devicesForVersion = if ($preferredDevicesPerVersion.ContainsKey($version)) { $preferredDevicesPerVersion[$version] } else { @("iPhone Xs", "iPhone 16 Pro") }
foreach ($deviceName in $devicesForVersion) {
$device = $null
$deviceRuntime = $null
foreach ($rt in $matchingRuntimes) {
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/bump-global-json.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Bump global.json for dotnet/dotnet bumps
on: pull_request_target

jobs:
bump-global-json:
name: Bump global.json
runs-on: ubuntu-latest
# GITHUB_TOKEN change from read-write to read-only on 2024-02-01 requires permissions block
# https://docs.opensource.microsoft.com/github/apps/permission-changes/
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
permissions:
contents: write
if: contains(github.event.pull_request.title, 'Update dependencies from dotnet/') && github.actor == 'dotnet-maestro[bot]'
steps:
- name: 'Checkout repo'
uses: actions/checkout@v6
with:
fetch-depth: 0
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}

- name: 'Update global.json'
env:
PR_NUMBER: ${{ github.event.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
set -exo pipefail

sudo apt-get install libxml2-utils
DOTNET_VERSION=$(xmllint --xpath '/Project/PropertyGroup/MicrosoftNETSdkPackageVersion/text()' eng/Versions.props)

jq '.tools.dotnet = "'$DOTNET_VERSION'"' global.json > global.json.tmp
mv global.json.tmp global.json
if git diff --exit-code -- global.json; then
echo "No global.json update necessary"
exit 0
fi
git add -- global.json
git config --global user.email "github-actions@xamarin.com"
git config --global user.name "GitHub Actions"
git checkout "$GITHUB_HEAD_REF"
git commit -m "Re-generate global.json for PR #$PR_NUMBER: $PR_TITLE"
git push
33 changes: 15 additions & 18 deletions .github/workflows/dogfood-comment.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
name: Add Dogfooding Comment

on:
# Trigger when the maui-pr build check completes
check_run:
types: [completed]
# Use pull_request_target to run in the context of the base branch
# This allows commenting on PRs from forks
# Note: check_run trigger doesn't work because Azure DevOps check runs
# don't populate the pull_requests[] field, so we can't get the PR number.
pull_request_target:
types: [opened, reopened, synchronize]
branches:
- 'main'
- 'net*'
- 'release/**'

# Allow manual triggering
workflow_dispatch:
Expand All @@ -15,23 +22,13 @@ on:

# Ensure only one instance runs at a time per PR to prevent duplicate comments
concurrency:
group: dogfood-comment-${{ github.event.check_run.pull_requests[0].number || github.event.inputs.pr_number || 'unknown' }}
group: dogfood-comment-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
cancel-in-progress: true

jobs:
add-dogfood-comment:
# Only run on the dotnet org, for the maui-pr check, when it completes successfully
if: |
github.repository_owner == 'dotnet' &&
(
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'check_run' &&
github.event.check_run.name == 'maui-pr (Pack .NET MAUI Pack Windows)' &&
github.event.check_run.conclusion == 'success' &&
github.event.check_run.pull_requests[0] != null
)
)
# Only run on the dotnet org to avoid running on forks
if: ${{ github.repository_owner == 'dotnet' }}
runs-on: ubuntu-latest
permissions:
pull-requests: write
Expand All @@ -41,8 +38,8 @@ jobs:
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
// Get PR number from either the check_run event or manual input
const prNumber = context.payload.check_run?.pull_requests?.[0]?.number || context.payload.inputs?.pr_number;
// Get PR number from either the PR event or manual input
const prNumber = context.payload.pull_request?.number || context.payload.inputs?.pr_number;

const bashScript = 'https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh';
const psScript = 'https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1';
Expand Down
12 changes: 12 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
<!-- `clear` ensures no additional sources are inherited from another config file. -->
<packageSources>
<clear />
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-android -->
<!-- End: Package sources from dotnet-android -->
<!-- Begin: Package sources from dotnet-macios -->
<!-- End: Package sources from dotnet-macios -->
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
<!-- Begin: Package sources from dotnet-dotnet -->
<add key="darc-pub-dotnet-dotnet-e17b0d0" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-dotnet-e17b0d08/nuget/v3/index.json" />
<!-- End: Package sources from dotnet-dotnet -->
Expand All @@ -15,6 +21,12 @@
<add key="dotnet-libraries-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries-transport/nuget/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" protocolVersion="3" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" protocolVersion="3" />
<add key="dotnet11" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet11/nuget/v3/index.json" />
<add key="dotnet11-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet11-transport/nuget/v3/index.json" />
<add key="dotnet10" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10/nuget/v3/index.json" />
<add key="dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
<add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
<add key="dotnet9-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9-transport/nuget/v3/index.json" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
Expand Down
Loading