Freeze Aspire.TypeSystem AssemblyVersion at 13.4.4.0 to fix cross-ALC codegen binding#18160
Freeze Aspire.TypeSystem AssemblyVersion at 13.4.4.0 to fix cross-ALC codegen binding#18160sebastienros wants to merge 1 commit into
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18160Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18160" |
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical issue where polyglot (TypeScript/Python/Java/Go/Rust) AppHost code generation silently fails when the installed Aspire CLI is older than the AppHost's configured SDK within the same major version (e.g., 13.4.3 CLI + 13.5.0 SDK). The root cause was that the strong-named AssemblyVersion floated with MAJOR.MINOR.PATCH, preventing the older bundled Aspire.TypeSystem from satisfying newer codegen assemblies' strong-named references.
Changes:
- Pins
Aspire.TypeSystem'sAssemblyVersionto$(MajorVersion).0.0.0so that any CLI/SDK combination within the same major binds successfully, while preserving real build identities inFileVersionandInformationalVersion. - Adds explanatory comments in
IntegrationLoadContextandAssemblyLoaderdocumenting why the version pin makes the shared-assembly short-circuit and mismatch check safe. - Introduces
AtsSharedContractSurfaceTestswith an embedded baseline snapshot to guard against future breaking changes to the public surface that could reintroduce the binding failure.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/Aspire.TypeSystem/Aspire.TypeSystem.csproj |
Core fix: pins AssemblyVersion to MAJOR.0.0.0 with thorough rationale comment |
src/Aspire.Hosting.RemoteHost/IntegrationLoadContext.cs |
Documents why the SharedAssemblyName short-circuit is safe under the pinned version |
src/Aspire.Hosting.RemoteHost/AssemblyLoader.cs |
Restructures WarnIfSharedAssemblyMismatch docs to explain post-pin semantics (cross-major only warning, same-version/differing-MVID is benign) |
tests/Aspire.Hosting.RemoteHost.Tests/AtsSharedContractSurfaceTests.cs |
New back-compat guard test comparing assembly public surface against embedded baseline |
tests/Aspire.Hosting.RemoteHost.Tests/Aspire.Hosting.RemoteHost.Tests.csproj |
Adds embedded resource and Aspire.TypeSystem project reference for the new test |
tests/Aspire.Hosting.RemoteHost.Tests/Snapshots/AtsSharedContractSurface.txt |
Frozen public API surface baseline for Aspire.TypeSystem |
PR Testing ReportPR Information
Artifact Version Verification
Changes AnalyzedFiles Changed
Change Categories
Frozen-version proof (the heart of the fix)Extracted from the dogfood hive ( The package version still floats ( Test Scenarios ExecutedScenario 1: Install + version matchObjective: Install the PR CLI and confirm it reports the PR head commit. Steps:
Evidence: version Scenario 2: TypeScript AppHost codegen (regression check)Objective: Verify TypeScript polyglot code generation works (the exact path that failed in the regression). Steps:
Evidence (
Scenario 3: Python AppHost codegen (regression check)Objective: Verify a second polyglot language (Python) codegen path works. Steps:
Evidence (
Scenario 4: Package build (CP0003) ships without any overrideObjective: Confirm the Key delta vs the earlier Evidence (CI run
CI corroboration: all five polyglot languages green on head
|
| Scenario | Status | Notes |
|---|---|---|
| 1. Install + version match | ✅ Passed | 13.4.4-pr.18160.g37ba3575 matches head |
| 2. TypeScript codegen | ✅ Passed | aspire.mts 2.6 MB, 1366 Redis refs, no cryptic error |
| 3. Python codegen | ✅ Passed | aspire_app.py 530 KB, 43 Redis refs, no cryptic error |
| 4. Package build (CP0003) | ✅ Passed | No DisablePackageBaselineValidation needed (13.4.4.0 >= 13.4.0) |
| CI polyglot matrix (TS/Py/Java/Go/Rust) | ✅ Passed | run 27453745514, all codegen suites green |
Overall Result
✅ PR VERIFIED
Notes
- Frozen
AssemblyVersion = 13.4.4.0is a no-op onrelease/13.4(product is already 13.4.4) and only constrains 13.5+; merged forward to main it keeps every future stable/servicing bundle on the sentinel. - Skew (old/pre-freeze CLI + newer SDK) is intentionally not dogfood-reproducible; that path relies on the prior binary A/B repro + the contract-freeze guard + Surface actionable diagnostic when TypeScript codegen generator is dropped by load failure #18125 diagnostics.
- PR is a draft — this is test-and-report only; no approve/merge performed.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
a68ad08 to
39c789d
Compare
39c789d to
37ba357
Compare
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
… codegen binding
Polyglot (TypeScript/Python/Java/Go/Rust) AppHost code generation silently fails
("No code generator found for language: ...") when the installed CLI and the
AppHost's SDK skew in version. The CLI's bundled apphost server force-shares
Aspire.TypeSystem from its default ALC, but the SDK-side codegen assemblies carry a
strong-named reference to a different Aspire.TypeSystem version. The CLR only
satisfies a strong-named reference when the loaded copy's AssemblyVersion is >= the
requested version, so a floating per-build AssemblyVersion makes the bind fail,
Assembly.GetTypes() throws ReflectionTypeLoadException, and every generator is
dropped (#18110, #17910).
Freeze the strong-name AssemblyVersion at the fixed constant 13.4.4.0 (the version of
the servicing release that introduces this freeze, >= the latest shipped stable
13.4.3), decoupled from the build and carried forward to main so every later stable
and servicing release bundles the same value. Only AssemblyVersion is frozen;
FileVersion/InformationalVersion/PackageVersion stay build-derived so diagnostics keep
real identities. Document the now-intentional shared-from-bundle binding in
IntegrationLoadContext and the version-ordered warning in AssemblyLoader.
Add AtsSharedContractSurfaceTests as a back-compat guard over the shared contract
surface (embedded baseline) so any removal/signature change forces a deliberate
AssemblyVersion bump instead of silently reintroducing the binding failure.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
37ba357 to
88c35bb
Compare
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
❓ CLI E2E Tests unknown — 112 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #27476760558 |
Problem
Polyglot AppHost code generation (TypeScript/Python/Java/Go/Rust) silently fails with
No code generator found for language: <lang>when the installed Aspire CLI and the AppHost's configured SDK skew in version (e.g. an older CLI running a newer SDK, or a current CLI running an older stable SDK).Root cause
The CLI's bundled apphost server (
Aspire.Hosting.RemoteHost, shipped as the single-fileaspire-managedexecutable) loadsAspire.TypeSysteminto its defaultAssemblyLoadContextandIntegrationLoadContextdeliberately force-shares it from there, so the cross-ALC contracts (ICodeGenerator,ILanguageSupport,AtsContext) keep a single type identity across the ALC boundary.The SDK-side codegen assemblies (
Aspire.Hosting.CodeGeneration.*) are strong-named (StrongNameKeyId=Open) and carry a strong-named reference toAspire.TypeSystem. The CLR satisfies a strong-named reference only when the loaded copy'sAssemblyVersionis>=the requested version. BecauseAssemblyVersionfloated with the build (MAJOR.MINOR.PATCH), the bundled copy and the codegen reference diverged whenever the CLI and SDK were built at different times → the bind failed →Assembly.GetTypes()threwReflectionTypeLoadException→ every generator was silently dropped (#18110, #17910).This affects all polyglot languages and the ATS capability-scan path, not just TypeScript. The
Aspire.TypeSystemsource surface itself is unchanged betweenrelease/13.4andmain— it is purely the strong-name version bump that breaks the bind.Fix
Freeze the strong-name
AssemblyVersionofAspire.TypeSystemat the fixed constant13.4.4.0, decoupled from the build:13.4.4.0is the version of the 13.4.4 servicing release that introduces the freeze, and is>= 13.4.3.0(the latest shipped stable), so a current CLI binds against any already-shipped stable app's codegen reference — the common, must-work backward-compat direction.mainso every later stable and servicing release (13.4.4, 13.5, ...) bundles the same value; post-freeze CLI/SDK pairs then match exactly and no skew matters. Onrelease/13.4the product version is already13.4.4, so this is a no-op for that build and only constrains future minors.AssemblyVersionis frozen;FileVersion,InformationalVersion, and the NuGet package version stay build-derived, so diagnostics keep real build identities.Aspire.TypeSystemis consumed only viaProjectReference(noPackageReferenceconsumers), so the frozen assembly version is not a package contract anyone binds to by exact version, and CP0003 package-baseline validation still passes (13.4.4.0 >=baseline).Residual cases (routed to diagnostics, not silent)
Two narrow skews can't be fixed by any freeze value and are surfaced as an actionable "run
aspire update" message by the #18125 diagnostics:13.4.4.0.13.5.0.0(>13.4.4.0); preview-channel skew is outside the supported stable matrix and is superseded by post-freeze builds.Back-compat guard
Because binding now succeeds on version alone, that safety only holds if the shared contract stays strictly additive.
AtsSharedContractSurfaceTestssnapshots the shared-contract surface (embedded baseline) and fails on any removal/signature change, forcing a deliberate decision: additive (no bump) vs breaking (bumpAssemblyVersion).Validation
Aspire.Hosting.RemoteHost.Tests: 451/451 passed on therelease/13.4base (includes the new contract-surface guard).dotnet pack src/Aspire.TypeSystem: succeeds with no CP0003 override.ReflectionTypeLoadException(generators dropped), AFTER → generator discovered.Targets
release/13.4for the 13.4.4 servicing release. Relates to #18110, #17910; complementary to the #18125 diagnostics.