Skip to content
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
46 changes: 32 additions & 14 deletions src/DemaConsulting.BuildMark/BuildInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,19 @@
/// <summary>
/// Represents build information for a release.
/// </summary>
/// <param name="FromVersion">Starting version (null if from beginning of history).</param>
/// <param name="ToVersion">Ending version.</param>
/// <param name="FromHash">Starting git hash (null if from beginning of history).</param>
/// <param name="ToHash">Ending git hash.</param>
/// <param name="BaselineVersionTag">Starting version tag (null if from beginning of history).</param>
/// <param name="CurrentVersionTag">Ending version tag.</param>
/// <param name="Changes">Non-bug changes performed between versions.</param>
/// <param name="Bugs">Bugs fixed between versions.</param>
/// <param name="KnownIssues">Known issues (unfixed or fixed but not in this build).</param>
/// <param name="CompleteChangelogLink">Optional link to the full changelog (null if not available).</param>
public record BuildInformation(
Version? FromVersion,
Version ToVersion,
string? FromHash,
string ToHash,
VersionTag? BaselineVersionTag,
VersionTag CurrentVersionTag,
List<ItemInfo> Changes,
List<ItemInfo> Bugs,
List<ItemInfo> KnownIssues)
List<ItemInfo> KnownIssues,
WebLink? CompleteChangelogLink)
{
/// <summary>
/// Generates a Markdown build report from this build information.
Expand Down Expand Up @@ -73,6 +71,12 @@
AppendKnownIssuesSection(markdown, subHeading);
}

// Add full changelog section if link is available
if (CompleteChangelogLink != null)
{
AppendCompleteChangelogSection(markdown, subHeading);
}

// Return the complete markdown report
return markdown.ToString();
}
Expand All @@ -88,15 +92,15 @@
markdown.AppendLine($"{subHeading} Version Information");
markdown.AppendLine();
markdown.AppendLine("| Field | Value |");
markdown.AppendLine("|-------|-------|");

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build windows-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)

Check warning on line 95 in src/DemaConsulting.BuildMark/BuildInformation.cs

View workflow job for this annotation

GitHub Actions / Build / Build ubuntu-latest

Define a constant instead of using this literal '|-------|-------|' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)
markdown.AppendLine($"| **Version** | {ToVersion.Tag} |");
markdown.AppendLine($"| **Commit Hash** | {ToHash} |");
markdown.AppendLine($"| **Version** | {CurrentVersionTag.VersionInfo.Tag} |");
markdown.AppendLine($"| **Commit Hash** | {CurrentVersionTag.CommitHash} |");

// Add previous version information or N/A if this is the first release
if (FromVersion != null)
if (BaselineVersionTag != null)
{
markdown.AppendLine($"| **Previous Version** | {FromVersion.Tag} |");
markdown.AppendLine($"| **Previous Commit Hash** | {FromHash} |");
markdown.AppendLine($"| **Previous Version** | {BaselineVersionTag.VersionInfo.Tag} |");
markdown.AppendLine($"| **Previous Commit Hash** | {BaselineVersionTag.CommitHash} |");
}
else
{
Expand Down Expand Up @@ -197,4 +201,18 @@
// Add blank line after section
markdown.AppendLine();
}

/// <summary>
/// Appends the full changelog section to the markdown report.
/// </summary>
/// <param name="markdown">StringBuilder containing the markdown report.</param>
/// <param name="subHeading">Sub-heading prefix.</param>
private void AppendCompleteChangelogSection(System.Text.StringBuilder markdown, string subHeading)
{
// Add full changelog section header and link
markdown.AppendLine($"{subHeading} Full Changelog");
markdown.AppendLine();
markdown.AppendLine($"See the full changelog at [{CompleteChangelogLink!.LinkText}]({CompleteChangelogLink.TargetUrl}).");
markdown.AppendLine();
}
}
10 changes: 5 additions & 5 deletions src/DemaConsulting.BuildMark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@ private static void ProcessBuildNotes(Context context)
}

// Display build information summary
context.WriteLine($"Build Version: {buildInfo.ToVersion.Tag}");
context.WriteLine($"Commit Hash: {buildInfo.ToHash}");
if (buildInfo.FromVersion != null)
context.WriteLine($"Build Version: {buildInfo.CurrentVersionTag.VersionInfo.Tag}");
context.WriteLine($"Commit Hash: {buildInfo.CurrentVersionTag.CommitHash}");
if (buildInfo.BaselineVersionTag != null)
{
context.WriteLine($"Previous Version: {buildInfo.FromVersion.Tag}");
context.WriteLine($"Previous Commit Hash: {buildInfo.FromHash}");
context.WriteLine($"Previous Version: {buildInfo.BaselineVersionTag.VersionInfo.Tag}");
context.WriteLine($"Previous Commit Hash: {buildInfo.BaselineVersionTag.CommitHash}");
}
context.WriteLine($"Changes: {buildInfo.Changes.Count}");
context.WriteLine($"Bugs Fixed: {buildInfo.Bugs.Count}");
Expand Down
41 changes: 36 additions & 5 deletions src/DemaConsulting.BuildMark/RepoConnectors/GitHubRepoConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,23 @@ public override async Task<BuildInformation> GetBuildInformationAsync(Version? v
bugs.Sort((a, b) => a.Index.CompareTo(b.Index));
knownIssues.Sort((a, b) => a.Index.CompareTo(b.Index));

// Build version tags from version and hash info
var currentTag = new VersionTag(toVersion, toHash);
var baselineTag = fromVersion != null && fromHash != null
? new VersionTag(fromVersion, fromHash)
: null;

// Generate full changelog link for GitHub
var changelogLink = GenerateGitHubChangelogLink(owner, repo, fromVersion?.Tag, toVersion.Tag);

// Create and return build information with all collected data
return new BuildInformation(
fromVersion,
toVersion,
fromHash,
toHash,
baselineTag,
currentTag,
nonBugChanges,
bugs,
knownIssues);
knownIssues,
changelogLink);
}

/// <summary>
Expand Down Expand Up @@ -720,4 +728,27 @@ private static (string owner, string repo) ParseOwnerRepo(string path)
// Return parsed owner and repo
return (parts[0], parts[1]);
}

/// <summary>
/// Generates a GitHub compare link for the full changelog.
/// </summary>
/// <param name="owner">Repository owner.</param>
/// <param name="repo">Repository name.</param>
/// <param name="oldTag">Old tag name (null if from beginning).</param>
/// <param name="newTag">New tag name.</param>
/// <returns>WebLink to GitHub compare page, or null if no baseline tag.</returns>
private static WebLink? GenerateGitHubChangelogLink(string owner, string repo, string? oldTag, string newTag)
{
// Cannot generate comparison link without a baseline tag
if (oldTag == null)
{
return null;
}

// Build comparison label and URL
var comparisonLabel = $"{oldTag}...{newTag}";
var comparisonUrl = $"https://github.com/{owner}/{repo}/compare/{comparisonLabel}";

return new WebLink(comparisonLabel, comparisonUrl);
}
}
39 changes: 34 additions & 5 deletions src/DemaConsulting.BuildMark/RepoConnectors/MockRepoConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,23 @@ public override async Task<BuildInformation> GetBuildInformationAsync(Version? v
bugs.Sort((a, b) => a.Index.CompareTo(b.Index));
knownIssues.Sort((a, b) => a.Index.CompareTo(b.Index));

// Build version tags from version and hash info
var currentTag = new VersionTag(toTagInfo, toHash.Trim());
var baselineTag = fromTagInfo != null && fromHash != null
? new VersionTag(fromTagInfo, fromHash.Trim())
: null;

// Generate mock changelog link
var changelogLink = GenerateMockChangelogLink(fromTagInfo?.Tag, toTagInfo.Tag);

// Create and return build information with all collected data
return new BuildInformation(
fromTagInfo,
toTagInfo,
fromHash?.Trim(),
toHash.Trim(),
baselineTag,
currentTag,
nonBugChanges,
bugs,
knownIssues);
knownIssues,
changelogLink);
}

/// <summary>
Expand Down Expand Up @@ -526,4 +534,25 @@ private Task<List<ItemInfo>> GetOpenIssuesAsync()
// Return task with open issues data
return Task.FromResult(openIssuesData);
}

/// <summary>
/// Generates a mock changelog link for testing.
/// </summary>
/// <param name="oldTag">Old tag name (null if from beginning).</param>
/// <param name="newTag">New tag name.</param>
/// <returns>WebLink to mock compare page, or null if no baseline tag.</returns>
private static WebLink? GenerateMockChangelogLink(string? oldTag, string newTag)
{
// Cannot generate comparison link without a baseline tag
if (oldTag == null)
{
return null;
}

// Build comparison label and URL for mock repo
var comparisonLabel = $"{oldTag}...{newTag}";
var comparisonUrl = $"https://github.com/example/repo/compare/{comparisonLabel}";

return new WebLink(comparisonLabel, comparisonUrl);
}
}
28 changes: 28 additions & 0 deletions src/DemaConsulting.BuildMark/VersionTag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) DEMA Consulting
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

namespace DemaConsulting.BuildMark;

/// <summary>
/// Represents a version paired with its corresponding commit hash.
/// </summary>
/// <param name="VersionInfo">The version information.</param>
/// <param name="CommitHash">The git commit hash for this version.</param>
public record VersionTag(Version VersionInfo, string CommitHash);
28 changes: 28 additions & 0 deletions src/DemaConsulting.BuildMark/WebLink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) DEMA Consulting
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

namespace DemaConsulting.BuildMark;

/// <summary>
/// Represents a hyperlink with descriptive text and target URL.
/// </summary>
/// <param name="LinkText">The display text for the link.</param>
/// <param name="TargetUrl">The destination URL.</param>
public record WebLink(string LinkText, string TargetUrl);
Loading