Showed the .NET runtime and SDK actually in use on the information page

This commit is contained in:
Thorsten Sommer committed 2026-11-01 14:20:50 +01:00
1 parent 96d34e55b6
commit 8e8d1999d9
5 files changed
+105 -11

No files matched your search

@@ -122,13 +122,26 @@
<ReadLinesFromFile File="../../metadata.txt">
<Output TaskParameter="Lines" PropertyName="Metadata" />
</ReadLinesFromFile>
<!--
metadata.txt names the .NET SDK which the pipeline pins, but a local build may use another
one. Hence, we take the SDK which builds right now. Its .version file starts with the commit
it was built from. The .NET runtime is not recorded at all: the app asks for it while it runs.
-->
<PropertyGroup>
<DotnetSdkVersionFile>$(NetCoreRoot)sdk/$(NETCoreSdkVersion)/.version</DotnetSdkVersionFile>
</PropertyGroup>
<ReadLinesFromFile File="$(DotnetSdkVersionFile)" Condition="Exists('$(DotnetSdkVersionFile)')">
<Output TaskParameter="Lines" PropertyName="DotnetSdkVersionLines" />
</ReadLinesFromFile>
<PropertyGroup>
<MetaVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 0 ])</MetaVersion>
<MetaBuildTime>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 1 ])</MetaBuildTime>
<MetaBuild>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 2 ])</MetaBuild>
<MetaDotnetSdkVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 3 ])</MetaDotnetSdkVersion>
<MetaDotnetVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 4 ])</MetaDotnetVersion>
<MetaDotnetSdkVersion Condition="'$(DotnetSdkVersionLines)' != ''">$(NETCoreSdkVersion) (commit $([System.String]::Copy( $(DotnetSdkVersionLines) ).Split( ';' )[ 0 ].Substring( 0, 10 )))</MetaDotnetSdkVersion>
<MetaRustVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 5 ])</MetaRustVersion>
<MetaMudBlazorVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 6 ])</MetaMudBlazorVersion>
<MetaTauriVersion>$([System.String]::Copy( $(Metadata) ).Split( ';' )[ 7 ])</MetaTauriVersion>
@@ -157,11 +170,10 @@
<_Parameter3>$(MetaBuild)</_Parameter3>
<_Parameter3_TypeName>System.UInt32</_Parameter3_TypeName>
<_Parameter4>$(MetaDotnetSdkVersion)</_Parameter4>
<_Parameter5>$(MetaDotnetVersion)</_Parameter5>
<_Parameter6>$(MetaRustVersion)</_Parameter6>
<_Parameter7>$(MetaMudBlazorVersion)</_Parameter7>
<_Parameter8>$(MetaTauriVersion)</_Parameter8>
<_Parameter9>$(MetaAppCommitHash)</_Parameter9>
<_Parameter5>$(MetaRustVersion)</_Parameter5>
<_Parameter6>$(MetaMudBlazorVersion)</_Parameter6>
<_Parameter7>$(MetaTauriVersion)</_Parameter7>
<_Parameter8>$(MetaAppCommitHash)</_Parameter8>
</AssemblyAttribute>
<AssemblyAttribute Include="AIStudio.Tools.Metadata.MetaDataArchitecture">
<_Parameter1>$(MetaArchitecture)</_Parameter1>
@@ -89,7 +89,7 @@ public partial class Information : MSGComponentBase
private string VersionRust => $"{T("Used Rust compiler")}: v{META_DATA.RustVersion}";
private string VersionDotnetRuntime => $"{T("Used .NET runtime")}: v{META_DATA.DotnetVersion}";
private string VersionDotnetRuntime => $"{T("Used .NET runtime")}: v{DotnetRuntimeVersion.Current}";
private string VersionDotnetSdk => $"{T("Used .NET SDK")}: v{META_DATA.DotnetSdkVersion}";
@@ -0,0 +1,41 @@
using System.Reflection;
namespace AIStudio.Tools.Metadata;
/// <summary>
/// The .NET runtime which runs the app.
/// </summary>
/// <remarks>
/// Asked while the app runs instead of taken from metadata.txt: a release brings its own runtime,
/// and a development build runs on whichever runtime the developer installed.
/// </remarks>
public static class DotnetRuntimeVersion
{
/// <summary>
/// How many characters of the commit we show, as metadata.txt does.
/// </summary>
private const int COMMIT_LENGTH = 10;
/// <summary>
/// Gets the version of the runtime together with the commit it was built from, such as
/// <c>10.0.14 (commit 0427b9abbe)</c>.
/// </summary>
public static string Current { get; } = Describe(Environment.Version, typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion);
/// <summary>
/// Describes a version of the runtime together with the commit which the informational version
/// of its core library names after a plus sign, such as <c>10.0.14+0427b9abbead3f…</c>.
/// </summary>
/// <param name="version">The version of the runtime.</param>
/// <param name="informationalVersion">The informational version of the core library, if any.</param>
/// <returns>The version with its commit, or the version alone when the commit is unknown.</returns>
internal static string Describe(Version version, string? informationalVersion)
{
if (string.IsNullOrWhiteSpace(informationalVersion))
return version.ToString();
var plusIndex = informationalVersion.IndexOf('+');
var commit = plusIndex < 0 ? string.Empty : informationalVersion[(plusIndex + 1)..];
return commit.Length < COMMIT_LENGTH ? version.ToString() : $"{version} (commit {commit[..COMMIT_LENGTH]})";
}
}
@@ -7,7 +7,6 @@ public class MetaDataAttribute(
string buildTime,
uint buildNum,
string dotnetSdkVersion,
string dotnetVersion,
string rustVersion,
string mudBlazorVersion,
string tauriVersion,
@@ -20,8 +19,9 @@ public class MetaDataAttribute(
public uint BuildNum => buildNum;
public string DotnetVersion => dotnetVersion;
/// <summary>
/// Gets the .NET SDK which built the app. The .NET runtime which runs it is <see cref="DotnetRuntimeVersion.Current"/>.
/// </summary>
public string DotnetSdkVersion => dotnetSdkVersion;
public string RustVersion => rustVersion;
@@ -0,0 +1,41 @@
using System.Reflection;
using AIStudio.Tools.Metadata;
namespace AIStudio.Tests.Tools.Metadata;
/// <summary>
/// Checks the versions of .NET which the information page shows.
/// </summary>
/// <remarks>
/// The page names the runtime which runs the app and the SDK which built it, each with the commit it
/// was built from. Both may differ from what metadata.txt says: a release brings its own runtime, a
/// development build runs on whatever is installed, and a local build may use another SDK than the
/// pipeline.
/// </remarks>
[TestFixture]
public sealed class DotnetVersionTests
{
private const string VERSION_WITH_COMMIT = @"^\d+\.\d+\.\d+\S* \(commit [0-9a-f]{10}\)$";
[TestCase("10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa", ExpectedResult = "10.0.14 (commit 0427b9abbe)", TestName = "A runtime with its commit")]
[TestCase("10.0.0-rc.2.25502.107+89c8f6a112d37d2ea8b77821e56d170a1bccdc5a", ExpectedResult = "10.0.14 (commit 89c8f6a112)", TestName = "A runtime whose informational version has a label")]
[TestCase("10.0.14", ExpectedResult = "10.0.14", TestName = "A runtime without a commit")]
[TestCase("10.0.14+0427b9", ExpectedResult = "10.0.14", TestName = "A runtime with a cut-off commit")]
[TestCase("", ExpectedResult = "10.0.14", TestName = "A runtime without an informational version")]
[TestCase(null, ExpectedResult = "10.0.14", TestName = "A runtime whose core library names no version")]
public string TheRuntimeIsDescribedWithItsCommit(string? informationalVersion) => DotnetRuntimeVersion.Describe(new Version(10, 0, 14), informationalVersion);
[Test]
public void TheRuntimeIsTheOneRunningTheApp()
{
Assert.That(DotnetRuntimeVersion.Current, Does.StartWith($"{Environment.Version} ").And.Match(VERSION_WITH_COMMIT));
}
[Test]
public void TheSdkIsNamedWithItsCommit()
{
var metaData = typeof(DotnetRuntimeVersion).Assembly.GetCustomAttribute<MetaDataAttribute>();
Assert.That(metaData?.DotnetSdkVersion, Does.Match(VERSION_WITH_COMMIT));
}
}