Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
107 changes: 76 additions & 31 deletions build-tools/automation/yaml-templates/apk-instrumentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ parameters:
condition: succeeded()

steps:
# Build and install the APK to the device first, so that ComputeRunArguments
# can resolve the package name from AndroidManifest.xml.
# Build and install the APK to the device.
#
# Retry the install up to 3 times: the emulator/ADB connection occasionally
# drops mid-install (XAGCPU7000 "device offline") and a retry usually recovers.
Expand All @@ -34,7 +33,77 @@ steps:
retryCountOnTaskFailure: 3
continueOnError: false

# If the install above failed, snapshot device state so we can classify WHY on
# WORKAROUND: neither 'dotnet test' nor 'dotnet run' can be used to start the
# tests right now.
#
# 'dotnet test' fails to deploy to a device (dotnet/android#12254). 'dotnet run'
# gets further, but both of them deploy from a *second* MSBuild submission that
# does not go through 'Build'. _CollectJavaSourceForBinding and _CompileBindingJava
# only run as part of 'Build', so that second pass re-runs _CompileJava without the
# binding classes jar on javac's classpath and fails with XAJVC0000 'cannot find
# symbol'.
#
# The install above is a real 'Build', so it is correct. All that is left is to
# start the instrumentation, which is exactly what Microsoft.Android.Run does:
# adb shell am instrument -w -r <package>/<instrumentation>
# (src/Microsoft.Android.Run/AndroidTestAdapter.cs). Do that directly and skip the
# second MSBuild pass entirely.
#
# The on-device runner writes its own TRX (tests/TestRunner.Core/TestInstrumentation.cs)
# and reports it back as 'INSTRUMENTATION_RESULT: resultsPath=<device path>', so we
# scrape that and pull the TRX to where PublishTestResults expects it.
#
# Revert to 'dotnet test' once the SDK fix flows in.
- powershell: |
$ErrorActionPreference = "Continue"
$projectDir = Join-Path "${{ parameters.xaSourcePath }}" (Split-Path -Parent "${{ parameters.project }}")
$resultsDir = "${{ parameters.xaSourcePath }}/bin/Test${{ parameters.configuration }}/TestResults"
New-Item -ItemType Directory -Force -Path $resultsDir | Out-Null

# The <instrumentation/> element is generated into the manifest at build time
# from the [Instrumentation] attribute, so read the built manifest, not the
# one in the project.
$manifest = Get-ChildItem -Path (Join-Path $projectDir "obj/${{ parameters.configuration }}") -Recurse -Filter AndroidManifest.xml -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -replace '\\','/' -match '/android/manifest/AndroidManifest.xml$' } |
Select-Object -First 1
if (-not $manifest) {
Write-Host "##vso[task.logissue type=error]Could not find a generated AndroidManifest.xml under '$projectDir/obj/${{ parameters.configuration }}'."
exit 1
}
Write-Host "Using manifest: $($manifest.FullName)"
[xml]$xml = Get-Content $manifest.FullName
$ns = "http://schemas.android.com/apk/res/android"
$package = $xml.manifest.package
$instrumentation = $xml.manifest.instrumentation | Select-Object -First 1
if (-not $package -or -not $instrumentation) {
Write-Host "##vso[task.logissue type=error]Manifest '$($manifest.FullName)' has no package and/or <instrumentation/> element."
exit 1
}
$runner = $instrumentation.GetAttribute("name", $ns)
Write-Host "Running $package/$runner"
& adb shell am instrument -w -r "$package/$runner" 2>&1 | Tee-Object -Variable runOutput
$runExitCode = $LASTEXITCODE

$match = $runOutput | Select-String -Pattern 'INSTRUMENTATION_RESULT:\s*resultsPath=(.+)$' | Select-Object -Last 1
if (-not $match) {
Write-Host "##vso[task.logissue type=error]Instrumentation did not report a resultsPath; no TRX to publish. 'am instrument' exited with $runExitCode."
exit 1
}
$devicePath = $match.Matches[0].Groups[1].Value.Trim()
$trxPath = "$resultsDir/${{ parameters.testName }}.trx"
Write-Host "Pulling TRX from device: $devicePath"
& adb pull "$devicePath" "$trxPath"
if (-not (Test-Path $trxPath)) {
Write-Host "##vso[task.logissue type=error]Failed to pull TRX from device path '$devicePath'."
exit 1
}
if ($runOutput -match 'INSTRUMENTATION_FAILED') { exit 1 }
exit $runExitCode
displayName: run ${{ parameters.testName }}
condition: ${{ parameters.condition }}
continueOnError: true

# If the deploy above failed, snapshot device state so we can classify WHY on
# the next iteration instead of guessing: connectivity (adb devices/get-state),
# disk pressure (df), storage-service readiness (the StorageStatsManager NPE
# from install-create), boot completion, and how many test apps have piled up.
Expand All @@ -56,30 +125,6 @@ steps:
continueOnError: true
timeoutInMinutes: 3

# Run dotnet test from the project directory so it finds the project-local
# global.json with "test": { "runner": "Microsoft.Testing.Platform" }.
# This enables MTP mode, which uses RunCommand/RunArguments to invoke
# Microsoft.Android.Run for on-device test execution.
- powershell: |
$projectDir = Split-Path -Parent "${{ parameters.project }}"
$projectFile = Split-Path -Leaf "${{ parameters.project }}"
$resultsDir = "${{ parameters.xaSourcePath }}/bin/Test${{ parameters.configuration }}/TestResults"
Push-Location $projectDir
if ([Environment]::OSVersion.Platform -eq "Unix") {
$DOTNET_ROOT = "${{ parameters.xaSourcePath }}/bin/${{ parameters.buildConfiguration }}/dotnet"
$env:PATH = "${DOTNET_ROOT}:$env:PATH"
$dotnetPath = "${DOTNET_ROOT}/dotnet"
} else {
$DOTNET_ROOT = "${{ parameters.xaSourcePath }}\bin\${{ parameters.buildConfiguration }}\dotnet"
$env:PATH = "${DOTNET_ROOT};$env:PATH"
$dotnetPath = "${DOTNET_ROOT}\dotnet.exe"
}
& $dotnetPath test $projectFile --no-build -bl:${{ parameters.xaSourcePath }}/bin/Test${{ parameters.configuration }}/run-${{ parameters.testName }}.binlog -c ${{ parameters.configuration }} --results-directory $resultsDir --report-trx --report-trx-filename ${{ parameters.testName }}.trx --output Detailed ${{ parameters.extraBuildArgs }}
Pop-Location
displayName: run ${{ parameters.testName }}
condition: ${{ parameters.condition }}
continueOnError: true

- script: >
DEST="$(Build.StagingDirectory)/Test${{ parameters.configuration }}/${{ parameters.artifactFolder }}/" &&
mkdir -p "$DEST" &&
Expand All @@ -95,10 +140,10 @@ steps:
# any UnsatisfiedLinkError / dlopen messages only appear in logcat.
#
# Use always() (not the default succeeded()) so we still capture logcat when an
# earlier step failed or the job was canceled - in particular a failed -t:Install
# (which now fails the lane fast) or a hung/timed-out test run. Losing logcat in
# exactly those cases would defeat the diagnostics this template exists for; the
# capture is best-effort (continueOnError + '|| echo'). See dotnet/android#11830.
# earlier step failed or the job was canceled - in particular a failed deploy or a
# hung/timed-out test run. Losing logcat in exactly those cases would defeat the
# diagnostics this template exists for; the capture is best-effort
# (continueOnError + '|| echo'). See dotnet/android#11830.
- script: >
DEST="$(Build.StagingDirectory)/Test${{ parameters.configuration }}/${{ parameters.artifactFolder }}/" &&
mkdir -p "$DEST" &&
Expand Down
28 changes: 14 additions & 14 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.NET.Sdk" Version="11.0.100-preview.7.26365.101">
<Dependency Name="Microsoft.NET.Sdk" Version="11.0.100-preview.7.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.ILLink" Version="11.0.0-preview.7.26365.101">
<Dependency Name="Microsoft.NET.ILLink" Version="11.0.0-preview.7.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="11.0.0-preview.7.26365.101">
<Dependency Name="Microsoft.NETCore.App.Ref" Version="11.0.0-preview.7.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Cecil" Version="0.11.5-preview.26365.101">
<Dependency Name="Microsoft.DotNet.Cecil" Version="0.11.5-preview.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest-11.0.100-preview.4" Version="11.0.100-preview.4.26215.121">
<Uri>https://github.com/dotnet/dotnet</Uri>
Expand All @@ -36,17 +36,17 @@
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="11.0.0-beta.26365.101">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="11.0.0-beta.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="11.0.0-beta.26365.101">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="11.0.0-beta.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="Microsoft.TemplateEngine.Authoring.Tasks" Version="11.0.100-preview.7.26365.101">
<Dependency Name="Microsoft.TemplateEngine.Authoring.Tasks" Version="11.0.100-preview.7.26378.119">
<Uri>https://github.com/dotnet/dotnet</Uri>
<Sha>cb8306a63c5cf24e9381108a3a9eb58907fd0f60</Sha>
<Sha>283ef97f4038f1fc0c75c53cc06667b1ec8b1d6b</Sha>
</Dependency>
<Dependency Name="MSTest" Version="4.4.0-preview.26367.7">
<Uri>https://github.com/microsoft/testfx</Uri>
Expand Down
12 changes: 6 additions & 6 deletions eng/Versions.props
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<Project>
<!--Package versions-->
<PropertyGroup>
<MicrosoftNETSdkPackageVersion>11.0.100-preview.7.26365.101</MicrosoftNETSdkPackageVersion>
<MicrosoftNETSdkPackageVersion>11.0.100-preview.7.26378.119</MicrosoftNETSdkPackageVersion>
<MicrosoftDotnetSdkInternalPackageVersion>$(MicrosoftNETSdkPackageVersion)</MicrosoftDotnetSdkInternalPackageVersion>
<MicrosoftNETILLinkPackageVersion>11.0.0-preview.7.26365.101</MicrosoftNETILLinkPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>11.0.0-preview.7.26365.101</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftNETILLinkPackageVersion>11.0.0-preview.7.26378.119</MicrosoftNETILLinkPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>11.0.0-preview.7.26378.119</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftDotNetApiCompatPackageVersion>7.0.0-beta.22103.1</MicrosoftDotNetApiCompatPackageVersion>
<!-- Last version built for net10.0, needed for CI steps that only have the .NET 10 SDK installed (e.g., BAR manifest publishing) -->
<MicrosoftDotNetBuildTasksFeedPackageVersionNet10>11.0.0-beta.26060.102</MicrosoftDotNetBuildTasksFeedPackageVersionNet10>
<MicrosoftDotNetBuildTasksFeedPackageVersion>11.0.0-beta.26365.101</MicrosoftDotNetBuildTasksFeedPackageVersion>
<MicrosoftDotNetBuildTasksFeedPackageVersion>11.0.0-beta.26378.119</MicrosoftDotNetBuildTasksFeedPackageVersion>
<MicrosoftNETWorkloadMonoToolchainCurrentManifest110100preview4PackageVersion>11.0.100-preview.4.26215.121</MicrosoftNETWorkloadMonoToolchainCurrentManifest110100preview4PackageVersion>
<MicrosoftNETWorkloadEmscriptenCurrentManifest110100preview4PackageVersion>11.0.100-preview.4.26215.121</MicrosoftNETWorkloadEmscriptenCurrentManifest110100preview4PackageVersion>
<MicrosoftNETWorkloadMonoToolChainPackageVersion>$(MicrosoftNETWorkloadMonoToolChainCurrentManifest110100preview4PackageVersion)</MicrosoftNETWorkloadMonoToolChainPackageVersion>
<MicrosoftNETWorkloadEmscriptenPackageVersion>$(MicrosoftNETWorkloadEmscriptenCurrentManifest110100preview4PackageVersion)</MicrosoftNETWorkloadEmscriptenPackageVersion>
<MicrosoftTemplateEngineAuthoringTasksPackageVersion>11.0.100-preview.7.26365.101</MicrosoftTemplateEngineAuthoringTasksPackageVersion>
<MicrosoftDotNetCecilPackageVersion>0.11.5-preview.26365.101</MicrosoftDotNetCecilPackageVersion>
<MicrosoftTemplateEngineAuthoringTasksPackageVersion>11.0.100-preview.7.26378.119</MicrosoftTemplateEngineAuthoringTasksPackageVersion>
<MicrosoftDotNetCecilPackageVersion>0.11.5-preview.26378.119</MicrosoftDotNetCecilPackageVersion>
<MSTestPackageVersion>4.4.0-preview.26367.7</MSTestPackageVersion>
<SystemIOHashingPackageVersion>10.0.10</SystemIOHashingPackageVersion>
<SystemReflectionMetadataPackageVersion>11.0.0-preview.1.26104.118</SystemReflectionMetadataPackageVersion>
Expand Down
2 changes: 2 additions & 0 deletions eng/common/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Param(
[switch] $clean,
[switch][Alias('pb')]$productBuild,
[switch]$fromVMR,
[switch]$disablePipelineSetResult,
[switch][Alias('bl')]$binaryLog,
[string][Alias('bln')]$binaryLogName = '',
[switch][Alias('nobl')]$excludeCIBinarylog,
Expand Down Expand Up @@ -80,6 +81,7 @@ function Print-Usage() {
Write-Host " -nodeReuse <value> Sets nodereuse msbuild parameter ('true' or 'false')"
Write-Host " -buildCheck Sets /check msbuild parameter"
Write-Host " -fromVMR Set when building from within the VMR"
Write-Host " -disablePipelineSetResult Set to disable masking the actual exit code in the pipeline when the build fails"
Write-Host ""

Write-Host "Command line arguments not listed above are passed thru to msbuild."
Expand Down
11 changes: 11 additions & 0 deletions eng/common/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ usage()
echo " --projects <value> Project or solution file(s) to build"
echo " --ci Set when running on CI server"
echo " --excludeCIBinarylog Don't output binary log (short: -nobl)"
echo " --pipelinesLog Promote msbuild errors/warnings to Azure Pipelines timeline issues; defaults to on in CI (short: -pl)"
echo " --prepareMachine Prepare machine for CI run, clean up processes after build"
echo " --nodeReuse <value> Sets nodereuse msbuild parameter ('true' or 'false')"
echo " --warnAsError <value> Sets warnaserror msbuild parameter ('true' or 'false')"
echo " --warnNotAsError <value> Sets a semi-colon delimited list of warning codes that should not be treated as errors"
echo " --buildCheck <value> Sets /check msbuild parameter"
echo " --fromVMR Set when building from within the VMR"
echo " --disablePipelineSetResult Set to disable masking the actual exit code in the pipeline when the build fails"
echo ""
echo "Command line arguments not listed above are passed thru to msbuild."
echo "Arguments can also be passed in with a single hyphen."
Expand All @@ -68,6 +70,7 @@ build=false
source_build=false
product_build=false
from_vmr=false
disable_pipeline_set_result=false
rebuild=false
test=false
integration_test=false
Expand All @@ -86,6 +89,7 @@ build_check=false
binary_log=false
binary_log_name=''
exclude_ci_binary_log=false
pipelines_log=false

projects=''
configuration=''
Expand Down Expand Up @@ -124,6 +128,9 @@ while [[ $# -gt 0 ]]; do
-excludecibinarylog|-nobl)
exclude_ci_binary_log=true
;;
-pipelineslog|-pl)
pipelines_log=true
;;
-restore|-r)
restore=true
;;
Expand Down Expand Up @@ -152,6 +159,9 @@ while [[ $# -gt 0 ]]; do
-fromvmr|-from-vmr)
from_vmr=true
;;
-disablepipelinesetresult|-disable-pipeline-set-result)
disable_pipeline_set_result=true
;;
-test|-t)
test=true
;;
Expand Down Expand Up @@ -213,6 +223,7 @@ if [[ -z "$configuration" ]]; then
fi

if [[ "$ci" == true ]]; then
pipelines_log=true
# Disable node reuse on CI unless explicitly opted in via MSBUILD_NODEREUSE_ENABLED.
# Internal testing only; this env var will be replaced with a switch (https://github.com/dotnet/arcade/issues/17013) and must not be depended on.
if [[ "${MSBUILD_NODEREUSE_ENABLED:-}" != "1" ]]; then
Expand Down
19 changes: 14 additions & 5 deletions eng/common/core-templates/job/helix-job-monitor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ parameters:
type: boolean
default: true

# When true, test results are reported to Azure DevOps using the fully qualified test name
# (Namespace.Type.Method) as the stable automatedTestName and the visible title is qualified as
# well (--use-fully-qualified-test-name). Opt-in because it changes AzDO test identity and display;
# primarily useful for frameworks like MSTest whose display name is only the method name.
- name: useFullyQualifiedTestName
type: boolean
default: false

# Advanced: optional pipeline artifact (produced earlier in this run) that contains the tool
# nupkg. When set, the artifact is downloaded and the tool is installed from the nupkg into
# a local tool-path; this bypasses the repo's .config/dotnet-tools.json manifest and is
Expand Down Expand Up @@ -176,11 +184,12 @@ jobs:
set -euo pipefail

toolArgs=(
--helix-base-uri '${{ parameters.helixBaseUri }}'
--polling-interval-seconds '${{ parameters.pollingIntervalSeconds }}'
--fail-on-failed-tests '${{ parameters.failWorkItemsWithFailedTests }}'
--max-wait-minutes "$((${{ parameters.timeoutInMinutes }} - 5))" # Set the tool's timeout slightly lower than the Azure DevOps job timeout to allow it to exit gracefully.
--stage-name '$(System.StageName)'
--helix-base-uri '${{ parameters.helixBaseUri }}'
--polling-interval-seconds '${{ parameters.pollingIntervalSeconds }}'
--fail-on-failed-tests '${{ parameters.failWorkItemsWithFailedTests }}'
--use-fully-qualified-test-name '${{ parameters.useFullyQualifiedTestName }}'
--max-wait-minutes "$((${{ parameters.timeoutInMinutes }} - 5))" # Set the tool's timeout slightly lower than the Azure DevOps job timeout to allow it to exit gracefully.
--stage-name '$(System.StageName)'
)

organization='${{ parameters.organization }}'
Expand Down
Loading
Loading