-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Runtime binding proposal #51
Changes from 1 commit
6e2ba1c
ae4e1d9
371f25f
50f8757
a2d0e9f
1180811
83518d1
749eae3
179718e
fc12d38
cf72b01
2a80370
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -205,20 +205,37 @@ We will offer a configuration knobs for hosts that enable artificial roll-forwar | |
|
||
The host exposes the following configuration knobs that you can use to control binding behavior: | ||
|
||
### Version | ||
|
||
The `version` knob specifies the minimum (or floor) version required by an application as a 3-part version. | ||
|
||
`version` can be set in the following ways: | ||
|
||
* `RuntimeFrameworkVersion` in an MSBuild project | ||
* `version` in `.runtimeconfig.json` | ||
* `--fx-version` via the CLI | ||
|
||
|
||
If `RuntimeFrameworkVersion` is not set, then `version` defaults to the `0` patch for the specified target framework. For example, `version` would be set to `3.0.0` by default for the `netcoreapp3.0` target framework. | ||
|
||
MSBuild project settings are only consulted at build-time and are then written as properties to `.runtimeconfig.json`, which can be consulted at runtime. | ||
|
||
### RollForward | ||
|
||
We will introduce a new knob, called `RollForward`, with the following values: | ||
`RollForward` specifies the roll-forward policy for an application, either as a fallback in case a specific version | ||
|
||
`RollForward` can have the following values: | ||
|
||
* `None` -- Do not roll forward. Only bind to specified version. | ||
* `Patch` -- Roll forward to the highest patch verison. This disables minor version roll forward. | ||
* `Minor` -- Roll forward to the lowest higher minor verison, if requested minor version is missing. If the requested minor version is present, then the `Patch` policy is used. | ||
* `Major` -- Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing. If the requested major version is present, then the `Minor` and `Patch` policies are used, as appropriate. | ||
* `AlwaysLatestMinor` -- Roll forward to latest minor version, even if requested minor version is present. Intended for COM hosting scenario. | ||
* `AlwaysLatestMajor` -- Roll forward to latest major and highest minor version, even if requested major is present. Intended for COM hosting scenario. | ||
* `LatestPatch` -- Roll forward to the highest patch verison. This disables minor version roll forward. | ||
* `Minor` -- Roll forward to the lowest higher minor verison, if requested minor version is missing. If the requested minor version is present, then the `LatestPatch` policy is used. | ||
* `Major` -- Roll forward to lowest higher major version, and lowest minor version, if requested major version is missing. If the requested major version is present, then the `Minor` policy is used. | ||
* `LatestMinor` -- Roll forward to latest minor version, even if requested minor version is present. Intended for COM hosting scenario. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure we should explicitly state that this is for COM... it is useful in other cases as well. But if you think it makes sense, I'm fine with it. |
||
* `LatestMajor` -- Roll forward to latest major and highest minor version, even if requested major is present. Intended for COM hosting scenario. | ||
* `Disable` -- Do not roll forward. Only bind to specified version. This policy is not recommended for general use since it disable the ability to roll-forward to the latest patches. It is only recommended for testing. | ||
|
||
`Minor` is the default setting. See **Configuration Precedence** for more information. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Last time we spoke in a big group about this topic, there was a lot of openness to Major becoming the default. Is that now off the table? cc @DamianEdwards I think that this proposal makes configuration easier and the whole process easier to understand, I was really hoping that global tools would start to just workin mismatched major case. cc @wli3 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was more openness to it at the time. I'm not proposing that, however, as the way to move forward. When we flip that lever, the journey to re-inventing the .NET Framework will be complete. Yeahh! Another way of putting is asking which UX experience we want (since both will exist to some degree):
I'm pushing choice 1 as the good default. The second one is too hard for everyone involved. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's also the argument about hosting environments (think ASP.NET hosting). That is running my app on a container/VM which is managed by somebody else. If in such case I try to run a 2.* app on a host which only has 3.0 and it silently works... everybody thinks (including the hosting provider), that it will work just fine. In reality there might be some slight behavioral difference which can't be tested for upfront before deployment. It makes it harder for both sides to have a solid experience. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. Next question: do you consider it OK if we recommend to global tool authors to put RollForward=Major in their csproj. We have a lot of feedback that folks don't like that their global tools do not work with only 3.0 installed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It is ok as long as the global tool authors understand the consequences. This setting increases probability that the tool won't work. I think it is manageable for small tools that are unlikely to break. I would not recommend it for large complex tools. |
||
|
||
Can be specified via the following ways: | ||
`RollForward` can be set in the following ways: | ||
|
||
* Project file property: `RollForward` | ||
* Runtime configuration file property: `rollForward` | ||
|
@@ -238,13 +255,51 @@ The following policy will be used in 3.0: | |
|
||
Note: The ENV syntax is used above, but the same rules apply for any way that the two settings are set. | ||
|
||
### fx-version | ||
### Configuration Precedence | ||
|
||
The host will consult the various ways of setting `RollForward`, in order (later scopes take precendence over earlier ones): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo precendence -> precedence
richlander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
1. `.runtimeconfig.json` properties (AKA "json") | ||
2. Environment variables (AKA "ENV") | ||
3. CLI arguments | ||
|
||
The `version` and `roll-forward` settings compose in the following way: | ||
|
||
* A `version` setting at higher precedent scopes overwrites both the `version` and `roll-forward` values at lower scopes. For example, `version` specified at the CLI scope (with `--fx-version`) overwrites both a `version` and `roll-forward` setting that might exist at the json scope. | ||
* A `version` setting can flow to higher scopes if it is not replaced by another `version` value. This enables a `roll-forward` setting at a higher scope to compose with a `version` setting at a lower scope. | ||
* The absense of a `version` value is an error when the `roll-forward` value of `LatestPatch`, `Minor`, `Major` or `LatestMinor` is set since the initial version state is not available. It is not an error when the `roll-forward` value of `LatestMajor` is set since an initial version state is not meaningful. | ||
|
||
More generally: | ||
|
||
You can specify the exact desired runtime version using the command line argument '--fx-version'. | ||
* The `version` value establishes a floor for roll-forward behavior, except `LatestMajor`. | ||
* The default `roll-forward` setting is `Minor` except when `--fx-version` is specified when it is `Disabled`. | ||
|
||
### Using `version` and `roll-forward` in practice | ||
|
||
The following examples demonstrate various (non-exhaustive) ways that `version` and `roll-forward` can be used. | ||
|
||
Installed versions: | ||
|
||
The following example shows the existing behavior of this knob: | ||
* `2.1.0` | ||
* `2.1.1` | ||
* `2.1.7` | ||
* `2.2.1` | ||
* `2.2.3` | ||
* `3.1.0` | ||
* `4.0.0` | ||
* `4.2.1` | ||
|
||
```console | ||
C:\testapps\twooneapp>type twooneapp.csproj | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp2.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
</Project> | ||
|
||
C:\testapps\twooneapp>type Program.cs | ||
using System; | ||
|
||
|
@@ -259,46 +314,34 @@ namespace twooneapp | |
} | ||
} | ||
} | ||
C:\testapps\twooneapp> | ||
|
||
C:\testapps\twooneapp>dotnet bin\Debug\netcoreapp2.1\twooneapp.dll | ||
Hello World! | ||
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.7\System.Private.CoreLib.dll | ||
|
||
C:\testapps\twooneapp>dotnet --fx-version 2.1.0 bin\Debug\netcoreapp2.1\twooneapp.dll | ||
Hello World! | ||
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.0\System.Private.CoreLib.dll | ||
``` | ||
|
||
The `--fx-version` argument can be composed with the new `RollForward` settings, either via CLI or ENV. By default, `--fx-version` does not roll-forward. | ||
|
||
The following example enables a .NET Core 2.1 application to run on .NET Core 2.2 without having to select the correct 2.2 patch version. In this case `--fx-version` specifies the floor version. In this scenario, 2.2.0 is not on the machine, but a later patch version is. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Earlier a project (.csproj/.vbproj) setting was proposed. It's not mentioned here in precedence. Is that because it rolls into the runtimeconfig? Cool, but we should mention it I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes. Project values have no meaning at runtime since (in most cases) it no longer exists as an accessible artifact. I will add a note for that. |
||
```console | ||
C:\testapps\twooneapp>dotnet --fx-version 2.2.0 bin\Debug\netcoreapp2.1\twooneapp.dll | ||
It was not possible to find any compatible framework version | ||
The specified framework 'Microsoft.NETCore.App', version '2.2.0' was not found. | ||
|
||
C:\testapps\twooneapp>dotnet --fx-version 2.2.0 --roll-forward Patch bin\Debug\netcoreapp2.1\twooneapp.dll | ||
Hello World! | ||
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.3\System.Private.CoreLib.dll | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the overall outcome of this. The only confusion might arise when all the different ways to specify these settings is combined. If specified on command line together like this, it makes perfect sense. If the I'm not sure if it's OK to leave it like that, or if there's something we should do... and I don't know what... just raising a concern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a concern. The order of precedence for command line and ENV is really tough. Here are two scenarios to consider (where both CLI and ENV config is used):
I now think I have it wrong. I think most people expect that the CLI would beat config in the second case. That said, I do think that the ENV needs to be honored in the first example to enable hosters to have control over a large number of apps. |
||
``` | ||
|
||
### Configuration Precedence | ||
|
||
The host will consult the various ways of setting `RollForward`, in order (later scopes take precendence over earlier ones): | ||
|
||
1. `.runtimeconfig.json` properties (AKA "json") | ||
2. CLI arguments | ||
3. Environment variables (AKA "ENV") | ||
C:\testapps\twooneapp>SET DOTNET_ROLL_FORWARD=LatestMajor | ||
|
||
Note: The project file property is not listed because the project file is a build-time not runtime artifact. Runtime-oriented values in project files need to be written to `.runtimeconfig.json` as part of the build in order to influence runtime behavior. | ||
|
||
The `version` and `roll-forward` settings compose in the following way: | ||
|
||
* A `version` setting at higher precedent scopes overwrites both the `version` and `roll-forward` values at lower scopes. For example, `version` specified at the CLI scope (with `--fx-version`) overwrites both a `version` and `roll-forward` setting that might exist at the json scope. | ||
* A `version` setting can flow to higher scopes if it is not replaced by another `version` value. This enables a `roll-forward` setting at a higher scope to compose with a `version` setting at a lower scope. | ||
* The absense of a `version` value is an error when the `roll-forward` value of `Patch`, `Minor`, `Major` or `AlwaysLatestMinor` is set since the initial version state is not available. It is not an error when the `roll-forward` value of `AlwaysLatestMajor` is set since an initial version state is not meaningful. | ||
C:\testapps\twooneapp>dotnet bin\Debug\netcoreapp2.1\twooneapp.dll | ||
Hello World! | ||
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\4.2.1\System.Private.CoreLib.dll | ||
|
||
More generally: | ||
C:\testapps\twooneapp>dotnet --fx-version 2.2.0 bin\Debug\netcoreapp2.1\twooneapp.dll | ||
It was not possible to find any compatible framework version | ||
The specified framework 'Microsoft.NETCore.App', version '2.2.0' was not found. | ||
|
||
* The `version` value establishes a floor for roll-forward behavior, except `AlwaysLatestMajor`. | ||
* The default `roll-forward` setting is `Minor` except when `--fx-version` is specified when it is `None`. | ||
C:\testapps\twooneapp>dotnet --fx-version 2.2.0 --roll-forward Patch bin\Debug\netcoreapp2.1\twooneapp.dll | ||
Hello World! | ||
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.3\System.Private.CoreLib.dll | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a copy paste error - the sentence seem to end too early.