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

Extract release report #7

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
118 changes: 7 additions & 111 deletions src/Distroessed/Program.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
using DotnetRelease;
using EndOfLifeDate;

if (args.Length is 0 || !int.TryParse(args[0], out int majorVersion))
{
ReportInvalidArgs();
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);
}
Expand All @@ -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<SupportCycle>? cycles;
List<string> activeReleases = [];
List<string> unsupportedActiveRelease = [];
List<string> soonEolReleases = [];
List<string> supportedUnActiveReleases = [];
List<string> 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);
Expand Down
3 changes: 1 addition & 2 deletions src/Distroessed/distroessed.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\DotnetRelease\DotnetRelease.csproj" />
<ProjectReference Include="..\EndOfLifeDate\EndOfLifeDate.csproj" />
<ProjectReference Include="..\ReleaseReport\ReleaseReport.csproj" />
</ItemGroup>

<PropertyGroup>
Expand Down
10 changes: 10 additions & 0 deletions src/DotnetRelease/PatchReleaseOverviewRecords.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ComponentFile> Files,

Expand All @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions src/DotnetRelease/ReleaseNotes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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);
2 changes: 1 addition & 1 deletion src/DotnetRelease/ReleaseReportRecords.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ public record ReportOverview(DateTime Timestamp, string Version, IList<ReportFam

public record ReportFamily(string Name, IList<ReportDistribution> Distributions);

public record ReportDistribution(string Name, IList<string> ActiveReleases, IList<string> ActiveReleasesUnsupported, IList<string> ActiveReleasesEOLSoon, IList<string> NotActiveReleasesSupported, IList<string> ReleasesMissing);
public record ReportDistribution(string Name, IList<string> ActiveReleases, IList<string> ActiveReleasesUnsupported, IList<string> ActiveReleasesEOLSoon, IList<string> NotActiveReleasesSupported, IList<string> NotActiveReleasesUnsupported, IList<string> ReleasesMissing);
4 changes: 1 addition & 3 deletions src/LinuxPackagesMd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
14 changes: 14 additions & 0 deletions src/ReleaseReport/ReleaseReport.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\DotnetRelease\DotnetRelease.csproj" />
<ProjectReference Include="..\EndOfLifeDate\EndOfLifeDate.csproj" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
115 changes: 115 additions & 0 deletions src/ReleaseReport/ReleaseReportGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using DotnetRelease;
using EndOfLifeDate;

public class ReleaseReportGenerator
{
public static async Task<ReportOverview> 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<SupportCycle>? cycles;
List<string> activeReleases = [];
List<string> unsupportedActiveRelease = [];
List<string> soonEolReleases = [];
List<string> supportedUnActiveReleases = [];
List<string> unsupportedUnActiveReleases = [];
List<string> 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)
6. (EOL, Unsupported | Unlisted)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having that case would allow me to check for former supported versions and adding them to a table. That's the only thing that was blocking me from using this report directly and needing to duplicate the whole logic.

// these are not covered
7. (Listed, Unlisted)
8. (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 6
else if (!isActive && !isSupported)
{
unsupportedUnActiveReleases.Add(cycle.Cycle);
}

// Case 5
if (isActive && support.EolDate < threeMonthsDate)
{
soonEolReleases.Add(cycle.Cycle);
}
}

ReportDistribution reportDistribution = new(distro.Name, activeReleases, unsupportedActiveRelease, soonEolReleases, supportedUnActiveReleases, missingReleases);
reportFamily.Distributions.Add(reportDistribution);
}
}

return report;
}
}
11 changes: 4 additions & 7 deletions src/SupportedOsMd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -29,6 +25,7 @@
StreamWriter writer = new(stream);
SupportedOSMatrix? matrix = null;
Link pageLinks = new();
bool preferWeb = supportJson.StartsWith("https");

if (preferWeb)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Test/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
}

var json = JsonSerializer.Serialize(releases, MajorReleaseOverviewSerializerContext.Default.MajorReleaseOverview);
File.WriteAllText("releases.json", json);
File.WriteAllText(ReleaseNotes.Releases, json);
Loading