Skip to content

Decouple SDK package versions from in-development builds - #36598

Closed
jonathanpeppers wants to merge 1 commit into
mainfrom
jonathanpeppers-decouple-extensions-versions
Closed

Decouple SDK package versions from in-development builds#36598
jonathanpeppers wants to merge 1 commit into
mainfrom
jonathanpeppers-decouple-extensions-versions

Conversation

@jonathanpeppers

@jonathanpeppers jonathanpeppers commented Jul 15, 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!

Root Cause

MAUI used the package-specific versions flowed from each in-development .NET SDK build for both shipping projects and tests. That forced shipping packages to move with every SDK preview. Template packing also substituted those exact prerelease versions, and its file-only incremental inputs could reuse stale generated metadata when only version properties changed.

Description of Change

  • introduces coherent previous-published properties for Microsoft.Extensions., Microsoft.AspNetCore., Microsoft.JSInterop, and runtime-coupled packages used by shipping/source projects
  • preserves the package-specific SDK-flowed properties as the current versions and opts tests, benchmarks, manual tests, and device runners into them
  • removes stale hardcoded test and build-task versions so centralized selection applies consistently
  • emits floating * versions from generated templates while the current dependency is prerelease, then emits the concrete previous-published stable version automatically at GA
  • reruns template substitution on every pack so version-only changes cannot leave stale template defaults
  • aligns workload substitutions and component-governance metadata with previous-published shipping versions
  • runs preview N-1, first-preview/prior-stable, current-preview test, and stable-GA assertions as part of template packing

Key Technical Details

The SDK-flowed package-specific properties remain unchanged for dependency automation. MicrosoftExtensionsPreviousPublishedPackageVersion, MicrosoftAspNetCorePreviousPublishedPackageVersion, and MicrosoftNETCoreAppRefPreviousPublishedPackageVersion define the coherent shipping baseline; UseLatestDotNetPackageVersions switches test projects back to current N.

Template floating behavior is based on whether the current SDK-flowed dependency is prerelease, not whether N-1 is prerelease. This keeps Preview 1 floating even when its previous published fallback is the prior stable major.

Tests

  • dotnet test src\Core\tests\UnitTests\Core.UnitTests.csproj -v:minimal (831 passed, 3 skipped)
  • dotnet build src\Controls\tests\Xaml.UnitTests\Controls.Xaml.UnitTests.csproj -v:minimal
  • dotnet build src\Workload\Microsoft.NET.Sdk.Maui.Manifest\Microsoft.NET.Sdk.Maui.Manifest.csproj -v:minimal
  • dotnet build src\Templates\src\Microsoft.Maui.Templates.csproj -v:minimal
  • preview and stable template packs, including consecutive packs without cleaning, produced * and 11.0.0 respectively

Alternatives Considered

No existing PR referencing this issue or the decoupling title was found. Hardcoding N-1 independently in every source project was rejected because it would duplicate policy and discard the current package-specific properties needed by dependency automation and tests.

Issues Fixed

Fixes #36434

Use previous published .NET package versions for shipping projects while keeping tests on the current SDK versions. Float generated template dependencies during previews and materialize stable versions at GA.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 04f3cfc9-6fd2-4bf1-9c79-0413b50f5ae6
Copilot AI review requested due to automatic review settings July 15, 2026 19:27
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36598

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36598"

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions github-actions Bot added the area-infrastructure CI, Maestro / Coherency, upstream dependencies/versions label Jul 15, 2026

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 adjusts MAUI’s dependency versioning so shipping/workload/template references can remain on the last publicly available .NET package versions (typically N-1 during previews), while tests/benchmarks/manual runners can still consume the current SDK-flowed versions. This helps avoid rebuilding MAUI against every in-development SDK drop and enables templates to restore without version-mismatch warnings.

Changes:

  • Introduces “previous published” version properties and updates centralized package version selection in eng/NuGetVersions.targets.
  • Updates templates packing to emit floating * versions during previews and concrete versions at stable, plus makes template substitution non-incremental.
  • Opts test, benchmark, manual test, and device runner projects into “latest SDK” package versions and removes stale hardcoded package versions.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Workload/Microsoft.NET.Sdk.Maui.Manifest/Microsoft.NET.Sdk.Maui.Manifest.csproj Maps selected workload manifest substitutions to previous-published AspNetCore/JSInterop versions.
src/TestUtils/src/DeviceTests.Runners/TestUtils.DeviceTests.Runners.csproj Opts device test runner into latest SDK versions; removes hardcoded Microsoft.Extensions.Logging.Console version.
src/Templates/src/Microsoft.Maui.Templates.csproj Adds preview/stable template version selection (* vs exact), disables incremental substitution, and adds a pack-time validation target.
src/Core/tests/UnitTests/Core.UnitTests.csproj Opts unit tests into latest SDK versions.
src/Core/tests/DeviceTests.Shared/Core.DeviceTests.Shared.csproj Opts device tests into latest SDK versions; removes hardcoded logging package version.
src/Core/tests/Benchmarks/Core.Benchmarks.csproj Opts benchmarks into latest SDK versions.
src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj Opts XAML unit tests into latest SDK versions; removes hardcoded System.CodeDom version.
src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj Opts UI test host app into latest SDK versions.
src/Controls/tests/ManualTests/Controls.ManualTests.csproj Opts manual tests into latest SDK versions; removes hardcoded logging debug package version.
src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj Opts Controls core unit tests into latest SDK versions.
src/Controls/src/Build.Tasks/Controls.Build.Tasks.csproj Removes hardcoded System.CodeDom version to rely on centralized selection.
src/Compatibility/Core/tests/Compatibility.UnitTests/Compatibility.Core.UnitTests.csproj Opts compatibility unit tests into latest SDK versions.
eng/Versions.props Adds previous-published version properties for runtime/extensions/aspnetcore.
eng/scripts/update-cgmanifest.ps1 Aligns cgmanifest version mapping for select Microsoft.Extensions packages to previous-published versions.
eng/NuGetVersions.targets Implements the central “shipping uses previous-published; tests can opt into latest” version selection logic.

Comment thread eng/Versions.props
Comment on lines +39 to +42
<MicrosoftNETCoreAppRefPreviousPublishedPackageVersion>10.0.0</MicrosoftNETCoreAppRefPreviousPublishedPackageVersion>
<SystemTextJsonPackageVersion>$(MicrosoftNETCoreAppRefPreviousPublishedPackageVersion)</SystemTextJsonPackageVersion>
<SystemTextEncodingsWebPackageVersion>$(MicrosoftNETCoreAppRefPreviousPublishedPackageVersion)</SystemTextEncodingsWebPackageVersion>
<MicrosoftBclAsyncInterfacesPackageVersion>$(MicrosoftNETCoreAppRefPreviousPublishedPackageVersion)</MicrosoftBclAsyncInterfacesPackageVersion>
Comment thread eng/Versions.props
Comment on lines +44 to 46
<SystemCodeDomPackageVersion>$(MicrosoftNETCoreAppRefPreviousPublishedPackageVersion)</SystemCodeDomPackageVersion>
<MicrosoftExtensionsPreviousPublishedPackageVersion>10.0.0</MicrosoftExtensionsPreviousPublishedPackageVersion>
<MicrosoftExtensionsConfigurationVersion>10.0.0</MicrosoftExtensionsConfigurationVersion>
Comment thread eng/Versions.props
Comment on lines +81 to 82
<MicrosoftAspNetCorePreviousPublishedPackageVersion>10.0.0</MicrosoftAspNetCorePreviousPublishedPackageVersion>
<MicrosoftAspNetCoreAuthorizationPackageVersion>10.0.0</MicrosoftAspNetCoreAuthorizationPackageVersion>
@jonathanpeppers

Copy link
Copy Markdown
Member Author

This is targeting the wrong branch

kubaflo pushed a commit that referenced this pull request Aug 13, 2026
<!-- 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!

### Root Cause

MAUI uses package versions from the in-development .NET SDK for shipping
projects, tests, and generated templates. During previews, each SDK
update therefore changes shipping dependencies and template defaults
even though the previous band's compatible packages are already
published.

An unconstrained NuGet `*` is also not prerelease-aware: it selected
stable .NET 10 ASP.NET Core packages for prerelease MAUI artifacts,
causing the Blazor integration builds to fail with assembly version
conflicts.

### Description of Change

- consumes the SDK-flowed .NET 11 dependency versions as N without
changing `eng/Versions.props` — currently `11.0.0-rc.1.26379.102`
- defines one explicit `MicrosoftDotNetN1PackageVersion` in
`eng/NuGetVersions.targets`, pinned to the published Preview 7 packages
(`11.0.0-preview.7.26381.103`)
- patches the existing package version properties to N-1 for
shipping/source projects while current N is prerelease
- uses current N for standard and MAUI test projects, plus explicit
current-source runners, benchmarks, and manual test apps
- automatically returns shipping projects to exact N when the current
version becomes stable
- covers Microsoft.Extensions.*, Microsoft.AspNetCore.*,
Microsoft.JSInterop, System.Text.Json, System.Text.Encodings.Web,
Microsoft.Bcl.AsyncInterfaces, and System.CodeDom
- removes stale hardcoded test versions so centralized N selection
applies consistently
- emits prerelease-aware `11.0.0-*` template defaults while N is
prerelease and exact current versions when N is stable
- records N-1 Microsoft.Extensions template dependencies in component
governance during previews and exact current dependencies at GA

The N-1 substitution is gated on N containing a prerelease label, so it
remained active across the Preview → RC transition and disables itself
automatically at GA.

### Validation

Verified against the current N / N-1 pair (`11.0.0-rc.1.26379.102` /
`11.0.0-preview.7.26381.103`):

- the pin is taken from the official release metadata (`releases.json` →
`runtime.version` for `11.0.0-preview.7`), and all affected packages
were confirmed published on nuget.org
- confirmed the PR has no diff under `eng/Version*`, and adds no
`preview.6` literal
- provisioned the RC 1 SDK with `dotnet cake --target=dotnet` and
restored with it
- `Core`, `Controls.Core`, and
`Microsoft.AspNetCore.Components.WebView.Maui` resolve **only** N-1
packages — scanned each `project.assets.json`, zero RC 1 leakage into
shipping projects
- `Core.UnitTests` resolves the `Microsoft.Extensions.*` stack at
current N (RC 1), confirming the test lane is unaffected
- `dotnet build` of `Core` and
`Microsoft.AspNetCore.Components.WebView.Maui` succeeds with 0 warnings
and 0 errors — the BlazorWebView surface is where the original assembly
version conflict appeared
- template version items evaluate to `11.0.0-*` for the .NET tokens
while N is prerelease
- `eng/scripts/update-cgmanifest.ps1` resolves `Microsoft.Extensions.*`
to N-1, and missing N-1 data still fails generation explicitly

Validated earlier against the previous band, with the mechanism
unchanged since: consecutive preview-then-stable template packs
switching all seven generated defaults from `11.0.0-*` to exact
`11.0.0`; generating and building Blazor Server and Auto/WebAssembly
projects from an installed template `.nupkg`; and inspecting 22 produced
`.nupkg` nuspecs for dependency-band leakage.

### Merge Notes

Merging the latest `net11.0` conflicted with #35950, which added an
`AVALONIA_CONTROLS_MAUI_VERSION_VALUE` template token to the
property-group replacement block that this PR replaces with
`_TemplatePackageVersion` items. The token was folded into the new item
form, and its computed value is byte-identical to the previous behaviour
(`11.0.0-preview.6.*`).

`Avalonia.Controls.Maui` is third-party, pinned separately in
`eng/Versions.props`, and is intentionally **not** wired into the N/N-1
mechanism, so its band is preserved rather than floated to `11.0.0-*`.

### Alternatives Considered

PR #36598 attempted the same decoupling from `main`, using generic
previous-published aggregates and private selector properties. This
replacement targets the actual `net11.0` dependency graph, treats the
most recently published band as N-1, and uses an explicit `N1`-named
property as requested.

A bare `*` was initially used for preview template defaults, but NuGet
excludes prerelease packages from that range. Constraining the floating
version to the current release (`11.0.0-*`) keeps preview templates
floating while preventing fallback to stable packages from an older .NET
release.

The initial implementation added duplicate conditional
`PackageReference` items and a self-invoking MSBuild test harness to the
template project. The final implementation instead patches the existing
central version properties and keeps test-only targets out of the
production project.

### Issues Fixed

Fixes #36434

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f8808afd-de8d-414a-b271-fae23ee7b596
Copilot-Session: 7d43af42-9e93-4be0-9754-b362beec3456
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-infrastructure CI, Maestro / Coherency, upstream dependencies/versions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decouple Microsoft.Extensions.* versions from the in-development .NET SDK to avoid per-SDK rebuilds

2 participants