Add proposal for supporting older .NET SDKs#16812
Conversation
This document proposes changes to support older .NET SDKs with Arcade `main`, allowing consumer repositories to manage their SDK versions independently and simplifying the SDK update process.
|
|
||
| **Recommendation**: stop the PCS-driven SDK flow. | ||
|
|
||
| **Fallback**: if there is product-level pressure to keep some repos on a specific SDK in lockstep with Arcade, the current PCS mechanism can be retained as an opt-in for those repos. The expectation, however, is that this becomes the exception, not the default. |
There was a problem hiding this comment.
isn't it only a small number of tooling repos that use an earlier arcade (== SDK)? the vast majority of repos use the arcade-distributed SDK version. You also need to think of repos outside of the VMR.
I'd make the dependabot behavior opt-in instead.
I also don't know if dependabot supports updating to nightly/preview builds of the SDK which is important for dogfooding and we regularly do that today via VMR rebootstrap.
|
|
||
| PCS honors `tools.pinned: true` and will not update the SDK version in that repo's `global.json`. This is the supported per-repo opt-out and works independently of Change A. A repo can apply it today, ahead of any global change to PCS behavior, as a low-risk way to decouple its SDK cadence from Arcade's. | ||
|
|
||
| Open question: do we want a transition period where both mechanisms coexist, and what is the off-ramp? `tools.pinned` makes a long coexistence cheap, since opt-out is a one-line repo change. |
There was a problem hiding this comment.
if we keep it I'd prefer we add sdk.pinned, having it in tools sounds confusing if this is the only thing there
|
|
||
| ### 4.2 Redefine the floating TFM properties | ||
|
|
||
| The goal is to make `NetCurrent`/`NetPrevious`/`NetMinimum` mean the same thing in Arcade `main`, `release/10.0`, `release/9.0`, etc., so that a project author does not have to reason about "which Arcade branch am I being built by". |
There was a problem hiding this comment.
mean the same thing in Arcade
main,release/10.0,release/9.0
I thought one goal was to basically get rid of arcade release branches?
|
|
||
| Drawbacks / open questions: | ||
|
|
||
| - Two repos on the same Arcade `main` but different SDKs would see different `NetCurrent` values. That is the point, but it is also a behavioural change. |
There was a problem hiding this comment.
not just two repos, but given Arcade "main" would be used in e.g. runtime release/10.0 and release/9.0 there's really no other way that I can see (other than your option B).
|
|
||
| #### Option B — Decouple from the SDK entirely (open) | ||
|
|
||
| Is there a useful definition of `NetCurrent` that is independent of both the Arcade branch and the consuming SDK? For example, "the latest GA .NET TFM at the time of build" derived from an external source. This is listed as an open question; it is not obvious that decoupling from the SDK actually adds value over Option A. |
There was a problem hiding this comment.
"the latest GA .NET TFM at the time of build" derived from an external source
This sounds like a magic value coming from somewhere that is hard to reason about later on...
TBH the only good way I can think of is adding in a property into Version.props that defines which .NET release train this branch targets (but that doesn't sound ideal either)
|
|
||
| ### 4.3 Keep Arcade compatible with the SDKs that map to `$(NetMinimum)` and newer | ||
|
|
||
| Arcade `main` and everything inside `eng/common` must build and run on every .NET SDK from `$(NetMinimum)` up to the in-development one. Today that is .NET 10 and .NET 11. |
There was a problem hiding this comment.
I don't think NetMinimum as defined today (which is from the point of view of the .NET release the current arcade maps to) can be translated into this, e.g. today we still support 8.0 and 9.0. If the goal is to just have Arcade main then we'd need to support down to 8.0 today.
|
|
||
| This document proposes three coordinated changes that, taken together, allow Arcade `main` to be consumed by any repo on a supported .NET SDK (at minimum the current and previous major release — today .NET 11 and .NET 10): | ||
|
|
||
| 1. Move .NET SDK updates in consumer repos to [Dependabot](https://devblogs.microsoft.com/dotnet/using-dependabot-to-manage-dotnet-sdk-updates/) and stop flowing the SDK version through the Product Construction Service (PCS) via Arcade's dependency-flow channel. Repos can opt out of PCS-driven SDK updates today by setting `tools.pinned: true` in `global.json`; in parallel, `global.json` can be simplified to use only `sdk.version` (no duplicate `tools.dotnet`), which requires a small `eng/common` change. |
There was a problem hiding this comment.
Will dependabot pick up the random versions of the SDK we produce on a daily basis? I think this works for released versions..but what about in-development? Won't we just end up having many repos just having to stay on what the VMR has due to repos taking dependencies on new SDK behavior?
|
|
||
| 1. Move .NET SDK updates in consumer repos to [Dependabot](https://devblogs.microsoft.com/dotnet/using-dependabot-to-manage-dotnet-sdk-updates/) and stop flowing the SDK version through the Product Construction Service (PCS) via Arcade's dependency-flow channel. Repos can opt out of PCS-driven SDK updates today by setting `tools.pinned: true` in `global.json`; in parallel, `global.json` can be simplified to use only `sdk.version` (no duplicate `tools.dotnet`), which requires a small `eng/common` change. | ||
| 2. Redefine the floating TFM properties (`NetCurrent`, `NetPrevious`, `NetMinimum`, `NetFrameworkMinimum`) so their values are no longer tied to a specific Arcade release branch. | ||
| 3. Keep Arcade `main` and `eng/common` working on the current and previous major .NET SDK versions, going forward. |
There was a problem hiding this comment.
This is primarily about eng/common's TFM-related elements, right?
|
|
||
| - **Source-build (`DotNetBuildSourceOnly`)**: The existing collapse of `NetPrevious`/`NetMinimum` onto `NetCurrent` when building from source must be preserved by whichever option is chosen in §4.2. | ||
| - **`NetCurrent` consumers that expected "in-development .NET"**: A small number of repos use `$(NetCurrent)` precisely to follow the in-development version. Under Option A, that behaviour requires those repos to keep their SDK on the preview channel themselves. | ||
| - **CI cost**: Validating Arcade and `eng/common` against N and N-1 SDKs increases CI matrix size. The cost should be scoped before committing. |
| - **Source-build (`DotNetBuildSourceOnly`)**: The existing collapse of `NetPrevious`/`NetMinimum` onto `NetCurrent` when building from source must be preserved by whichever option is chosen in §4.2. | ||
| - **`NetCurrent` consumers that expected "in-development .NET"**: A small number of repos use `$(NetCurrent)` precisely to follow the in-development version. Under Option A, that behaviour requires those repos to keep their SDK on the preview channel themselves. | ||
| - **CI cost**: Validating Arcade and `eng/common` against N and N-1 SDKs increases CI matrix size. The cost should be scoped before committing. | ||
| - **Repos relying on PCS-driven SDK uplift for compliance**: Some teams may rely on Arcade pushing the SDK as their only signal to update. Dependabot adoption needs to be in place before turning off the PCS flow. |
There was a problem hiding this comment.
This likely won't work for out of support product versions. There will need to be reconfiguration to use PCS once we hit that point (e.g. 6.0)
|
|
||
| 1. **PCS flows the SDK version.** Repos subscribed to Arcade's dependency-flow channel receive Arcade's `global.json` SDK alongside Arcade package versions, so an SDK uplift is forced regardless of whether the repo wants it. | ||
| 2. **`NetCurrent`/`NetPrevious`/`NetMinimum` change meaning with the Arcade branch.** A project that uses `<TargetFramework>$(NetCurrent)</TargetFramework>` retargets simply because the upstream Arcade branch moved on. That is desirable for some repos and surprising for others. | ||
| 3. **Cross-cutting VMR changes are expensive.** When building inside the VMR, every inner repo is built against Arcade `main`. But the same inner repos in their standalone (non-VMR) builds may consume a different Arcade — typically because they are pinned to a specific .NET SDK (e.g. .NET 10) that Arcade `main` doesn't support, so they pick up Arcade `release/10.0` instead. This is independent of which release band the repo ships in: a current-band (.NET 11) repo can still be on Arcade `release/10.0` because of its SDK pin. A cross-cutting change to Arcade plus its consumers therefore can't simply be made in `main` and one PR per repo — the change has to work against whatever Arcade each repo uses standalone, which often means coordinated changes across multiple Arcade branches and inner repos before anything can flow. |
There was a problem hiding this comment.
I don't think this proposal changes the cross-cutting problem. You will still have it.
11.0.1xx will be on 11.0 arcade:
10.0.4xx will be on 10.0 arcade.
That would mean that, in theory, msbuild's 10.0.4xx branch could move to 11.0 arcade (so no need for dual changes), but that would pull other repos in that direction too to avoid any kind of cross-cutting friction: SDK's 10.0.4xx branch, for instance, would get pulled forward to 11.0 arcade.
That might be possible, but then we introduce new risk into the servicing bands.
mmitche
left a comment
There was a problem hiding this comment.
I worry this might just replace one kind of friction with another set. Validation of Arcade main against multiple in-support bands is one major concern, so validation friction. But also, it would keep us from introducing any strong coupling between SDK features and Arcade infra. Arcade can't take advantage of any new SDK features until they are long since shipped.. This will likely push this kind of customization down into repos, where it will be harder to maintain.
I kind of think the current pain might be better than the alternative?
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Added an explicit section for the scope, goals and anti-goals of this proposal. |
This document proposes changes to support older .NET SDKs with Arcade
main, allowing consumer repositories to manage their SDK versions independently and simplifying the SDK update process.The current state in dotnet/msbuild#13735 (comment) made me finally submit this proposal.
To double check: