Skip to content

Fix font/splash assets missing on first build and when incremental outputs are deleted - #33919

Merged
kubaflo merged 20 commits into
inflight/currentfrom
fix/issue-23268-font-assets-first-build
Jul 17, 2026
Merged

Fix font/splash assets missing on first build and when incremental outputs are deleted#33919
kubaflo merged 20 commits into
inflight/currentfrom
fix/issue-23268-font-assets-first-build

Conversation

@PureWeen

@PureWeen PureWeen commented Feb 5, 2026

Copy link
Copy Markdown
Member

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

The Resizetizer copies and registers MauiFont / MauiSplashScreen assets during the build. Two incremental-build gaps could leave an app packaged without its fonts or splash screen:

  1. First build (Android/Tizen) — item registration (AndroidAsset, BundleResource, …) lived inside the incremental ProcessMauiFonts target. On a clean build the target's output-inference glob was empty, so the platform items were never registered and fonts were missing until a second build. The fix splits registration into an always-run _CollectMauiFontItems target that maps font paths predictively from @(MauiFont).

  2. Incremental build (all platforms)ProcessMauiFonts / ProcessMauiSplashScreens tracked freshness with mauifont.stamp / mauisplash.stamp files. A stamp could stay newer than a generated output that was later deleted (partial obj clean or concurrent build), so MSBuild skipped the target and the package shipped without the missing font/splash. The fix replaces stamps with mauifont.outputs / mauisplash.outputs manifests. _ReadMauiFontOutputs / _ReadMauiSplashOutputs run before freshness evaluation, delete the manifest when a listed generated output is missing, and each processor uses the manifest as its sole Outputs. This makes only the affected processor rerun without re-stamping unchanged generated assets and unnecessarily invalidating downstream consumers such as Android aapt2.

This PR consolidates #35962 (closed): it drops the font/splash stamps, adds ProcessMauiSplashScreensDependsOnTargets, and de-duplicates fonts by intermediate filename before CreatePartialInfoPlistTask, so colliding names (for example an app and a ProjectReference both shipping OpenSans.ttf) do not emit duplicate UIAppFonts entries.

The related runtime-side symptom (noisy missing-font fallback logging) is intentionally out of scope here and handled separately in #35963.

Issues Fixed

Fixes #23268
Fixes #33092

Tests

  • ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild — clean Release build of the maui template asserts the font lands in the Android assets folder on the first build, then an incremental build confirms ProcessMauiFonts is skipped while the always-run _CollectMauiFontItems still registers the asset.
  • ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing (macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes only the generated iOS/MacCatalyst MauiInfo.plist files and verifies both font processors rerun and restore them, then deletes generated font/splash folders, verifies recovery, and finally verifies a no-op build skips both processors.

Validation

  • A focused MSBuild sequence verified initial generation, no-op skipping, regeneration after deleting a recorded output, and a subsequent no-op skip using the same manifest-invalidation protocol.
  • The full integration workflow could not complete locally because Android workload installation exhausted the shared disk; the updated Build integration test will validate on CI.

Copilot AI review requested due to automatic review settings February 5, 2026 23:02

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 pull request fixes a race condition in Android and Tizen builds where font assets were not copied on the first build. The issue occurred because ProcessMauiFonts used AfterTargets with ResizetizeCollectItems, which is a weak scheduling hint that can be skipped during parallel/concurrent MSBuild processes.

Changes:

  • Replaced ProcessMauiFontsAfterTargets with ProcessMauiFontsBeforeTargets for Android, using _ComputeAndroidResourcePaths as the hard dependency
  • Replaced ProcessMauiFontsAfterTargets with ProcessMauiFontsBeforeTargets for Tizen, using PrepareResources as the hard dependency
  • Added detailed comments explaining the rationale for using BeforeTargets to create hard dependencies

@PureWeen

PureWeen commented Feb 6, 2026

Copy link
Copy Markdown
Member Author

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 2 pipeline(s).

@PureWeen

PureWeen commented Feb 7, 2026

Copy link
Copy Markdown
Member Author

/rebase

For Android and Tizen, ProcessMauiFonts used AfterTargets (a weak
scheduling hint) which could be skipped during concurrent builds
(e.g. VS design-time build racing with regular build). Changed to
BeforeTargets to create a hard dependency, matching the pattern
already used by iOS, Windows, and WPF platforms.

Fixes #23268
The ProcessMauiFonts target has Inputs/Outputs incremental checks, which
means its entire body is skipped when the stamp file is up-to-date. This
includes the platform-specific item registrations (AndroidAsset,
BundleResource, etc.), causing fonts to be missing from the app when the
target is skipped during concurrent or cached builds (e.g., VS design-time
builds running alongside regular builds).

Fix: Extract all platform item registrations into a new
_CollectMauiFontItems target that has no Inputs/Outputs, ensuring items
are always registered regardless of incremental build state. The new target
uses DependsOnTargets=ProcessMauiFonts to ensure font files are copied
first, and uses predictive path mapping from @(MauiFont) instead of
wildcard globbing to avoid collecting stale intermediate files.

This follows the same pattern used by ResizetizeImages in the same file.

Fixes #23268
…ifestsDependsOn

The iOS scheduling uses CollectAppManifestsDependsOn to pull in ProcessMauiFonts.
With the split target, this must reference _CollectMauiFontItems instead, which
transitively depends on ProcessMauiFonts via DependsOnTargets.
MSBuild output inference evaluates ItemGroups even in skipped targets.
The real danger is wildcard globs that depend on task side-effects.
Corrections verified by 6 agents (Sonnet 4.5, Gemini 3 Pro, Codex 5.2,
Opus 4.5, GPT-5.1, Sonnet 4):

1. iOS scheduling table: ResizetizeCollectItems uses
   CollectBundleResourcesDependsOn/CompileImageAssetsDependsOn.
   ResizetizeImages uses AfterTargets=ResizetizeCollectItems.
   ProcessMauiFonts now via _CollectMauiFontItems.

2. mauimanifest.stamp has no companion .inputs file.

3. Split platform items into separate font/image tables with
   correct metadata (Android images use StampFile, not Link).
@github-actions
github-actions Bot force-pushed the fix/issue-23268-font-assets-first-build branch from d6287cf to fb01628 Compare February 7, 2026 21:12
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 23, 2026
@dotnet dotnet deleted a comment from MauiBot Mar 24, 2026
@kubaflo kubaflo removed s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Mar 24, 2026
@kubaflo

kubaflo commented May 24, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml

MauiBot

This comment was marked as outdated.

@PureWeen PureWeen left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Adversarial review

No actionable findings on the current head.

  • Consensus: 3 independent reviewers with adversarial consensus + MAUI domain specialist
  • What was verified: manifest invalidation before incremental freshness checks, first-build font registration, no-op behavior, deleted font/splash/plist recovery, platform scheduling, and FileWrites cleanup
  • Coverage: the changed paths include focused first-build and missing-intermediate-output integration coverage
  • Prior feedback: all review threads are resolved; no new actionable discussion was found

The manifest-only output model correctly avoids re-stamping generated assets while preserving recovery when a recorded output is removed.

@kubaflo kubaflo 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.

🔍 AI-generated review (multi-model: Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro), on behalf of @kubaflo.

✅ LGTM — 3-model consensus; my prior REQUEST_CHANGES regression is verified resolved

This lifts my earlier REQUEST_CHANGES (the e7ca7fcf "stop over-touching" commit had regressed this PR's own Resizetizer tests — ProcessMauiFonts should have been skipped (up-to-date) failing ×2 on macOS+Windows). The 569d2a0e "preserve manifest-based incremental recovery" commit fixes it, confirmed two independent ways:

1. Code reasoning (unanimous across Opus 4.8 · GPT-5.5 · Gemini 3.1 Pro):

  • The missing-output recovery is correctly ordered — the manifest <Delete> lives in the separate _ReadMauiFontOutputs / _ReadMauiSplashOutputs targets pulled via DependsOnTargets, which MSBuild always runs before the parent's incremental up-to-date check. It is a genuine pre-check, not dead code inside the skippable body.
  • Dropping @(_Maui*Outputs) from Outputs (leaving only the always-Touch-stamped manifest) eliminates the stale-timestamp false-run, while the manifest-delete-on-!Exists restores the deleted-output recovery. No false-skip survives: the manifest is re-stamped every execution so its mtime tracks the newest input, and real inputs remain covered by the Inputs lists.
  • The GetTargetStatus helper rewrite is provably correct across multi-TFM / multi-edge builds — it counts only TargetSkipReason.OutputsUpToDate and ignores the PreviouslyBuiltSuccessfully skips emitted for extra request edges (started > 0 && started == upToDateSkips). This is exactly the semantics my prior finding required.

2. Empirical CI (verified, not inferred): at head 569d2a0e, AzDO build 1503832 — both integration legs report Microsoft.Maui.IntegrationTests.dll Passed! Failed: 0, Passed: 69, Total: 69 on macOS (log 956) and windows (log 965). The previously-failing FontsAreCopiedToAndroidAssetsOnFirstBuild and BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing are green. All 30 checks pass.

Non-blocking suggestions (3, all suggestion-severity — no changes required to merge)

  • Recovery scope is "missing", not "stale-content" (After.targets ~L710): manifest-delete keys on !Exists(...), so an in-place corrupted output (manifest still present + newer than inputs) won't re-trigger. This is an intentional tradeoff that mirrors the legacy ResizetizeImages stamp and fully restores the deleted-output detection — flagging only to confirm "missing" is the intended scope.
  • Delete-recovery is CI-validated on the macOS leg only (ResizetizerTests.cs ~L168): the recovery sub-cases are gated to macOS. The _Read*Outputs logic is platform-agnostic MSBuild so this is sufficient for correctness; a lightweight Android-lane delete-recovery assertion would harden against platform-specific scheduling regressions.
  • Cosmetic (ResizetizerTests.cs ~L380): the if (!TestEnvironment.IsWindows) if (true) return; idiom is a correct-but-unconventional Windows gate that leaves redundant later IsWindows checks; worth a future tidy. (The AdditionalProperties propagation + this idiom largely landed via #35575, outside this delta.)

Verdict: LGTM (0 error / 0 warning / 3 suggestion across all three models). The regression that prompted my REQUEST_CHANGES is resolved. Great fix — the manifest-delete pre-check is the right pattern here.

@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jul 12, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

@PureWeen — new AI review results are available based on this last commit: 569d2a0. To request a fresh review after new comments or commits, comment /review rerun.

Gate No Tests Confidence Low Platform Android Primary


🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix

Gate Result: ⚠️ SKIPPED

No tests were detected in this PR.

Recommendation: Add tests to verify the fix using the write-tests-agent.


📋 Pre-Flight — Context & Validation

Issue: #23268 - Copy font assets only works at second build; #33092 - Compilation randomly missing custom fonts & splashScreen
PR: #33919 - Fix font/splash assets missing on first build and when incremental outputs are deleted
Platforms Affected: Android primary; shared Resizetizer font/splash build targets also affect iOS/MacCatalyst, Windows App SDK, WPF, and Tizen.
Files Changed: 1 implementation, 1 test, 1 instruction/documentation

Key Findings

  • #23268 reports Android Release builds missing Resources\Fonts assets after deleting bin/obj and doing a clean first build; a second build stages the .ttf files into obj/.../assets.
  • #33092 reports intermittent missing custom fonts and Android splash screen output after incremental/rebuild scenarios where generated Resizetizer outputs can be absent while old stamp files remain newer.
  • PR #33919 replaces bare font/splash stamp freshness with mauifont.outputs / mauisplash.outputs manifests and pre-read targets that delete a manifest when a recorded output is missing.
  • The PR keeps ProcessMauiFonts incremental but moves platform font registration into always-run _CollectMauiFontItems; current head also de-duplicates flattened font paths and deletes stale iOS/MacCatalyst MauiInfo.plist when the last font is removed.
  • Tests were added in src/TestUtils/src/Microsoft.Maui.IntegrationTests/ResizetizerTests.cs, though the provided gate result for this run was skipped and must not be re-run.
  • Impacted UI test categories: NONE. This is build/package-time Resizetizer target logic, not runtime UI behavior.

Code Review Summary

Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 0 | Suggestions: 1

Key code review findings:

  • 💡 Optional broader recovery coverage: the deleted-output recovery test is macOS-gated because it builds Apple TFMs; an Android-only deleted-output test could further harden platform-specific scheduling, but this is not a blocking issue.
  • Blast radius: shared MSBuild infrastructure for font/splash processing and platform item registration across Android, iOS/MacCatalyst, Windows, WPF, and Tizen.
  • Failure modes probed: first clean Android Release build, second/no-op build, deleted generated outputs, duplicate flattened font names, and removing all fonts.
  • CI caveat: authenticated gh pr checks --required was unavailable in this environment; public check-run fallback was reported green for relevant lanes by the expert reviewer, but required-check membership could not be verified.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33919 Manifest-based font/splash freshness plus always-run font item registration with predictive, de-duplicated intermediate font paths. ⚠️ SKIPPED (Gate: no tests detected in prior step) Microsoft.Maui.Resizetizer.After.targets, ResizetizerTests.cs, Resizetizer instructions Original PR

🔬 Code Review — Deep Analysis

Code Review — PR #33919

Independent Assessment

What this changes:
PR #33919 changes Resizetizer font/splash MSBuild behavior:

  • Replaces font/splash stamp files with mauifont.outputs / mauisplash.outputs manifests.
  • Adds _ReadMauiFontOutputs / _ReadMauiSplashOutputs pre-check targets that delete the manifest when a previously generated output is missing.
  • Splits font platform-item registration into always-run _CollectMauiFontItems.
  • Uses predictive font path mapping plus RemoveDuplicates before platform registration and iOS plist generation.
  • Adds integration tests for Android first-build font asset packaging and deleted-output recovery.

Inferred motivation:
Fix missing MAUI fonts/splash assets when incremental MSBuild skips processing targets even though platform packaging still needs asset items or generated outputs were deleted.

Approach assessment:
The final head implementation is sound. The manifest-only Outputs model avoids re-touching generated font/splash assets on no-op builds while still detecting missing recorded outputs before MSBuild freshness evaluation.

Reconciliation with PR Narrative

The PR description matches the code:

  • #23268: Android Release first-build missing fonts is addressed by always-run _CollectMauiFontItems.
  • #33092: missing/deleted generated font/splash outputs are addressed by output manifests and pre-check deletion.
  • The later de-duplication and stale MauiInfo.plist handling are present in the current diff.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Incremental tests regressed after generated outputs stopped being touched while also listed in Outputs. kubaflo review, 2026-07-08 ✅ Fixed Current head uses manifest-only outputs at Microsoft.Maui.Resizetizer.After.targets:407 and :547.
Duplicate flattened font paths could register duplicate platform assets. MauiBot / kubaflo earlier comments ✅ Fixed _MauiFontOutputUnique and _MauiFontCopiedUnique use RemoveDuplicates before plist/platform registration.
Stale iOS/MacCatalyst MauiInfo.plist could remain after removing all fonts. kubaflo earlier comment ✅ Fixed ProcessMauiFonts deletes MauiInfo.plist when @(MauiFont) is empty.

No unresolved prior ❌ Error findings found on the current head.

Blast Radius

  • Runs for all instances: Yes — Resizetizer targets affect MAUI app builds using fonts/splash assets across Android, iOS/MacCatalyst, Windows, WPF, and Tizen.
  • Startup impact: No runtime startup impact; build/package-time only.
  • Static/shared state: None.
  • Cross-platform side effects: Medium risk because shared MSBuild target behavior affects multiple platform packaging pipelines, but the change is scoped and tested in the relevant Resizetizer integration area.

CI Status

  • gh pr checks --required could not run because GitHub CLI authentication is unavailable.
  • Public check-run fallback was reported green for the relevant maui-pr, Build Analysis, integration build, Android, iOS, Windows, pack, and Helix legs by the expert reviewer.
  • Required-check membership could not be independently verified without authenticated gh, so CI confidence is partially capped.

Findings

❌ Error

None.

⚠️ Warning

None.

💡 Suggestion — Optional broader recovery coverage

ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing is macOS-gated, which is reasonable for Apple TFMs and currently covers Android+iOS/MacCatalyst from that lane. If this area regresses again, a lighter Android-only deleted-output recovery test could further harden platform-specific scheduling, but I would not block this PR on it.

Failure-Mode Probing

  • First clean Android Release build: _CollectMauiFontItems runs independently of ProcessMauiFonts incremental execution and registers AndroidAsset items from predicted intermediate font paths.
  • Second/no-op build: ProcessMauiFonts can skip via manifest-only Outputs; _CollectMauiFontItems still runs to re-register packaging items.
  • Deleted generated font/splash output: _ReadMauiFontOutputs / _ReadMauiSplashOutputs read the previous manifest before freshness evaluation and delete it if a recorded file is missing, forcing regeneration.
  • Duplicate same-name fonts from app + project reference: Flattened intermediate paths are de-duplicated before plist generation and platform registration.
  • Removing all fonts: The iOS/MacCatalyst partial MauiInfo.plist is explicitly deleted, preventing stale UIAppFonts registration.

Verdict: NEEDS_DISCUSSION

Confidence: low

Summary: Code review found no actionable correctness issues. I’m not marking this as full LGTM only because authenticated required-check status was unavailable, so required CI membership could not be verified directly.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 maui-expert-reviewer Real generated font files as Outputs, co-located font/splash stamps, Android BeforeTargets; no manifests or split collection target. ❌ Environment-blocked 1 file Focused integration test could not validate Android build because Linux restore required unavailable Microsoft.iOS.Sdk.net10.0_26.0; also weaker for partial splash deletion than PR.
2 maui-expert-reviewer Android source-file AndroidAsset registration plus stamp invalidation health checks; no output manifests. ❌ Environment-blocked; XML valid 1 file Android-biased and less complete cross-platform; same environment blocker.
3 maui-expert-reviewer Deterministic font path transform inside single ProcessMauiFonts target plus Android BeforeTargets; no manifests. ❌ Environment-blocked; XML valid 1 file Smallest first-build fix, but does not cover deleted-output recovery for #33092.
PR PR #33919 Manifest-based font/splash freshness, _ReadMaui*Outputs invalidation, and always-run predictive/de-duplicated font item registration. ⚠️ Gate skipped (provided prior result); expert review found no code errors 1 implementation + tests + instructions Original PR remains most complete among explored approaches.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes try-fix-1: real generated files as MSBuild Outputs plus co-located stamps.
maui-expert-reviewer 1 Yes try-fix-2: Android source-asset registration plus stamp health-check invalidation.
maui-expert-reviewer 2 Yes try-fix-3: deterministic font item transform inside the single font target.
maui-expert-reviewer 2 No further stronger ideas Remaining variants are trivial combinations of the above or regress #33092 coverage versus the PR.

Exhausted: Yes
Selected Fix: PR #33919 — It is the only explored approach that addresses both linked issues (#23268 first-build Android font registration and #33092 deleted font/splash output recovery) with per-output manifests, duplicate flattened-font handling, stale plist cleanup, and added integration tests. None of the alternative candidates was demonstrably better; all focused test runs were blocked by the Linux environment missing Microsoft.iOS.Sdk.net10.0_26.0, and static analysis shows each alternative is less robust than the PR for at least one required failure mode.


🏁 Report — Final Recommendation

Comparative Report — PR #33919

Candidate ranking

Rank Candidate Regression test result Assessment
1 pr Gate skipped; added integration tests present in diff Best overall. Addresses both #23268 first-build font registration and #33092 deleted font/splash output recovery with manifest invalidation, split always-run font item collection, duplicate flattened-font handling, stale plist cleanup, tests, and Resizetizer guidance.
2 pr-plus-reviewer Same as pr Equivalent to pr. The expert reviewer found no actionable feedback, so this candidate has no delta over the raw PR fix and does not improve on it.
3 try-fix-2 Environment-blocked / inconclusive; XML valid Solves the Android first-build path by registering Android fonts from source and adds stamp health checks, but is Android-biased and less precise cross-platform than manifest-based per-output invalidation.
4 try-fix-1 Environment-blocked / inconclusive Uses real font outputs plus co-located stamps, but can still miss partial splash deletion cases and keeps item registration inside the processing target rather than using the safer split-target pattern.
5 try-fix-3 Environment-blocked / inconclusive; XML valid Smallest first-build fix family, but it retains stamp-based font/splash freshness and does not address #33092 deleted-output recovery.

No STEP 5a candidate had a demonstrated regression-test failure; all try-fix candidates were blocked by the local Linux workload environment before the focused Android integration test could validate behavior. Per the ranking rule, any candidate with a failed regression test would rank below passing candidates, but the available evidence here is inconclusive rather than failing.

Comparison notes

pr is the only candidate that covers the full problem space described by the issues and pre-flight analysis. It separates processing from always-run registration, uses output manifests instead of bare stamps for fonts and splash screens, and avoids unnecessary downstream invalidation by touching only the manifest when outputs are unchanged.

pr-plus-reviewer remains useful as a named candidate for the evaluation pipeline, but because the expert reviewer reported no actionable findings and inline-findings.json is empty, it is functionally identical to pr.

The try-fix candidates each explore narrower alternatives. try-fix-2 is the strongest alternative for Android-first-build behavior, but it bypasses intermediate copied fonts only on Android and depends on manually enumerated sentinel outputs for stamp invalidation. try-fix-1 and try-fix-3 are weaker because they either retain stamp gaps or do not comprehensively cover splash/font deletion recovery.

Winner

Winner: pr

The raw PR fix wins because it is complete, cross-platform, and already incorporates the relevant robustness improvements. The expert reviewer found no changes to apply, and every try-fix candidate is either less complete or environment-blocked without evidence of superiority.


🧭 Next Steps — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@kubaflo

kubaflo commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

@kubaflo

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Tests Failure Analysis

@PureWeen — test-failure review results are available based on commit 569d2a0.
To request a fresh review after new comments, commits, or CI runs, comment /review tests.

Overall Not ready Failures 15 Regressed vs base 5 Baseline 2 on base

Test Failure Review: Not ready - click to expand

Overall verdict: Not ready. Against main (5 recent base builds sampled per definition, though only the single most-recent maui-pr base build was green), 5 legs are red on the PR but green on every sampled base build — a deterministic regression vs base that forbids a green verdict. Only 2 of 15 distinct failures also appear on base, and both are flaky-on-base (indeterminate), not clean dismissals; the remaining 10 could not be attributed deterministically and need a human.

  • ✗ PR-related — regressed-vs-base failures (~5 legs): red on the PR and green on all 5 sampled base builds; the strongest signal is a NullReferenceException in DatePickerOpenedAndClosedEventsAreRaised, alongside build-pipeline breaks (Publish Logs, PublishTestResults, install Gradle init script, Install Simulator Runtimes) that may cascade from a canceled iOS integration leg.
  • i Uncertain — unexplained/aborted build legs + flaky-on-base tests (~10 failures + 16 legs): includes 16 failed build legs with no extractable failure, 2 aborted/canceled checks (maui-pr RunOniOS_BlazorDebug ARM64, maui-pr-uitests macOS CollectionView), Android provisioning flakes (to find package 'platform-tools;35.0.2'), and flaky UI tests such as BorderRoundRectangleWithImage — none provably PR-caused nor dismissible.

Coverage: 162 checks · 151 passing · 11 failing · 0 pending · 0 inaccessible · 1 unmapped · 16 unexplained build legs · 0 unaccounted failing checks · 2 aborted failing checks · 0 canceled-build checks · 0 device-test unverified · 10 unattributed · 5 regressed-vs-base. Deterministic ceiling: Not ready — 5 legs are red on the PR but green on the sampled base builds (deterministic regression), plus 16 unexplained build legs, 2 aborted checks, and 10 unattributed failures.

Builds (this PR): maui-pr 1512392, maui-pr-uitests 1512393, maui-pr-devicetests 1512394 (green). Base sampling (main, 5 recent builds per definition): 1503430, 1503135, 1503618.

Recommended action

A human should inspect the 5 regressed-vs-base legs — especially the DatePickerOpenedAndClosedEventsAreRaised NullReferenceException — to confirm whether they stem from this PR's asset-handling changes or from the canceled iOS integration leg, before merging.

@kubaflo

kubaflo commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@AlleSchonWeg can you please check if this fixes your problem?

@AlleSchonWeg

Copy link
Copy Markdown
Contributor

@AlleSchonWeg can you please check if this fixes your problem?

It looks good. But the issue appears randomly. So it's difficult to be 100% sure.

@kubaflo
kubaflo changed the base branch from main to inflight/current July 17, 2026 14:26
@kubaflo
kubaflo merged commit 57318ba into inflight/current Jul 17, 2026
152 of 163 checks passed
@kubaflo
kubaflo deleted the fix/issue-23268-font-assets-first-build branch July 17, 2026 14:26
@github-actions github-actions Bot added this to the .NET 10 SR10 milestone Jul 17, 2026
kubaflo added a commit that referenced this pull request Jul 22, 2026
…tputs are deleted (#33919)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

The Resizetizer copies and registers `MauiFont` / `MauiSplashScreen`
assets during the build. Two incremental-build gaps could leave an app
packaged **without** its fonts or splash screen:

1. **First build (Android/Tizen)** — item *registration*
(`AndroidAsset`, `BundleResource`, …) lived **inside** the incremental
`ProcessMauiFonts` target. On a clean build the target's
output-inference glob was empty, so the platform items were never
registered and fonts were missing until a *second* build. The fix splits
registration into an always-run `_CollectMauiFontItems` target that maps
font paths predictively from `@(MauiFont)`.

2. **Incremental build (all platforms)** — `ProcessMauiFonts` /
`ProcessMauiSplashScreens` tracked freshness with `mauifont.stamp` /
`mauisplash.stamp` files. A stamp could stay newer than a generated
output that was later deleted (partial `obj` clean or concurrent build),
so MSBuild skipped the target and the package shipped without the
missing font/splash. The fix replaces stamps with `mauifont.outputs` /
`mauisplash.outputs` manifests. `_ReadMauiFontOutputs` /
`_ReadMauiSplashOutputs` run before freshness evaluation, delete the
manifest when a listed generated output is missing, and each processor
uses the manifest as its sole `Outputs`. This makes only the affected
processor rerun without re-stamping unchanged generated assets and
unnecessarily invalidating downstream consumers such as Android aapt2.

This PR **consolidates** #35962 (closed): it drops the font/splash
stamps, adds `ProcessMauiSplashScreensDependsOnTargets`, and
de-duplicates fonts by intermediate filename before
`CreatePartialInfoPlistTask`, so colliding names (for example an app and
a `ProjectReference` both shipping `OpenSans.ttf`) do not emit duplicate
`UIAppFonts` entries.

The related runtime-side symptom (noisy missing-font fallback logging)
is intentionally out of scope here and handled separately in #35963.

### Issues Fixed

Fixes #23268
Fixes #33092

### Tests

- `ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild` — clean
Release build of the `maui` template asserts the font lands in the
Android `assets` folder on the **first** build, then an incremental
build confirms `ProcessMauiFonts` is skipped while the always-run
`_CollectMauiFontItems` still registers the asset.
-
`ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing`
(macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes
only the generated iOS/MacCatalyst `MauiInfo.plist` files and verifies
both font processors rerun and restore them, then deletes generated
font/splash folders, verifies recovery, and finally verifies a no-op
build skips both processors.

### Validation

- A focused MSBuild sequence verified initial generation, no-op
skipping, regeneration after deleting a recorded output, and a
subsequent no-op skip using the same manifest-invalidation protocol.
- The full integration workflow could not complete locally because
Android workload installation exhausted the shared disk; the updated
Build integration test will validate on CI.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Gerald Versluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 28, 2026
…tputs are deleted (#33919)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

The Resizetizer copies and registers `MauiFont` / `MauiSplashScreen`
assets during the build. Two incremental-build gaps could leave an app
packaged **without** its fonts or splash screen:

1. **First build (Android/Tizen)** — item *registration*
(`AndroidAsset`, `BundleResource`, …) lived **inside** the incremental
`ProcessMauiFonts` target. On a clean build the target's
output-inference glob was empty, so the platform items were never
registered and fonts were missing until a *second* build. The fix splits
registration into an always-run `_CollectMauiFontItems` target that maps
font paths predictively from `@(MauiFont)`.

2. **Incremental build (all platforms)** — `ProcessMauiFonts` /
`ProcessMauiSplashScreens` tracked freshness with `mauifont.stamp` /
`mauisplash.stamp` files. A stamp could stay newer than a generated
output that was later deleted (partial `obj` clean or concurrent build),
so MSBuild skipped the target and the package shipped without the
missing font/splash. The fix replaces stamps with `mauifont.outputs` /
`mauisplash.outputs` manifests. `_ReadMauiFontOutputs` /
`_ReadMauiSplashOutputs` run before freshness evaluation, delete the
manifest when a listed generated output is missing, and each processor
uses the manifest as its sole `Outputs`. This makes only the affected
processor rerun without re-stamping unchanged generated assets and
unnecessarily invalidating downstream consumers such as Android aapt2.

This PR **consolidates** #35962 (closed): it drops the font/splash
stamps, adds `ProcessMauiSplashScreensDependsOnTargets`, and
de-duplicates fonts by intermediate filename before
`CreatePartialInfoPlistTask`, so colliding names (for example an app and
a `ProjectReference` both shipping `OpenSans.ttf`) do not emit duplicate
`UIAppFonts` entries.

The related runtime-side symptom (noisy missing-font fallback logging)
is intentionally out of scope here and handled separately in #35963.

### Issues Fixed

Fixes #23268
Fixes #33092

### Tests

- `ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild` — clean
Release build of the `maui` template asserts the font lands in the
Android `assets` folder on the **first** build, then an incremental
build confirms `ProcessMauiFonts` is skipped while the always-run
`_CollectMauiFontItems` still registers the asset.
-
`ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing`
(macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes
only the generated iOS/MacCatalyst `MauiInfo.plist` files and verifies
both font processors rerun and restore them, then deletes generated
font/splash folders, verifies recovery, and finally verifies a no-op
build skips both processors.

### Validation

- A focused MSBuild sequence verified initial generation, no-op
skipping, regeneration after deleting a recorded output, and a
subsequent no-op skip using the same manifest-invalidation protocol.
- The full integration workflow could not complete locally because
Android workload installation exhausted the shared disk; the updated
Build integration test will validate on CI.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Gerald Versluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 29, 2026
…tputs are deleted (#33919)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

The Resizetizer copies and registers `MauiFont` / `MauiSplashScreen`
assets during the build. Two incremental-build gaps could leave an app
packaged **without** its fonts or splash screen:

1. **First build (Android/Tizen)** — item *registration*
(`AndroidAsset`, `BundleResource`, …) lived **inside** the incremental
`ProcessMauiFonts` target. On a clean build the target's
output-inference glob was empty, so the platform items were never
registered and fonts were missing until a *second* build. The fix splits
registration into an always-run `_CollectMauiFontItems` target that maps
font paths predictively from `@(MauiFont)`.

2. **Incremental build (all platforms)** — `ProcessMauiFonts` /
`ProcessMauiSplashScreens` tracked freshness with `mauifont.stamp` /
`mauisplash.stamp` files. A stamp could stay newer than a generated
output that was later deleted (partial `obj` clean or concurrent build),
so MSBuild skipped the target and the package shipped without the
missing font/splash. The fix replaces stamps with `mauifont.outputs` /
`mauisplash.outputs` manifests. `_ReadMauiFontOutputs` /
`_ReadMauiSplashOutputs` run before freshness evaluation, delete the
manifest when a listed generated output is missing, and each processor
uses the manifest as its sole `Outputs`. This makes only the affected
processor rerun without re-stamping unchanged generated assets and
unnecessarily invalidating downstream consumers such as Android aapt2.

This PR **consolidates** #35962 (closed): it drops the font/splash
stamps, adds `ProcessMauiSplashScreensDependsOnTargets`, and
de-duplicates fonts by intermediate filename before
`CreatePartialInfoPlistTask`, so colliding names (for example an app and
a `ProjectReference` both shipping `OpenSans.ttf`) do not emit duplicate
`UIAppFonts` entries.

The related runtime-side symptom (noisy missing-font fallback logging)
is intentionally out of scope here and handled separately in #35963.

### Issues Fixed

Fixes #23268
Fixes #33092

### Tests

- `ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild` — clean
Release build of the `maui` template asserts the font lands in the
Android `assets` folder on the **first** build, then an incremental
build confirms `ProcessMauiFonts` is skipped while the always-run
`_CollectMauiFontItems` still registers the asset.
-
`ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing`
(macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes
only the generated iOS/MacCatalyst `MauiInfo.plist` files and verifies
both font processors rerun and restore them, then deletes generated
font/splash folders, verifies recovery, and finally verifies a no-op
build skips both processors.

### Validation

- A focused MSBuild sequence verified initial generation, no-op
skipping, regeneration after deleting a recorded output, and a
subsequent no-op skip using the same manifest-invalidation protocol.
- The full integration workflow could not complete locally because
Android workload installation exhausted the shared disk; the updated
Build integration test will validate on CI.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Gerald Versluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Aug 7, 2026
…tputs are deleted (#33919)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

The Resizetizer copies and registers `MauiFont` / `MauiSplashScreen`
assets during the build. Two incremental-build gaps could leave an app
packaged **without** its fonts or splash screen:

1. **First build (Android/Tizen)** — item *registration*
(`AndroidAsset`, `BundleResource`, …) lived **inside** the incremental
`ProcessMauiFonts` target. On a clean build the target's
output-inference glob was empty, so the platform items were never
registered and fonts were missing until a *second* build. The fix splits
registration into an always-run `_CollectMauiFontItems` target that maps
font paths predictively from `@(MauiFont)`.

2. **Incremental build (all platforms)** — `ProcessMauiFonts` /
`ProcessMauiSplashScreens` tracked freshness with `mauifont.stamp` /
`mauisplash.stamp` files. A stamp could stay newer than a generated
output that was later deleted (partial `obj` clean or concurrent build),
so MSBuild skipped the target and the package shipped without the
missing font/splash. The fix replaces stamps with `mauifont.outputs` /
`mauisplash.outputs` manifests. `_ReadMauiFontOutputs` /
`_ReadMauiSplashOutputs` run before freshness evaluation, delete the
manifest when a listed generated output is missing, and each processor
uses the manifest as its sole `Outputs`. This makes only the affected
processor rerun without re-stamping unchanged generated assets and
unnecessarily invalidating downstream consumers such as Android aapt2.

This PR **consolidates** #35962 (closed): it drops the font/splash
stamps, adds `ProcessMauiSplashScreensDependsOnTargets`, and
de-duplicates fonts by intermediate filename before
`CreatePartialInfoPlistTask`, so colliding names (for example an app and
a `ProjectReference` both shipping `OpenSans.ttf`) do not emit duplicate
`UIAppFonts` entries.

The related runtime-side symptom (noisy missing-font fallback logging)
is intentionally out of scope here and handled separately in #35963.

### Issues Fixed

Fixes #23268
Fixes #33092

### Tests

- `ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild` — clean
Release build of the `maui` template asserts the font lands in the
Android `assets` folder on the **first** build, then an incremental
build confirms `ProcessMauiFonts` is skipped while the always-run
`_CollectMauiFontItems` still registers the asset.
-
`ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing`
(macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes
only the generated iOS/MacCatalyst `MauiInfo.plist` files and verifies
both font processors rerun and restore them, then deletes generated
font/splash folders, verifies recovery, and finally verifies a no-op
build skips both processors.

### Validation

- A focused MSBuild sequence verified initial generation, no-op
skipping, regeneration after deleting a recorded output, and a
subsequent no-op skip using the same manifest-invalidation protocol.
- The full integration workflow could not complete locally because
Android workload installation exhausted the shared disk; the updated
Build integration test will validate on CI.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Gerald Versluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Aug 12, 2026
…tputs are deleted (#33919)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

The Resizetizer copies and registers `MauiFont` / `MauiSplashScreen`
assets during the build. Two incremental-build gaps could leave an app
packaged **without** its fonts or splash screen:

1. **First build (Android/Tizen)** — item *registration*
(`AndroidAsset`, `BundleResource`, …) lived **inside** the incremental
`ProcessMauiFonts` target. On a clean build the target's
output-inference glob was empty, so the platform items were never
registered and fonts were missing until a *second* build. The fix splits
registration into an always-run `_CollectMauiFontItems` target that maps
font paths predictively from `@(MauiFont)`.

2. **Incremental build (all platforms)** — `ProcessMauiFonts` /
`ProcessMauiSplashScreens` tracked freshness with `mauifont.stamp` /
`mauisplash.stamp` files. A stamp could stay newer than a generated
output that was later deleted (partial `obj` clean or concurrent build),
so MSBuild skipped the target and the package shipped without the
missing font/splash. The fix replaces stamps with `mauifont.outputs` /
`mauisplash.outputs` manifests. `_ReadMauiFontOutputs` /
`_ReadMauiSplashOutputs` run before freshness evaluation, delete the
manifest when a listed generated output is missing, and each processor
uses the manifest as its sole `Outputs`. This makes only the affected
processor rerun without re-stamping unchanged generated assets and
unnecessarily invalidating downstream consumers such as Android aapt2.

This PR **consolidates** #35962 (closed): it drops the font/splash
stamps, adds `ProcessMauiSplashScreensDependsOnTargets`, and
de-duplicates fonts by intermediate filename before
`CreatePartialInfoPlistTask`, so colliding names (for example an app and
a `ProjectReference` both shipping `OpenSans.ttf`) do not emit duplicate
`UIAppFonts` entries.

The related runtime-side symptom (noisy missing-font fallback logging)
is intentionally out of scope here and handled separately in #35963.

### Issues Fixed

Fixes #23268
Fixes #33092

### Tests

- `ResizetizerTests.FontsAreCopiedToAndroidAssetsOnFirstBuild` — clean
Release build of the `maui` template asserts the font lands in the
Android `assets` folder on the **first** build, then an incremental
build confirms `ProcessMauiFonts` is skipped while the always-run
`_CollectMauiFontItems` still registers the asset.
-
`ResizetizerTests.BuildRegeneratesFontsAndSplashWhenIntermediateOutputsAreMissing`
(macOS-gated) — builds Android/iOS/MacCatalyst template targets, deletes
only the generated iOS/MacCatalyst `MauiInfo.plist` files and verifies
both font processors rerun and restore them, then deletes generated
font/splash folders, verifies recovery, and finally verifies a no-op
build skips both processors.

### Validation

- A focused MSBuild sequence verified initial generation, no-op
skipping, regeneration after deleting a recorded output, and a
subsequent no-op skip using the same manifest-invalidation protocol.
- The full integration workflow could not complete locally because
Android workload installation exhausted the shared disk; the updated
Build integration test will validate on CI.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Gerald Versluis <939291+jfversluis@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compilation randomly missing custom fonts & splashScreen Copy font assets only works at second build

7 participants