Repository navigation
[Microsoft.Android.Build.Tasks] Move FastDeploy task - #13458
simonrozsival wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The new task registration requires an assembly path missing from the AppDetectionTests fixture, causing MSB4022 during project evaluation and breaking all three cases before their targets run.
3 open issues
What changed in this PR
Moves FastDeploy into the modern .NET task assembly, continuing the task migrations in #13382 and #13386 and removing the debugging assembly’s dependency on the System.Text.Json package.
Changes:
- Relocates FastDeploy and its unit tests to the modern task projects.
- Links shared debugging helpers and localized resources, and updates Full/Core MSBuild registrations.
- Preserves deployment parameters and updates the task documentation link.
| File | Description |
|---|---|
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DebuggingTasksTests.cs |
Removes FastDeploy tests relocated to the modern suite. |
src/Xamarin.Android.Build.Debugging.Tasks/Xamarin.Android.Common.Debugging.targets |
Registers the modern task for Full and Core MSBuild. |
src/Xamarin.Android.Build.Debugging.Tasks/Xamarin.Android.Build.Debugging.Tasks.csproj |
Removes the System.Text.Json package reference. |
src/Xamarin.Android.Build.Debugging.Tasks/Utilities/AndroidHelper.cs |
Supports linked compilation and explicit diagnostic formatting culture. |
src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/FastDeployTypeMapTests.cs |
Updates the moved tests’ task namespace. |
src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/FastDeployTests.FakeAdb.cs |
Moves fake-ADB tests into the FastDeploy fixture. |
src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/FastDeployTests.cs |
Houses migrated deployment tests and helpers. |
src/Microsoft.Android.Build.Tasks/Tasks/FastDeployJsonSerializerContext.cs |
Moves JSON source generation into the modern assembly. |
src/Microsoft.Android.Build.Tasks/Tasks/FastDeploy.WarmState.cs |
Relocates warm-state handling. |
src/Microsoft.Android.Build.Tasks/Tasks/FastDeploy.Manifest.cs |
Relocates manifest handling and uses invariant tick formatting. |
src/Microsoft.Android.Build.Tasks/Tasks/FastDeploy.cs |
Moves the task entry point and uses invariant header formatting. |
src/Microsoft.Android.Build.Tasks/Tasks/FastDeploy.Adb.cs |
Relocates ADB command handling. |
src/Microsoft.Android.Build.Tasks/Microsoft.Android.Build.Tasks.csproj |
Links the shared Android helper and debugging resources. |
Documentation/guides/FastDeploy.md |
Points to the task’s new source location. |
Review effort: Balanced
| <UsingTask TaskName="Xamarin.Android.Tasks.GetPrimaryCpuAbi" AssemblyFile="Xamarin.Android.Build.Debugging.Tasks.dll" /> | ||
| <UsingTask TaskName="Xamarin.Android.Tasks.FastDeploy" AssemblyFile="Xamarin.Android.Build.Debugging.Tasks.dll" /> | ||
| <UsingTask TaskName="Microsoft.Android.Tasks.FastDeploy" AssemblyFile="$(_MicrosoftAndroidBuildTasksAssembly)" Runtime="NET" TaskFactory="TaskHostFactory" Condition=" '$(MSBuildRuntimeType)' == 'Full' " /> | ||
| <UsingTask TaskName="Microsoft.Android.Tasks.FastDeploy" AssemblyFile="$(_MicrosoftAndroidBuildTasksAssembly)" Runtime="NET" Condition=" '$(MSBuildRuntimeType)' == 'Core' " /> |
| <EmbeddedResource Include="..\Xamarin.Android.Build.Debugging.Tasks\Properties\Resources*.resx" Link="Properties\Debugging%(Filename)%(Extension)"> | ||
| <ManifestResourceName>Xamarin.Android.Build.Debugging.Tasks.Properties.%(Filename)</ManifestResourceName> | ||
| </EmbeddedResource> |
| <UsingTask TaskName="Xamarin.Android.Tasks.GetAndroidActivityName" AssemblyFile="Xamarin.Android.Build.Tasks.dll" /> | ||
| <UsingTask TaskName="Xamarin.Android.Tasks.GetPrimaryCpuAbi" AssemblyFile="Xamarin.Android.Build.Debugging.Tasks.dll" /> | ||
| <UsingTask TaskName="Xamarin.Android.Tasks.FastDeploy" AssemblyFile="Xamarin.Android.Build.Debugging.Tasks.dll" /> | ||
| <UsingTask TaskName="Microsoft.Android.Tasks.FastDeploy" AssemblyFile="$(_MicrosoftAndroidBuildTasksAssembly)" Runtime="NET" TaskFactory="TaskHostFactory" Condition=" '$(MSBuildRuntimeType)' == 'Full' " /> |
Move the `FastDeploy` task (all partial declarations and its
`FastDeployJsonSerializerContext`) from
`Xamarin.Android.Build.Debugging.Tasks.dll` (netstandard2.0) to
`Microsoft.Android.Build.Tasks.dll` (net12.0). The task keeps its
`Xamarin.Android.Tasks` namespace, so both `<FastDeploy/>` and
`<Xamarin.Android.Tasks.FastDeploy/>` continue to resolve.
* Register the task from `$(_MicrosoftAndroidBuildTasksAssembly)`
using the existing Full/Core pattern: `TaskHostFactory` +
`Runtime="NET"` on .NET Framework MSBuild, `Runtime="NET"` alone on
.NET MSBuild.
* Compile-link `AndroidHelper.cs` (still used by `GetPrimaryCpuAbi` and
`DetectIfAppWasUninstalled`) into MABT as `internal`, and link the
debugging `Resources.resx` files with their original manifest name so
XA#### messages stay localized.
* The manifest now uses the framework System.Text.Json; the
`System.Text.Json` PackageReference in DebuggingTasks had no other
consumer and is removed.
* Make the implicit current-culture formatting explicit to satisfy
CA1305, which MABT enforces; behavior is unchanged.
* Move the FastDeploy unit tests (and `FastDeployTypeMapTests`) to
`Microsoft.Android.Build.Tasks.Tests`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
a241ce3 to
72786e0
Compare
`AndroidHelper` caches the device selected by `GetPrimaryCpuAbi` with `RegisterTaskObjectAssemblyLocal`, whose key includes the Microsoft.Android.Build.BaseTasks path. FastDeploy now loads from `tools/net/` instead of `tools/`, so it missed that cache and ran an additional `adb devices -l` on every deploy. Also publish the selected serial (`""` for no device) under a framework-typed, non-assembly-local key, and read it only from the Microsoft.Android.Build.Tasks copy. FastDeploy only uses `AdbDeviceInfo.Serial`. `Microsoft.Android.Build.Tasks.csproj` did not define `MICROSOFT_ANDROID_BUILD_TASKS`, so the linked `AndroidHelper` was compiled as `public` there. Define it so the copy is `internal`. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the assembly-local device cache plus serial side-channel with a single cache whose values are framework types, so the copies of `AndroidHelper` in Xamarin.Android.Build.Debugging.Tasks.dll and Microsoft.Android.Build.Tasks.dll share every `AdbDeviceInfo` field (an empty array means no device was found), as they did when both tasks lived in one assembly. Keep `AndroidHelper` public in both copies and drop the `MICROSOFT_ANDROID_BUILD_TASKS` define. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move `FastDeploy` and `FastDeployJsonSerializerContext` into `Microsoft.Android.Tasks`, like the other tasks in Microsoft.Android.Build.Tasks.dll, and register the task as `Microsoft.Android.Tasks.FastDeploy`. `<FastDeploy/>` keeps resolving; the old qualified `<Xamarin.Android.Tasks.FastDeploy/>` name does not. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
`AppDetectionTests` imports `Xamarin.Android.Common.Debugging.targets` without `Microsoft.Android.Sdk.targets`, so FastDeploy's `<UsingTask/>` evaluated `$(_MicrosoftAndroidBuildTasksAssembly)` to an empty string (MSB4022) and `DeviceSelectionSurvivesDeviceOrderChanges` failed before the detector ran. Set the property alongside `_XamarinAndroidBuildTasksAssembly`. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
Code assessment: no blocking findings — 0 ❌ errors, 0
Reviewed all 16 changed files in full, the task callers, project references, resource naming/packaging, and the shared cache's producer/consumer paths. The task relocation preserves the deployment logic, the registrations match the existing modern-task hosting pattern, and the primitive cache representation avoids sharing assembly-specific AdbDeviceInfo identities. The existing FastDeploy tests move with the implementation, and the standalone-target fixture receives the new assembly property.
CI: GitHub reports all 40 head-commit checks successful, including the aggregate dotnet-android check for Azure build 1674826. Independent Azure build/timeline verification is incomplete: az devops invoke refused the read because authentication is required. No local build or tests were run in this review; the available dotnet reports SDK 10.0.403, while the moved task/test project targets net12.0. No confirmed regression was found by source inspection.
Generated by Android PR Reviewer for #13458 · copilot · gpt61 · 51.7 AIC · ⌖ 8.01 AIC · ⊞ 19.5K
Comment /review to run again
| { | ||
| string adbToolPath = Path.Combine (Path.GetTempPath (), "missing-" + Guid.NewGuid ().ToString ("N")); | ||
| IBuildEngine4 engine = new MockBuildEngine (TestContext.Out); | ||
| engine.RegisterTaskObject (DeviceCacheKey ("-s emulator-5554", Path.Combine (adbToolPath, "adb")), new object [] { |
There was a problem hiding this comment.
🤖 💡 Testing — Consider checking in the cross-task counting-fake-adb fixture described in the PR: let the actual GetPrimaryCpuAbi task populate the cache, then run FastDeploy through the shipped targets and assert that only one adb devices -l invocation occurred. This test hand-registers the expected payload and calls only the modern assembly's AndroidHelper, so it verifies cache consumption but cannot catch producer-side key/payload drift or assembly-loading differences between the two task assemblies. The manual smoke test is good evidence for this revision; preserving it as a regression test would protect the main reason for the shared-cache change.
{Rule: Test cross-assembly behavior at the consuming boundary}


Move the
FastDeploytask (all partials plusFastDeployJsonSerializerContext) fromXamarin.Android.Build.Debugging.Tasks.dll(netstandard2.0) toMicrosoft.Android.Build.Tasks.dll(net12.0), in theMicrosoft.Android.Tasksnamespace like the other tasks there. The task stays anAsyncTask, and its deployment behavior is unchanged.<FastDeploy/>keeps resolving; the fully qualified name is nowMicrosoft.Android.Tasks.FastDeploy(previouslyXamarin.Android.Tasks.FastDeploy).TaskHostFactory+Runtime="NET"on .NET Framework MSBuild, andRuntime="NET"on .NET MSBuild.AndroidHelper.cs(still used byGetPrimaryCpuAbi/DetectIfAppWasUninstalled) is compile-linked into MABT. The debuggingResources*.resxare linked with their original manifest name, so XA#### messages stay localized; the satellites ship through the existingtools/net/<lang>/Microsoft.Android.Build.Tasks.resources.dllentries. No new non-framework assemblies.PackageReferenceis removed.AndroidHelpercached devices withRegisterTaskObjectAssemblyLocalasAdbDeviceInfoinstances. The key includes the BaseTasks path (tools/vstools/net/), so FastDeploy would have missed the deviceGetPrimaryCpuAbialready selected and run an extraadb devices -l. The cache now stores everyAdbDeviceInfofield as framework types under a non-assembly-local key, so both copies ofAndroidHelpershare it as before. On .NET Framework MSBuild, FastDeploy runs in aTaskHostFactoryprocess and cannot share this in-process cache.FastDeployTypeMapTestsmove toMicrosoft.Android.Build.Tasks.Tests.AppDetectionTestsimports the debugging targets on their own, so its fixture now sets_MicrosoftAndroidBuildTasksAssemblynext to_XamarinAndroidBuildTasksAssembly.Not in scope:
[MSBuildMultiThreadableTask]support. Strict-mtbuilds run FastDeploy in a sidecar task host, as with other non-MT tasks.Testing (macOS arm64, local SDK)
dotnet test src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/Microsoft.Android.Build.Tasks.Tests.csproj --filter "FullyQualifiedName~FastDeployTests|FullyQualifiedName~FastDeployTypeMapTests": 65/65 passed. These are the 63 cases that previously ran inXamarin.Android.Build.Testsplus 2 new device-cache tests, which fail without the cache change.bin/Debug/dotnet/dotnet build Microsoft.Android.slnxplus-t:BuildExtraApiLevels: 0 errors. Packagedtools/net/Microsoft.Android.Build.Tasks.dllcontainsFastDeployand the debugging resources;Xamarin.Android.Build.Debugging.Tasks.dllno longer containsFastDeploy.adb, invoking both<FastDeploy/>and<Microsoft.Android.Tasks.FastDeploy/>through the shippedXamarin.Android.Common.Debugging.targets:./dotnet-local.sh msbuild … -m -nr:false: succeeded with 0 warnings/0 errors. The fakeadb's parent was the main MSBuild process, so FastDeploy ran in-process.… -m -mt -nr:false -warnaserror:MSB4286,MSB4287,MSB4288: succeeded with 0 warnings/0 errors, running in a task-host node../dotnet-local.sh test bin/TestDebug/net11.0/Xamarin.Android.Build.Tests.dll --filter "FullyQualifiedName~AppDetectionTests|FullyQualifiedName~DebuggingTasksTests|Name~AndroidEnableFastDeployment|Name~FastDeploymentDoesNotAddContentProvider": 53 passed, 1 skipped. That includes all 9AppDetectionTests(DeviceSelectionSurvivesDeviceOrderChangesfailed with MSB4022 in the previous CI run) and the 9 FastDeploy build/packaging tests, which are host-only and do not runFastDeploy.GetPrimaryCpuAbi→FastDeploy) against a counting fakeadb, 10 interleaved warm pairs comparingmainwith this PR. Per deploy, both make 1adb devices -lcall and 7 adb calls total, with 1 cache hit; every paired adb command log is identical.Not validated locally: .NET Framework (
MSBuildRuntimeType == 'Full') hosting, Windows, and on-device deployment (MSBuildDeviceIntegration). CI covers these.