Skip to content
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

Support tracking feature channels (#186) #187

Merged
merged 1 commit into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions src/dnvm/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public static class Channels
{
public static string GetDesc(this Channel c) => c switch
{
Channel.Versioned v => $"The latest version in the {v} support channel",
Channel.VersionedMajorMinor v => $"The latest version in the {v} support channel",
Channel.VersionedFeature v => $"The latest version in the {v} support channel",
Channel.Lts => "The latest version in Long-Term support",
Channel.Sts => "The latest version in Short-Term support",
Channel.Latest => "The latest supported version from either the LTS or STS support channels.",
Expand All @@ -30,7 +31,12 @@ private Channel() { }
/// <summary>
/// A major-minor versioned channel.
/// </summary>
public sealed partial record Versioned(int Major, int Minor) : Channel;
public sealed partial record VersionedMajorMinor(int Major, int Minor) : Channel;
/// <summary>
/// A major-minor-patch versioned channel.
/// </summary>
/// <param name="FeatureLevel"> The feature level of the version, e.g. 1 in 9.0.100</param>
public sealed partial record VersionedFeature(int Major, int Minor, int FeatureLevel) : Channel;
/// <summary>
/// Newest Long Term Support release.
/// </summary>
Expand Down Expand Up @@ -67,10 +73,14 @@ void ISerialize<Channel>.Serialize(Channel channel, ISerializer serializer)
=> serializer.SerializeString(channel.GetLowerName());
}

partial record Versioned
partial record VersionedMajorMinor
{
public override string GetDisplayName() => $"{Major}.{Minor}";
}
partial record VersionedFeature
{
public override string GetDisplayName() => $"{Major}.{Minor}.{FeatureLevel}xx";
}
partial record Lts : Channel
{
public override string GetDisplayName() => "LTS";
Expand Down Expand Up @@ -103,13 +113,24 @@ public static Channel FromString(string str)
case "preview": return new Preview();
default:
var components = str.Split('.');
if (components.Length != 2)
switch (components)
{
throw new DeserializeException($"Invalid channel version: {str}");
case [_, _]:
var major = int.Parse(components[0]);
var minor = int.Parse(components[1]);
return new VersionedMajorMinor(major, minor);
case [_, _, _]:
if (components[2] is not [<= '9' and >= '0', 'x', 'x'])
{
throw new DeserializeException($"Feature band must be 3 characters and end in 'xx': {str}");
}
major = int.Parse(components[0]);
minor = int.Parse(components[1]);
var featureLevel = components[2][0] - '0';
return new VersionedFeature(major, minor, featureLevel);
default:
throw new DeserializeException($"Invalid channel version: {str}");
}
var major = int.Parse(components[0]);
var minor = int.Parse(components[1]);
return new Versioned(major, minor);
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/dnvm/DotnetReleasesIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ await CancelScope.WithTimeoutAfter(DnvmEnv.DefaultTimeout,
or (Channel.Sts, "active", "sts")
or (Channel.Preview, "go-live", _)
or (Channel.Preview, "preview", _) => true,
(Channel.Versioned v, _, _) when v.ToString() == releaseVersion.ToMajorMinor() => true,
(Channel.VersionedMajorMinor v, _, _) when v.ToString() == releaseVersion.ToMajorMinor() => true,
(Channel.VersionedFeature v, _, _) when v.ToString() == releaseVersion.ToFeature() => true,
_ => false
};
if (found &&
Expand Down Expand Up @@ -163,4 +164,4 @@ public partial record File
public required string Rid { get; init; }
public string? Hash { get; init; } = null;
}
}
}
4 changes: 2 additions & 2 deletions src/dnvm/InstallCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static async Task<Result> Run(DnvmEnv env, Logger logger, CommandArgument
}

var sdkVersion = options.SdkVersion;
var channel = new Channel.Versioned(sdkVersion.Major, sdkVersion.Minor);
var channel = new Channel.VersionedMajorMinor(sdkVersion.Major, sdkVersion.Minor);

if (!options.Force && manifest.InstalledSdks.Any(s => s.SdkVersion == sdkVersion && s.SdkDirName == sdkDir))
{
Expand Down Expand Up @@ -351,4 +351,4 @@ @echo off
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/dnvm/TrackCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ internal static async Task<Result> InstallLatestFromChannel(
// 2. The channel is supported but there are currently no builds available
// We want to provide a helpful error message about the first case, but let the second
// case go through without attempting to install anything.
if (channel is Channel.Versioned)
if (channel is Channel.VersionedMajorMinor or Channel.VersionedFeature)
{
logger.Error($"Could not find channel '{channel}' in the dotnet releases index.");
return Result.UnknownChannel;
Expand Down
13 changes: 12 additions & 1 deletion src/dnvm/Utilities/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ public static void ChmodExec(IFileSystem vfs, UPath upath)

public static string ToMajorMinor(this SemVersion version) => $"{version.Major}.{version.Minor}";

public static string ToFeature(this SemVersion version)
{
int feature = version.Patch;
while (feature >= 10)
{
feature /= 10;
}

return $"{version.Major}.{version.Minor}.{feature}xx";
}

public static string SeqToString<T>(this IEnumerable<T> e)
{
return "[ " + string.Join(", ", e) + " ]";
Expand Down Expand Up @@ -337,4 +348,4 @@ public override string ToString()
Libc.Musl => string.Join('-', os, arch, "musl")
};
}
}
}
25 changes: 21 additions & 4 deletions test/UnitTests/CommandLineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,33 @@ public void TrackMajorMinor()
"99.99"
]);
Assert.True(options!.Command is CommandArguments.TrackArguments {
Channel: Channel.Versioned { Major: 99, Minor: 99 }
Channel: Channel.VersionedMajorMinor { Major: 99, Minor: 99 }
});
}

[Fact]
public void TrackBadChannel()
public void TrackFeature()
{
var options = CommandLineArguments.ParseRaw(new TestConsole(), [
"track",
"99.99.9xx"
]);
Assert.True(options!.Command is CommandArguments.TrackArguments {
Channel: Channel.VersionedFeature { Major: 99, Minor: 99, FeatureLevel: 9 }
});
}

[Theory]
[InlineData("badchannel")]
[InlineData("99.99.9x")]
[InlineData("99.99.9xxx")]
[InlineData("99.99.900")]
[InlineData("99.99.axx")]
public void TrackBadChannel(string channel)
{
var ex = Assert.Throws<ArgumentSyntaxException>(() => CommandLineArguments.ParseRaw(new TestConsole(), [
"track",
"badversion"
channel
]));
var tab = "\t";
Assert.Equal($"""
Expand Down Expand Up @@ -440,4 +457,4 @@ to the .dotnet folder in the same directory.

""".NormalizeLineEndings(), console.Output.TrimLines());
}
}
}
21 changes: 19 additions & 2 deletions test/UnitTests/TrackTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,24 @@ public Task ChannelOverlap() => RunWithServer(async (server, env) =>
[Fact]
public Task TrackMajorMinor() => RunWithServer(async (server, env) =>
{
var result = await TrackCommand.Run(env, _logger, new() { Channel = new Channel.Versioned(99, 99) });
var result = await TrackCommand.Run(env, _logger, new() { Channel = new Channel.VersionedMajorMinor(99, 99) });
Assert.Equal(TrackCommand.Result.Success, result);

var manifest = await env.ReadManifest();
var version = SemVersion.Parse("99.99.99-preview", SemVersionStyles.Strict);
Assert.Equal([ new() {
ReleaseVersion = version,
SdkVersion = version,
RuntimeVersion = version,
AspNetVersion = version,
SdkDirName = DnvmEnv.DefaultSdkDirName
} ], manifest.InstalledSdks);
});

[Fact]
public Task TrackFeature() => RunWithServer(async (server, env) =>
{
var result = await TrackCommand.Run(env, _logger, new() { Channel = new Channel.VersionedFeature(99, 99, 9) });
Assert.Equal(TrackCommand.Result.Success, result);

var manifest = await env.ReadManifest();
Expand Down Expand Up @@ -219,4 +236,4 @@ public Task TrackNoBuilds() => RunWithServer(async (mockServer, env) =>
InstalledSdkVersions = [ ]
}], manifest.RegisteredChannels);
});
}
}