Skip to content

Expose Android package output items#11674

Merged
jonathanpeppers merged 23 commits into
mainfrom
redth/android-publish-outputs
Jul 14, 2026
Merged

Expose Android package output items#11674
jonathanpeppers merged 23 commits into
mainfrom
redth/android-publish-outputs

Conversation

@Redth

@Redth Redth commented Jun 16, 2026

Copy link
Copy Markdown
Member

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 publish previously 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 callable GetApplicationArtifacts target. 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

  • Added @(ApplicationArtifact) collection after Android package, signing, and universal APK generation.
  • Included unsigned and signed APK/AAB outputs, per-ABI APKs, and universal APKs when produced.
  • Added Android-specific metadata:
    • PackageFormat: apk or aab
    • Signed: whether the package is signed
    • PackageId: the resolved Android package name
    • Abi: the ABI for per-ABI APKs
  • Added GetApplicationArtifacts, which builds the project and returns @(ApplicationArtifact).
  • Added $(GetApplicationArtifactsDependsOn) as an extension point that runs after Android creates the items, allowing later imports such as MAUI to add metadata before either GetApplicationArtifacts or Publish returns them.
  • Updated Publish to:
    • use @(ApplicationArtifact) as the source of package entries in @(ResolvedFileToPublish);
    • copy those packages to $(PublishDir);
    • return @(ApplicationArtifact) with identities updated to the published paths while preserving metadata.
  • Removed the publish-time existence filter so an expected artifact is not silently omitted from the returned item group if its publish copy is missing.
  • Extended the test DotNetCLI helper to accept arbitrary MSBuild command-line arguments, including -getTargetResult.
  • Documented @(ApplicationArtifact), GetApplicationArtifacts, the Publish return contract, metadata, extension behavior, and command-line query examples.

Tests

Added BuildTest.DotNetBuildReturnsApplicationArtifacts coverage for:

  • Debug APK results returned by GetApplicationArtifacts.
  • Debug APK publish paths returned by Publish.
  • Release AAB results, including unsigned/signed AABs and the signed universal APK.
  • A MAUI-style $(GetApplicationArtifactsDependsOn) extension that observes the Android-produced items and enriches their metadata before they are returned.

The tests parse MSBuild -getTargetResult JSON and validate artifact count, file name, package format, signed status, package ID, ABI, and extension-provided metadata.

Issues fixed

N/A

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>
Comment thread Documentation/docs-mobile/building-apps/build-items.md Outdated
Comment thread src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets Outdated
Comment thread src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets Outdated
Redth and others added 5 commits June 16, 2026 16:56
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>
@Redth Redth marked this pull request as ready for review June 16, 2026 21:28
@Redth Redth requested a review from simonrozsival as a code owner June 16, 2026 21:28
Copilot AI review requested due to automatic review settings June 16, 2026 21:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 publish flow 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.

Comment thread src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs Outdated
Comment thread Documentation/docs-mobile/building-apps/build-targets.md
Redth and others added 8 commits June 16, 2026 18:35
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>
@Redth

Redth commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

macios equivalent: dotnet/macios#25723

Redth and others added 2 commits June 17, 2026 14:28
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>
Comment thread src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Comment thread src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs Outdated
Redth and others added 3 commits June 17, 2026 15:59
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>
kubaflo pushed a commit to dotnet/maui that referenced this pull request Jun 19, 2026
…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>
kubaflo pushed a commit to dotnet/maui that referenced this pull request Jun 20, 2026
…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>
Comment thread src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs Outdated
Redth and others added 3 commits June 26, 2026 16:12
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
@jonathanpeppers

Copy link
Copy Markdown
Member

/review

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Code Review — Expose Android package output items

Verdict: ⚠️ Needs Changes (minor)

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;apk case is handled: _AndroidAdditionalPackageFormats=apk produces the signed universal APK at $(ApkFileSigned), which the unguarded Exists('$(ApkFileSigned)') include captures (3 items for AAB — matches the test).
  • _CollectApplicationArtifacts is wired into all the build/sign/package dependency chains after signing runs.

Issues (2 inline)

  1. ⚠️ MSBuild targets_UpdateApplicationArtifactsForPublish silently drops any artifact not found in $(PublishDir) (Publish.targets).
  2. 💡 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.DotNetPublish and PackagingTest.CheckSignApk (Release aab;apk, @(ResolvedFileToPublish) flow, per-ABI signed APKs). Those files are not in this diff — only BuildTest.cs was changed. Please reconcile the description with the actual test coverage, or add the missing tests. The per-ABI (AndroidCreatePackagePerAbi=true) and aab;apk publish 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

Comment thread src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs Outdated
- 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
@jonathanpeppers jonathanpeppers merged commit 9115378 into main Jul 14, 2026
42 checks passed
@jonathanpeppers jonathanpeppers deleted the redth/android-publish-outputs branch July 14, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants