|
| 1 | +# SDK Breaking Change and Diagnostic Guidelines |
| 2 | + |
| 3 | +Teams may want to add new diagnostics or breaking changes to the SDK. This document provides guidelines for how to introduce a new diagnostic or breaking change, which configuration knobs are available to teams, and what criteria should guide the decision around severity, timeline for introduction, and deprecation of diagnostics. |
| 4 | + |
| 5 | +## Overall procedure |
| 6 | + |
| 7 | +In general, we want to make updating the SDK as smooth as possible for users. This means as much as possible |
| 8 | +not rocking the boat unnecessarily. This means |
| 9 | + |
| 10 | +* introducing new changes in a staged/gradual way |
| 11 | +* trying to tie opinionated analyzers/changes to a mechanism that requires explicit user input |
| 12 | +* providing a way to opt out of a change entirely |
| 13 | + |
| 14 | +## Kinds of changes |
| 15 | + |
| 16 | +There are a bunch of kinds of changes that can ship in the SDK, and they have different implications for users. Here are some examples: |
| 17 | + |
| 18 | +* MSBuild warnings and errors |
| 19 | + * Directly triggered in MSBuild logic (props/targets) |
| 20 | + * directly in the SDK props/targets |
| 21 | + * indirectly via codeflow, just shipped in the SDK |
| 22 | + * Directly written by MSBuild Task implementations |
| 23 | + * Including those surfaced by key partners like NuGet (e.g. NuGet Audit, Package Source Mapping) |
| 24 | +* Roslyn Analyzers and CodeFixes |
| 25 | + * This includes trimming/ILLink analyzers and codefixes |
| 26 | +* Behavioral/implementation changes |
| 27 | + * MSBuild engine changes like MSBuild Server |
| 28 | + * Implementation changes for MSBuild Tasks |
| 29 | + * NuGet Restore algorithm enhancements |
| 30 | + * Changes to CLI grammar |
| 31 | + * Changes to defaults in CLI flags that impact behavior |
| 32 | + * `--configuration` flag defaulting to `Release` instead of `Debug` |
| 33 | + |
| 34 | +## Configuration Knobs |
| 35 | + |
| 36 | +The following knobs are available to teams to configure various changes (some may not apply to all kinds of changes): |
| 37 | + |
| 38 | +* TargetFramework (TFM) |
| 39 | +* SDK version (via SdkAnalysisLevel) |
| 40 | +* EditorConfig (for Analyzers) |
| 41 | +* AnalysisLevel (for Analyzers/CodeFixes) |
| 42 | +* WarningLevel |
| 43 | + |
| 44 | +## Deciding how to Surface Changes |
| 45 | + |
| 46 | +* Implement changes in an informational/non-blocking way initially |
| 47 | + |
| 48 | +What this means will vary change-to-change. For a change expressed as an Analyzer or MSBuild diagnostic, consider |
| 49 | +Informational level severities initially. For a behavioral change on a CLI, consider an informational message written to the |
| 50 | +stderr channel on the console instead of making the stdout output un-parseable by tools. |
| 51 | + |
| 52 | +Concrete example: When the `dotnet new --list` command was changed to `dotnet new list` to adhere to CLI design guidelines, |
| 53 | +the old command was still the default supported and a warning was written to the console when the old form was used pointing users to the new form. This allowed users and scripts to continue using the old form and gradually migrate to the new. |
| 54 | + |
| 55 | +* Gradually increase severity over each release |
| 56 | + |
| 57 | +If a change in introduced in an informational/non-blocking way, determine the time frame where it is safe to increase the severity. For Analyzers, this may mean tying it to the next value of AnalysisLevel (which is downstream of TFM). For |
| 58 | +MSBuild diagnostics, this may mean tying it to the next Warning Level or SdkAnalysisLevel. For CLI changes, this may mean tying it to the next LTS major version of the SDK. Ideally the way you would structure this increase would be automated and |
| 59 | +documented so that users know what's coming down the pipe. |
| 60 | + |
| 61 | +* Cut-over to new behavior after a long introduction period |
| 62 | + |
| 63 | +After the change has been introduced in a gradual way, cut over to the new behavior. This may mean removing the old behavior entirely, or it may mean making the new behavior the default and providing a way to opt out of it. It is important that you |
| 64 | +provide enough time for users to adapt - for example the `dotnet new --list` example above took an entire major release to make the new forms the default. |
| 65 | + |
| 66 | +* Always provide a way to opt out of the change |
| 67 | + |
| 68 | +Have some kind of knob that allows users to opt out of the change entirely. This could be a flag, an environment variable, or a global.json setting. This allows users to continue using the old behavior if they need to in exceptional situations. It is |
| 69 | +important to document this knob and its behavior in the SDK documentation. It is also important to define a timeline for when this knob will be removed entirely, forcing users to adopt the new behavior. |
| 70 | + |
| 71 | +For systems like Analyzers that time may be 'never', because the cost of detection is so low. This is a product-level decision |
| 72 | +that is hard to give universal guidance for. |
| 73 | + |
| 74 | +* Hook into the unified SdkAnalysisLevel knob to allow users to easily opt out of all changes |
| 75 | + |
| 76 | +This knob exists so that users can safely and consistently say "for whatever reason, I just need you to act like SDK version X". This is the one-stop shop - users no longer need to know about all the individual knobs that are available to them. |
| 77 | + |
| 78 | +## Worked examples of changes |
0 commit comments