Expose Android package output items#11674
Conversation
Add metadata-rich AndroidPackageOutput and AndroidPublishedPackageOutput item groups so custom MSBuild targets and CI can discover final APK/AAB outputs without recalculating file names. Wire the publish target to consume the package output items, cover publish/signing scenarios in tests, and document the new item metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR makes Android packaging outputs discoverable by introducing a stable @(AndroidPackageOutput) item group (and a GetAndroidPackageOutputs target) so custom targets and CI workflows can consume authoritative APK/AAB paths without reimplementing packaging logic.
Changes:
- Add
_CollectAndroidPackageOutputs+GetAndroidPackageOutputs, and wire collection into build/sign/package order so outputs are available after packaging/signing. - Update
dotnet publishflow to publish packages via@(AndroidPackageOutput)(instead of filename globs) and then rewrite the item group to point at$(PublishDir)copies. - Add test coverage and documentation for the new item group.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | Adds package-output collection target and public target returning @(AndroidPackageOutput) with metadata. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets | Schedules _CollectAndroidPackageOutputs after package/sign/universal APK creation and in related target dependency chains. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Publish.targets | Publishes using @(AndroidPackageOutput) and updates items to the final publish paths after copy. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs | Adds dotnet publish assertions ensuring package outputs flow into ResolvedFileToPublish and @(AndroidPackageOutput). |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs | Adds assertions that signed APK outputs (including per-ABI) appear in @(AndroidPackageOutput) with correct metadata. |
| Documentation/docs-mobile/building-apps/build-targets.md | Mentions @(AndroidPackageOutput) for SignAndroidPackage (needs a section for the new GetAndroidPackageOutputs target). |
| Documentation/docs-mobile/building-apps/build-items.md | Documents the new @(AndroidPackageOutput) item group and its metadata. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prove that GetApplicationArtifactsDependsOn targets observe Android-produced ApplicationArtifact items before adding MAUI-style metadata, including publish outputs and per-ABI APK artifacts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Route Android Publish through GetApplicationArtifacts so targets appended through GetApplicationArtifactsDependsOn can observe and augment ApplicationArtifact items before Publish calculates and returns them. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add command-line target-result examples for GetApplicationArtifacts and Publish so callers can discover returned ApplicationArtifact items from the documented target surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
State that GetApplicationArtifactsDependsOn extension targets run after platform ApplicationArtifact items are populated so later imports can update existing items with additional metadata. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep Build outside the user-extensible GetApplicationArtifactsDependsOn property so overriding the property cannot skip platform ApplicationArtifact population before metadata extension targets run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prefer dotnet build for ApplicationArtifact target-result examples instead of dotnet msbuild. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
macios equivalent: dotnet/macios#25723 |
Write ApplicationArtifact test output with item transforms so WriteLinesToFile receives the full item list in one invocation instead of batching per item. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep artifact creation behind a mandatory internal target that runs Build and then explicitly packages, signs, and collects application artifacts before public extension targets can enrich the items. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep GetApplicationArtifacts directly dependent on Build before extension targets run, avoiding an extra private artifact-production wrapper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The PackagingTest.CheckSignApk and XASdkTests.DotNetPublish additions injected ~80 lines of inline MSBuild XML plus file-based bookkeeping into existing matrix tests to validate the new `@(ApplicationArtifact)` behavior. That coupled the new feature to unrelated test surfaces and inflated test runtime across the `[Values]` matrix. Instead, parameterize `BuildTest.DotNetBuildReturnsApplicationArtifacts` to cover the same contract from one focused test that uses the JSON emitted by `-getTargetResult:` rather than `WriteLinesToFile`/read-back. Added cases: * `aab` package format - asserts 3 items (unsigned aab, signed aab, signed universal apk from the bundle). * Per-ABI apk with explicit RuntimeIdentifiers - asserts the per-ABI items carry `Abi` metadata. * Extension hook - validates the `_CreateApplicationArtifacts` -> `$(GetApplicationArtifactsDependsOn)` ordering contract by appending a target that runs `Update` to add `MauiArtifact=true`. If the order regresses, `Update` would have nothing to update and the metadata wouldn't appear on the returned items. Reverted all changes to PackagingTest.cs and XASdkTests.cs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…title/description
The Phase 4 prompt forced a rewrite of the PR title/description on every
review ("restate them cleaned-up") using a generic 1-sentence + bullets
template. On PRs that already have strong, detailed descriptions this
produced a STRICTLY WORSE result — e.g. it shortened
"Add MAUI ApplicationArtifact metadata for net11p6" to the vaguer
"Add MAUI metadata to application artifacts" and dropped the critical
"Platform dependencies" links (dotnet/android#11674, dotnet/macios).
Rework Phase 4 to apply the pr-finalize skill's core "Preserve Quality"
principle:
- Inject the PR's CURRENT title + description into the prompt so the agent
can evaluate-first (fetch body via gh pr view; truncate to 4k chars).
- Only recommend a rewrite when the current title/description is stale,
inaccurate, vague, or missing key info; otherwise emit a "keep as-is"
assessment and NO degraded replacement.
- When a change is warranted, require a STRICT IMPROVEMENT that preserves
dependency links, platform sections, specific type/term names and issue
refs, following the skill's "[Platform] Component: What changed" title
formula.
No change to post-ai-summary-comment.ps1 rendering; Pester 15/15 still pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ze evaluate-first `gh pr view` is unreliable in the CopilotReview phase after the squash-merge checkout (the previous fix's fresh gh fetch returned empty, so the prompt hit the "could not fetch" fallback and the agent rebuilt the description from the diff — dropping author-only context like external dependency links). Persist the PR title+body to pr-metadata.json during the Setup phase, where gh provably works and $prInfo is populated, then read it back in STEP 5b via the same cross-phase shared-dir mechanism the setup-complete sentinel uses. gh fetch / $prInfo / non-degrading text remain as ordered fallbacks. Now the evaluate-first prompt reliably sees the real current title and description, so it can correctly choose keep-as-is and preserve specifics (e.g. dotnet/android#11674 dependency links) instead of regenerating. Verified: parses cleanly; Setup→CopilotReview file round-trip preserves title + dep-links; Pester 15/15. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the unsupported per-ABI target-result case from DotNetBuildReturnsApplicationArtifacts. The callable-target coverage now matches the default-project scenarios requested in review while keeping APK, Publish, AAB, and extension metadata coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the ProjectBuilder AssertHasAtMostWarnings helper used by the packaging tests so the test project builds cleanly before running the application artifact coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-outputs # Conflicts: # src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs # src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/AssertionExtensions.cs
|
/review |
|
✅ Android PR Reviewer completed successfully! |
There was a problem hiding this comment.
🤖 Code Review — Expose Android package output items
Verdict:
Solid, well-scoped MSBuild change. The new @(ApplicationArtifact) item group and GetApplicationArtifacts / Publish return contract are clean, the metadata surface (PackageFormat, Signed, PackageId, Abi) is intentionally small, and the docs are thorough. I verified:
- ✅
PackageId="$(_AndroidPackage)"correctly maps to the resolved Android package name (ApplicationId), matching the docs. - ✅ The
aab;apkcase is handled:_AndroidAdditionalPackageFormats=apkproduces the signed universal APK at$(ApkFileSigned), which the unguardedExists('$(ApkFileSigned)')include captures (3 items for AAB — matches the test). - ✅
_CollectApplicationArtifactsis wired into all the build/sign/package dependency chains after signing runs.
Issues (2 inline)
⚠️ MSBuild targets —_UpdateApplicationArtifactsForPublishsilently drops any artifact not found in$(PublishDir)(Publish.targets).- 💡 Testing — Test comment references the wrong target name
_CreateApplicationArtifacts(BuildTest.cs).
Notes (not blocking)
- PR description vs. diff: The description lists added coverage in
XASdkTests.DotNetPublishandPackagingTest.CheckSignApk(Releaseaab;apk,@(ResolvedFileToPublish)flow, per-ABI signed APKs). Those files are not in this diff — onlyBuildTest.cswas changed. Please reconcile the description with the actual test coverage, or add the missing tests. The per-ABI (AndroidCreatePackagePerAbi=true) andaab;apkpublish paths in particular are currently exercised only indirectly. - CI has no completed statuses yet (pending) — verdict assumes the pipeline goes green.
Nice work on the documentation and the extension-hook ordering test.
Generated by Android PR Reviewer for #11674 · 140.5 AIC · ⌖ 13.1 AIC · ⊞ 6.8K
Comment /review to run again
- Drop the Exists() filter in _UpdateApplicationArtifactsForPublish so a missing copy in $(PublishDir) surfaces as a failure downstream instead of silently dropping the artifact from the returned item group. - Fix a stale target name in the DotNetBuildReturnsApplicationArtifacts extension-hook comment (_CreateApplicationArtifacts -> _CollectApplicationArtifacts). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5bbc94fa-010d-48af-9bfc-7b29ef7f2a43
Why this change is necessary
Android package outputs are difficult for custom targets, CI workflows, and higher-level workloads to discover reliably. Final APK and AAB paths are calculated by the Android build, while
dotnet publishpreviously rediscovered packages indirectly. Consumers therefore had to duplicate Android-specific naming and packaging logic.This change exposes the authoritative final package outputs through
@(ApplicationArtifact)and a callableGetApplicationArtifactstarget. The item name is intentionally platform-neutral so workloads such as MAUI and other .NET mobile platforms can enrich or populate the same contract.What changed
@(ApplicationArtifact)collection after Android package, signing, and universal APK generation.PackageFormat:apkoraabSigned: whether the package is signedPackageId: the resolved Android package nameAbi: the ABI for per-ABI APKsGetApplicationArtifacts, which builds the project and returns@(ApplicationArtifact).$(GetApplicationArtifactsDependsOn)as an extension point that runs after Android creates the items, allowing later imports such as MAUI to add metadata before eitherGetApplicationArtifactsorPublishreturns them.Publishto:@(ApplicationArtifact)as the source of package entries in@(ResolvedFileToPublish);$(PublishDir);@(ApplicationArtifact)with identities updated to the published paths while preserving metadata.DotNetCLIhelper to accept arbitrary MSBuild command-line arguments, including-getTargetResult.@(ApplicationArtifact),GetApplicationArtifacts, thePublishreturn contract, metadata, extension behavior, and command-line query examples.Tests
Added
BuildTest.DotNetBuildReturnsApplicationArtifactscoverage for:GetApplicationArtifacts.Publish.$(GetApplicationArtifactsDependsOn)extension that observes the Android-produced items and enriches their metadata before they are returned.The tests parse MSBuild
-getTargetResultJSON and validate artifact count, file name, package format, signed status, package ID, ABI, and extension-provided metadata.Issues fixed
N/A