diff --git a/fallout.slnx b/fallout.slnx index 0f6ae9699..59d5c32e7 100644 --- a/fallout.slnx +++ b/fallout.slnx @@ -9,6 +9,7 @@ + diff --git a/src/Fallout.Common/ChangeLog/ChangeLogTasks.cs b/src/Fallout.Common/ChangeLog/ChangeLogTasks.cs index 473da0562..2d5d0f307 100644 --- a/src/Fallout.Common/ChangeLog/ChangeLogTasks.cs +++ b/src/Fallout.Common/ChangeLog/ChangeLogTasks.cs @@ -12,6 +12,11 @@ // ReSharper disable ArgumentsStyleLiteral namespace Fallout.Common.ChangeLog; +/// +/// Provides a set of tasks and utility methods for working with changelogs in a software repository. +/// This class includes methods for reading, extracting, and finalizing changelog entries, as well as +/// preparing release notes for publishing on platforms such as NuGet. +/// public static class ChangelogTasks { public static string GetNuGetReleaseNotes(string changelogFile, GitRepository repository = null) @@ -150,18 +155,47 @@ public static void FinalizeChangelog(AbsolutePath changelogFile, string tag, Git } /// - /// Extracts the notes of the specified changelog section. + /// Extracts the notes from a specific section of the given changelog file, optionally filtered by a section tag. /// /// The path to the changelog file. - /// The tag which release notes should get extracted. - /// A collection of the release notes. + /// The optional tag to identify the specific section to extract notes from. If null, the first valid section is used. + /// An enumerable collection of strings representing the notes in the specified section. If the file does not exist or the section is not found, an empty collection is returned. public static IEnumerable ExtractChangelogSectionNotes(AbsolutePath changelogFile, string tag = null) { - var content = changelogFile.ReadAllLines().Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); - var sections = GetReleaseSections(content); - var section = tag == null - ? sections.First(x => x.StartIndex < x.EndIndex) - : sections.FirstOrDefault(x => x.Caption.EqualsOrdinalIgnoreCase(tag)).NotNull($"Could not find release section for '{tag}'."); + if (!changelogFile.FileExists()) + { + // We treat a non-existing changelog file as empty. + Log.Information("Changelog file {File} does not exist, so skipping section extraction", changelogFile); + return Array.Empty(); + } + + List content = changelogFile.ReadAllLines().Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + List sections = GetReleaseSections(content).ToList(); + if (!sections.Any()) + { + // We treat an empty changelog as if the section does not exist. + Log.Information("Changelog file {File} doesn't contain any sections, so skipping section extraction", changelogFile); + + return Array.Empty(); + } + + ReleaseSection section; + if (tag == null) + { + section = sections.FirstOrDefault(x => x.StartIndex < x.EndIndex); + if (section == null) + { + return Array.Empty(); + } + } + else + { + section = sections.FirstOrDefault(x => x.Caption.EqualsOrdinalIgnoreCase(tag)); + if (section == null) + { + throw new Exception($"Could not find release section for '{tag}'."); + } + } return content .Skip(section.StartIndex + 1) diff --git a/tests/Fallout.Common.Tests/ChangelogTasksTest.cs b/tests/Fallout.Common.Tests/ChangelogTasksTest.cs index 07e7e718a..f7f639681 100644 --- a/tests/Fallout.Common.Tests/ChangelogTasksTest.cs +++ b/tests/Fallout.Common.Tests/ChangelogTasksTest.cs @@ -28,6 +28,16 @@ public void ExtractChangelogSectionNotes_ChangelogReferenceFile_ThrowsNoExceptio act.Should().NotThrow(); } + [Fact] + public void Extracting_a_changelog_from_a_non_existing_file_returns_an_empty_collection() + { + // Arrange + var file = RootDirectory / "does-not-exist.md"; + + // Act / Assert + ChangelogTasks.ExtractChangelogSectionNotes(file).Should().BeEmpty(); + } + [Fact] public void GetReleaseSections_ChangelogReferenceFileWithoutReleaseHead_ReturnsEmpty() {