diff --git a/src/Distroessed/Program.cs b/src/Distroessed/Program.cs index 290a9fb4..87115fa4 100644 --- a/src/Distroessed/Program.cs +++ b/src/Distroessed/Program.cs @@ -1,5 +1,4 @@ using DotnetRelease; -using EndOfLifeDate; if (args.Length is 0 || !int.TryParse(args[0], out int majorVersion)) { @@ -7,30 +6,18 @@ return; } +string? baseUrl = args.Length > 1 ? args[1] : null; + string version = $"{majorVersion}.0"; -string baseDefaultURL = "https://raw.githubusercontent.com/dotnet/core/main/release-notes/"; -string baseUrl = args.Length > 1 ? args[1] : baseDefaultURL; -bool preferWeb = baseUrl.StartsWith("https"); -HttpClient client= new(); -DateOnly threeMonthsDate = DateOnly.FromDateTime(DateTime.UtcNow.AddMonths(3)); -string supportMatrixUrl, releaseUrl; +string supportMatrixUrl = ReleaseNotes.GetUri(ReleaseNotes.SupportedOS, version, baseUrl); +string releaseUrl = ReleaseNotes.GetUri(ReleaseNotes.Releases, version, baseUrl); +bool preferWeb = supportMatrixUrl.StartsWith("https"); SupportedOSMatrix? matrix = null; MajorReleaseOverview? majorRelease = null; -ReportOverview report = new(DateTime.UtcNow, version, []); - -if (preferWeb) -{ - supportMatrixUrl = $"{baseUrl}/{version}/supported-os.json"; - releaseUrl = $"{baseUrl}/{version}/releases.json"; -} -else -{ - supportMatrixUrl = Path.Combine(baseUrl, version,"supported-os.json"); - releaseUrl = Path.Combine(baseUrl, version,"releases.json"); -} if (preferWeb) { + HttpClient client = new(); matrix = await ReleaseNotes.GetSupportedOSes(client, supportMatrixUrl); majorRelease = await ReleaseNotes.GetMajorRelease(client, releaseUrl); } @@ -40,98 +27,7 @@ majorRelease = await ReleaseNotes.GetMajorRelease(File.OpenRead(releaseUrl)); } -DateOnly initialRelease = majorRelease?.Releases.FirstOrDefault(r => r.ReleaseVersion.Equals($"{majorVersion}.0.0"))?.ReleaseDate ?? DateOnly.MaxValue; -DateOnly eolDate = majorRelease?.EolDate ?? DateOnly.MaxValue; - -foreach (SupportFamily family in matrix?.Families ?? throw new Exception()) -{ - ReportFamily reportFamily = new(family.Name, []); - report.Families.Add(reportFamily); - - foreach (SupportDistribution distro in family.Distributions) - { - IList? cycles; - List activeReleases = []; - List unsupportedActiveRelease = []; - List soonEolReleases = []; - List supportedUnActiveReleases = []; - List missingReleases = []; - - try - { - cycles = await EndOfLifeDate.Product.GetProduct(client, distro.Id); - if (cycles is null) - { - continue; - } - } - catch (HttpRequestException) - { - Console.WriteLine($"No data found at endoflife.date for: {distro.Id}"); - Console.WriteLine(); - continue; - } - - foreach (SupportCycle cycle in cycles) - { - SupportInfo support = cycle.GetSupportInfo(); - // dotnet statements - bool isSupported = distro.SupportedVersions.Contains(cycle.Cycle); - bool isUnsupported = distro.UnsupportedVersions?.Contains(cycle.Cycle) ?? false; - // EndofLife.Date statement - bool isActive = support.IsActive; - bool hasOverlappingLifecycle = initialRelease <= support.EolDate && cycle.ReleaseDate <= eolDate; - - if (isActive) - { - activeReleases.Add(cycle.Cycle); - } - - /* - Cases (EOLDate, dotnet): - 1. (Active, Supported) - 2. (Active, Unsupported) - 3. (OverlappingLifecycle, Unlisted) - 4. (EOL, Supported) - 5. (Active - EolSoon, Supported) - // these are not covered - 6. (Unlisted, Listed) - 7. (EOL, Unsupported | Unlisted) - 8. (Listed, Unlisted) - */ - - // Case 1 - if (isActive && isSupported) - { - // nothing to do - } - // Case 2 - else if (isActive && isUnsupported) - { - unsupportedActiveRelease.Add(cycle.Cycle); - } - // Case 3 - else if (hasOverlappingLifecycle && !isSupported && !isUnsupported) - { - missingReleases.Add(cycle.Cycle); - } - // Case 4 - else if (!isActive && isSupported) - { - supportedUnActiveReleases.Add(cycle.Cycle); - } - - if (isActive && support.EolDate < threeMonthsDate) - { - soonEolReleases.Add(cycle.Cycle); - } - } - - ReportDistribution reportDistribution = new(distro.Name, activeReleases, unsupportedActiveRelease, soonEolReleases, supportedUnActiveReleases, missingReleases); - reportFamily.Distributions.Add(reportDistribution); - } -} - +var report = await ReleaseReportGenerator.GetReportOverviewAsync(matrix, majorRelease); var reportJson = ReleaseReport.WriteReport(report); Console.WriteLine(reportJson); diff --git a/src/Distroessed/distroessed.csproj b/src/Distroessed/distroessed.csproj index 5e907127..8b726785 100644 --- a/src/Distroessed/distroessed.csproj +++ b/src/Distroessed/distroessed.csproj @@ -1,8 +1,7 @@  - - + diff --git a/src/DotnetRelease/PatchReleaseOverviewRecords.cs b/src/DotnetRelease/PatchReleaseOverviewRecords.cs index 8c91d9f1..d6e0c078 100644 --- a/src/DotnetRelease/PatchReleaseOverviewRecords.cs +++ b/src/DotnetRelease/PatchReleaseOverviewRecords.cs @@ -78,6 +78,10 @@ public record RuntimeComponent( JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string VSVersion, + [property: Description("The version of Visual Studio on MacOS that includes this component version."), + JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string VSMacVersion, + [property: Description("The files that are available for this component.")] IList Files, @@ -100,9 +104,15 @@ public record SdkComponent( [property: Description("The version of Visual Studio that includes this component version.")] string VSVersion, + [property: Description("The version of Visual Studio on MacOS that includes this component version.")] + string VSMacVersion, + [property: Description("The minimum version of Visual Studio that supports this component version.")] string VSSupport, + [property: Description("The minimum version of Visual Studio on MacOS that supports this component version.")] + string VSMacSupport, + [property: Description("The version of C# included in the component."), JsonPropertyName("csharp-version")] string CSharpVersion, diff --git a/src/DotnetRelease/ReleaseNotes.cs b/src/DotnetRelease/ReleaseNotes.cs index 06dd8dd4..4b1c5dc8 100644 --- a/src/DotnetRelease/ReleaseNotes.cs +++ b/src/DotnetRelease/ReleaseNotes.cs @@ -19,6 +19,8 @@ public class ReleaseNotes public static string Releases { get; private set; } = "releases.json"; + public static string PatchRelease { get; private set; } = "release.json"; + public static string SupportedOS { get; private set; } = "supported-os.json"; public static string PreviewDirectory { get; private set; } = "preview"; @@ -77,6 +79,14 @@ public static ReleaseName GetReleaseName(string version) return new(name, "preview", true); } } + + public static string GetUri(string fileName, string version, string? baseUri = null) + { + baseUri ??= GitHubBaseUri; + return baseUri.StartsWith("https") + ? $"{baseUri}/{version}/{fileName}" + : Path.Combine(baseUri, version, fileName); + } } public record ReleaseName(string Name, string Folder, bool IsPreview); diff --git a/src/DotnetRelease/ReleaseReportRecords.cs b/src/DotnetRelease/ReleaseReportRecords.cs index 5425c564..956b1f36 100644 --- a/src/DotnetRelease/ReleaseReportRecords.cs +++ b/src/DotnetRelease/ReleaseReportRecords.cs @@ -4,4 +4,4 @@ public record ReportOverview(DateTime Timestamp, string Version, IList Distributions); -public record ReportDistribution(string Name, IList ActiveReleases, IList ActiveReleasesUnsupported, IList ActiveReleasesEOLSoon, IList NotActiveReleasesSupported, IList ReleasesMissing); +public record ReportDistribution(string Name, IList ActiveReleases, IList ActiveReleasesUnsupported, IList ActiveReleasesEOLSoon, IList NotActiveReleasesSupported, IList NotActiveReleasesUnsupported, IList ReleasesMissing); diff --git a/src/DotnetRelease/SerializerContext.cs b/src/DotnetRelease/SerializerContext.cs index 888476fd..6217821f 100644 --- a/src/DotnetRelease/SerializerContext.cs +++ b/src/DotnetRelease/SerializerContext.cs @@ -1,4 +1,3 @@ -using System.Text.Json; using System.Text.Json.Serialization; namespace DotnetRelease; diff --git a/src/DotnetRelease/SupportedOS.cs b/src/DotnetRelease/SupportedOS.cs index 6cc53eb6..53777cad 100644 --- a/src/DotnetRelease/SupportedOS.cs +++ b/src/DotnetRelease/SupportedOS.cs @@ -1,7 +1,3 @@ -using System.Net.Http.Json; -using System.Text.Json; -using System.Text.Json.Serialization; - namespace DotnetRelease; public class SupportedOS diff --git a/src/LinuxPackagesMd/Program.cs b/src/LinuxPackagesMd/Program.cs index 33a8f0b1..3b086d8f 100644 --- a/src/LinuxPackagesMd/Program.cs +++ b/src/LinuxPackagesMd/Program.cs @@ -18,9 +18,7 @@ if (!packageJson.EndsWith(".json")) { - packageJson = preferWeb ? - $"{baseUrl}/{version}/os-packages.json" : - Path.Combine(baseUrl, version,"os-packages.json"); + packageJson = ReleaseNotes.GetUri(ReleaseNotes.OSPackages, version, baseUrl); } string file = "os-packages.md"; diff --git a/src/MarkdownHelpers/BreakBuffer.cs b/src/MarkdownHelpers/BreakBuffer.cs index a1c61b0c..c1627637 100644 --- a/src/MarkdownHelpers/BreakBuffer.cs +++ b/src/MarkdownHelpers/BreakBuffer.cs @@ -4,7 +4,7 @@ namespace MarkdownHelpers; public class BreakBuffer(StringBuilder builder, int index = 0) { - StringBuilder _builder = builder; + readonly StringBuilder _builder = builder; int _index = index; public void Append(string value) diff --git a/src/MarkdownHelpers/Link.cs b/src/MarkdownHelpers/Link.cs index 0d57ceef..12d83526 100644 --- a/src/MarkdownHelpers/Link.cs +++ b/src/MarkdownHelpers/Link.cs @@ -1,5 +1,3 @@ -using System.Collections.Specialized; - namespace MarkdownHelpers; public class Link(int startingIndex = 0) diff --git a/src/MarkdownHelpers/Table.cs b/src/MarkdownHelpers/Table.cs index 8ca49425..2a79bedc 100644 --- a/src/MarkdownHelpers/Table.cs +++ b/src/MarkdownHelpers/Table.cs @@ -1,15 +1,9 @@ -using System.ComponentModel.DataAnnotations.Schema; -using System.Data.Common; -using System.IO.Compression; -using System.Text; -using Microsoft.VisualBasic.FileIO; - namespace MarkdownHelpers; public class Table(IWriter writer, int[] columns) { private readonly IWriter _writer = writer; - private int[] _columns = columns; + private readonly int[] _columns = columns; private readonly int _columnMax = columns.Length - 1; private int _column = 0; private int _realLength = 0; diff --git a/src/ReleaseReport/ReleaseReport.csproj b/src/ReleaseReport/ReleaseReport.csproj new file mode 100644 index 00000000..5f8f906b --- /dev/null +++ b/src/ReleaseReport/ReleaseReport.csproj @@ -0,0 +1,14 @@ + + + + + + + + + net8.0 + enable + enable + + + diff --git a/src/ReleaseReport/ReleaseReportGenerator.cs b/src/ReleaseReport/ReleaseReportGenerator.cs new file mode 100644 index 00000000..5489eccc --- /dev/null +++ b/src/ReleaseReport/ReleaseReportGenerator.cs @@ -0,0 +1,116 @@ +using DotnetRelease; +using EndOfLifeDate; + +public class ReleaseReportGenerator +{ + public static async Task GetReportOverviewAsync(SupportedOSMatrix? matrix, MajorReleaseOverview? majorRelease) + { + string version = matrix?.ChannelVersion + ?? majorRelease?.ChannelVersion + ?? "0.0"; + HttpClient client = new(); + DateOnly threeMonthsDate = DateOnly.FromDateTime(DateTime.UtcNow.AddMonths(3)); + DateOnly initialRelease = majorRelease?.Releases.FirstOrDefault(r => r.ReleaseVersion.Equals($"{version}.0"))?.ReleaseDate ?? DateOnly.MaxValue; + DateOnly eolDate = majorRelease?.EolDate ?? DateOnly.MaxValue; + ReportOverview report = new(DateTime.UtcNow, version, []); + + foreach (SupportFamily family in matrix?.Families ?? throw new Exception()) + { + ReportFamily reportFamily = new(family.Name, []); + report.Families.Add(reportFamily); + + foreach (SupportDistribution distro in family.Distributions) + { + IList? cycles; + List activeReleases = []; + List unsupportedActiveRelease = []; + List soonEolReleases = []; + List supportedUnActiveReleases = []; + List unsupportedUnActiveReleases = []; + List missingReleases = []; + + try + { + cycles = await EndOfLifeDate.Product.GetProduct(client, distro.Id); + if (cycles is null) + { + continue; + } + } + catch (HttpRequestException) + { + Console.WriteLine($"No data found at endoflife.date for: {distro.Id}"); + Console.WriteLine(); + continue; + } + + foreach (SupportCycle cycle in cycles) + { + SupportInfo support = cycle.GetSupportInfo(); + // dotnet statements + bool isSupported = distro.SupportedVersions.Contains(cycle.Cycle); + bool isUnsupported = distro.UnsupportedVersions?.Contains(cycle.Cycle) ?? false; + // EndofLife.Date statement + bool isActive = support.IsActive; + bool hasOverlappingLifecycle = initialRelease <= support.EolDate && cycle.ReleaseDate <= eolDate; + + if (isActive) + { + activeReleases.Add(cycle.Cycle); + } + + /* + Cases (EOLDate, dotnet): + 1. (Active, Supported) + 2. (Active, Unsupported) + 3. (OverlappingLifecycle, Unlisted) + 4. (EOL, Supported) + 5. (EOL, Unsupported) + 6. (Active - EolSoon, Supported) + // these are not covered + 7. (Listed, Unlisted) + 8. (EOL, Unlisted) + 9. (Unlisted, Listed) + */ + + // Case 1 + if (isActive && isSupported) + { + // nothing to do + } + // Case 2 + else if (isActive && isUnsupported) + { + unsupportedActiveRelease.Add(cycle.Cycle); + } + // Case 3 + else if (hasOverlappingLifecycle && !isSupported && !isUnsupported) + { + missingReleases.Add(cycle.Cycle); + } + // Case 4 + else if (!isActive && isSupported) + { + supportedUnActiveReleases.Add(cycle.Cycle); + } + // Case 5 + else if (!isActive && isUnsupported) + { + unsupportedUnActiveReleases.Add(cycle.Cycle); + } + + // Case 6 + if (isActive && support.EolDate < threeMonthsDate) + { + soonEolReleases.Add(cycle.Cycle); + } + } + + ReportDistribution reportDistribution = new(distro.Name, activeReleases, unsupportedActiveRelease, soonEolReleases, supportedUnActiveReleases, unsupportedUnActiveReleases, missingReleases); + reportFamily.Distributions.Add(reportDistribution); + } + } + + return report; + } +} diff --git a/src/SupportedOsMd/Program.cs b/src/SupportedOsMd/Program.cs index 9efeaf30..765aa9a2 100644 --- a/src/SupportedOsMd/Program.cs +++ b/src/SupportedOsMd/Program.cs @@ -9,16 +9,12 @@ } string version = $"{ver}.0"; -string baseDefaultURL = "https://raw.githubusercontent.com/dotnet/core/main/release-notes/"; -string baseUrl = args.Length > 1 ? args[1] : baseDefaultURL; -bool preferWeb = baseUrl.StartsWith("https"); -string supportJson = baseUrl; +string? baseUrl = args.Length > 1 ? args[1] : null; +string supportJson = baseUrl ?? string.Empty; if (!supportJson.EndsWith(".json")) { - supportJson = preferWeb ? - $"{baseUrl}/{version}/supported-os.json" : - Path.Combine(baseUrl, version,"supported-os.json"); + supportJson = ReleaseNotes.GetUri(ReleaseNotes.SupportedOS, version, baseUrl); } string template = $"supported-os-template{ver}.md"; @@ -29,6 +25,7 @@ StreamWriter writer = new(stream); SupportedOSMatrix? matrix = null; Link pageLinks = new(); +bool preferWeb = supportJson.StartsWith("https"); if (preferWeb) { diff --git a/src/Test/Program.cs b/src/Test/Program.cs index de969b75..943ffcca 100644 --- a/src/Test/Program.cs +++ b/src/Test/Program.cs @@ -10,4 +10,4 @@ } var json = JsonSerializer.Serialize(releases, MajorReleaseOverviewSerializerContext.Default.MajorReleaseOverview); -File.WriteAllText("releases.json", json); +File.WriteAllText(ReleaseNotes.Releases, json); diff --git a/src/UpdateReleasesIndex/Program.cs b/src/UpdateReleasesIndex/Program.cs index 5c9708b4..d154c155 100644 --- a/src/UpdateReleasesIndex/Program.cs +++ b/src/UpdateReleasesIndex/Program.cs @@ -1,8 +1,4 @@ -using System.ComponentModel.Design; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices.Marshalling; -using System.Text.Json; -using System.Text.Json.Nodes; +using System.Text.Json; using DotnetRelease; const string majorReleaseFile = "releases.json"; @@ -64,7 +60,7 @@ static void ProcessMajorRelease(MajorReleaseOverview majorReleaseOverview, strin continue; } var releaseJsonUrl = $"{ReleaseNotes.OfficialBaseUri}{channelVersion}/{folder}/{patchReleaseFile}"; - string patchReleaseJson = Path.Combine(dir, folder, "release.json"); + string patchReleaseJson = Path.Combine(dir, folder, ReleaseNotes.PatchRelease); var patchReleaseOverview = new PatchReleaseOverview( channelVersion, @@ -95,7 +91,7 @@ static void ProcessMajorRelease(MajorReleaseOverview majorReleaseOverview, strin majorReleaseOverview.OsPackagesInfoUri, patchReleases); - string patchReleasesIndexJson = Path.Combine(dir, "patch-releases-index.json"); + string patchReleasesIndexJson = Path.Combine(dir, ReleaseNotes.PatchReleasesIndex); WritePatchReleasesIndex(index, patchReleasesIndexJson); } diff --git a/src/src.sln b/src/src.sln index ca4f2a47..223e2365 100644 --- a/src/src.sln +++ b/src/src.sln @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateReleasesIndex", "UpdateReleasesIndex\UpdateReleasesIndex.csproj", "{1CC51404-5AB9-49BA-8BE7-6263259F02E9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReleaseReport", "ReleaseReport\ReleaseReport.csproj", "{0A34777F-E4DC-4E37-A2CF-4B2110B60B47}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,10 @@ Global {1CC51404-5AB9-49BA-8BE7-6263259F02E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {1CC51404-5AB9-49BA-8BE7-6263259F02E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {1CC51404-5AB9-49BA-8BE7-6263259F02E9}.Release|Any CPU.Build.0 = Release|Any CPU + {0A34777F-E4DC-4E37-A2CF-4B2110B60B47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0A34777F-E4DC-4E37-A2CF-4B2110B60B47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0A34777F-E4DC-4E37-A2CF-4B2110B60B47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0A34777F-E4DC-4E37-A2CF-4B2110B60B47}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE