Skip to content

Commit

Permalink
Merge pull request #8 from credfeto/feat/fix-read-me
Browse files Browse the repository at this point in the history
Checking changelog insert positions
  • Loading branch information
credfeto authored Nov 19, 2020
2 parents a794365 + 099332c commit 5369d73
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 24 deletions.
39 changes: 29 additions & 10 deletions .github/workflows/pr-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,32 @@ jobs:
include-changelog-entry:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0
- if: ${{ github.actor != 'dependabot-preview[bot]' }}
uses: Zomzog/[email protected]
with:
fileName: CHANGELOG.md
noChangelogLabel: Changelog Not Required
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/[email protected]
with:
fetch-depth: 0
- if: ${{ github.actor != 'dependabot[bot]' }}
uses: Zomzog/[email protected]
with:
fileName: CHANGELOG.md
noChangelogLabel: Changelog Not Required
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

change-log-entry-is-in-unreleased:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0
- uses: credfeto/[email protected]
- uses: actions/setup-dotnet@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Enable dotnet tools
run: dotnet new tool-manifest
- name: Install Changelog tool
run: dotnet tool install --local Credfeto.ChangeLog.Cmd
- name: Check Changelog
run: dotnet changelog -changelog D:\Work\changelog-manager\CHANGELOG.md -check-insert ${{ github.base_ref}}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release

## [Unreleased]
### Added
- Added support for checking where changelog entries were entered
### Fixed
### Changed
### Removed
Expand Down
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
# cs-template
C# Template
# Changelog manager .net tool

## Installation

```shell
dotnet tool install Credfeto.ChangeLog.Cmd
```

## Usage

Extract the release notes for a pre-release build
```shell
dotnet changelog -changelog CHANGELOG.md -extract RELEASE_NOTES.md -version 1.0.1.27-master
```

Extract the release notes for a release build
```shell
dotnet changelog -changelog CHANGELOG.md -extract RELEASE_NOTES.md -version 1.0.2.77
```

3 changes: 1 addition & 2 deletions src/Credfeto.ChangeLog.Cmd/Credfeto.ChangeLog.Cmd.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifiers>win10-x64;win81-x64;osx.10.12-x64</RuntimeIdentifiers>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<WarningsAsErrors/>
Expand All @@ -26,7 +26,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0"/>

</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.3.0" PrivateAssets="All"/>
Expand Down
25 changes: 23 additions & 2 deletions src/Credfeto.ChangeLog.Cmd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private static async Task<int> Main(string[] args)
{
string version = configuration.GetValue<string>("version");

string text = await ChangeLogReader.ExtractReleasNodesFromFileAsync(changeLogFileName: changeLog, version: version);
string text = await ChangeLogReader.ExtractReleaseNodesFromFileAsync(changeLogFileName: changeLog, version: version);

await File.WriteAllTextAsync(path: extractFileName, contents: text, encoding: Encoding.UTF8);

Expand All @@ -61,6 +61,26 @@ private static async Task<int> Main(string[] args)
return SUCCESS;
}

string? branchName = configuration.GetValue<string>("check-insert");

if (!string.IsNullOrWhiteSpace(branchName))
{
bool valid = await ChangeLogChecker.ChangeLogModifiedInReleaseSectionAsync(changeLogFileName: changeLog, originBranchName: branchName);

if (valid)
{
Console.WriteLine("Changelog is valid");

return SUCCESS;
}

await Console.Error.WriteLineAsync("ERROR: Changelog modified in released section");

return ERROR;
}

Console.WriteLine("ERROR: No known action specified");

return ERROR;
}
catch (Exception exception)
Expand All @@ -80,7 +100,8 @@ private static IConfigurationRoot LoadConfiguration(string[] args)
{@"-version", @"version"},
{@"-extract", @"extract"},
{@"-add", @"add"},
{@"-message", @"message"}
{@"-message", @"message"},
{@"-check-insert", @"check-insert"}
})
.Build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<WarningsAsErrors/>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
Expand Down
22 changes: 22 additions & 0 deletions src/Credfeto.ChangeLog/BranchMissingException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Credfeto.ChangeLog.Management
{
public sealed class BranchMissingException : Exception
{
public BranchMissingException()
: this("Could not find branch")
{
}

public BranchMissingException(string message)
: base(message)
{
}

public BranchMissingException(string message, Exception innerException)
: base(message: message, innerException: innerException)
{
}
}
}
107 changes: 107 additions & 0 deletions src/Credfeto.ChangeLog/ChangeLogChecker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using LibGit2Sharp;

namespace Credfeto.ChangeLog.Management
{
public static class ChangeLogChecker
{
private static readonly Regex HunkPositionRegex =
new Regex(pattern: @"^@@\s*\-(?<OriginalFileStart>\d*)(,(?<OriginalFileEnd>\d*))?\s*\+(?<CurrentFileStart>\d*)(,(?<CurrentFileChangeLength>\d*))?\s*@@",
RegexOptions.Compiled | RegexOptions.Multiline);

public static async Task<bool> ChangeLogModifiedInReleaseSectionAsync(string changeLogFileName, string originBranchName)
{
int? position = await ChangeLogReader.FindFirstReleaseVersionPositionAsync(changeLogFileName);

if (position == null)
{
return false;
}

string changelogDir = Path.GetDirectoryName(changeLogFileName)!;

using (Repository repo = OpenRepository(changelogDir))
{
string? sha = repo.Head.Tip.Sha;

Branch? originBranch = repo.Branches.FirstOrDefault(b => b.FriendlyName == originBranchName);

if (originBranch == null)
{
throw new BranchMissingException($"Could not find branch {originBranchName}");
}

if (originBranch.Tip.Sha == sha)
{
// same branch/commit
return false;
}

string changeLogInRepoPath = FindChangeLogPositionInRepo(repo: repo, changeLogFileName: changeLogFileName);

int firstReleaseVersionIndex = position.Value;

Patch changes = repo.Diff.Compare<Patch>(oldTree: originBranch.Tip.Tree,
newTree: repo.Head.Tip.Tree,
new CompareOptions {ContextLines = 0, InterhunkLines = 0, IncludeUnmodified = false});

foreach (var change in changes)
{
if (change.Path == changeLogInRepoPath)
{
string patchDetails = change.Patch;
Console.WriteLine(patchDetails);

MatchCollection matches = HunkPositionRegex.Matches(patchDetails);

foreach (Match? match in matches)
{
if (match == null)
{
continue;
}

int changeStart = Convert.ToInt32(match.Groups["CurrentFileStart"]
.Value);

if (!int.TryParse(s: match.Groups["CurrentFileChangeLength"]
.Value,
out int changeLength))
{
changeLength = 1;
}

int changeEnd = changeStart + changeLength;

if (changeEnd >= firstReleaseVersionIndex)
{
return false;
}
}

return true;
}
}
}

return true;
}

private static string FindChangeLogPositionInRepo(Repository repo, string changeLogFileName)
{
return changeLogFileName.Substring(repo.Info.WorkingDirectory.Length)
.Replace(oldValue: "\\", newValue: "/");
}

private static Repository OpenRepository(string workDir)
{
string found = Repository.Discover(workDir);

return new Repository(found);
}
}
}
28 changes: 23 additions & 5 deletions src/Credfeto.ChangeLog/ChangeLogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

namespace Credfeto.ChangeLog.Management
{
public sealed class ChangeLogReader
public static class ChangeLogReader
{
private static readonly Regex RemoveComments = new Regex(pattern: "<!--[\\s\\S]*?-->", RegexOptions.Compiled | RegexOptions.Multiline);
private static readonly Regex VersionHeaderMatch = new Regex(pattern: @"^##\s\[(\d+)", options: RegexOptions.Compiled);

public static async Task<string> ExtractReleasNodesFromFileAsync(string changeLogFileName, string version)
public static async Task<string> ExtractReleaseNodesFromFileAsync(string changeLogFileName, string version)
{
string textBlock = await File.ReadAllTextAsync(path: changeLogFileName, encoding: Encoding.UTF8);

Expand All @@ -28,8 +29,6 @@ public static string ExtractReleaseNotes(string changeLog, string version)

FindSectionForBuild(text: text, version: releaseVersion, out int foundStart, out int foundEnd);

StringBuilder releaseNotes = new StringBuilder();

if (foundStart == -1)
{
return string.Empty;
Expand All @@ -40,7 +39,9 @@ public static string ExtractReleaseNotes(string changeLog, string version)
foundEnd = text.Length;
}

string previousLine = "";
string previousLine = string.Empty;

StringBuilder releaseNotes = new StringBuilder();

for (int i = foundStart; i < foundEnd; i++)
{
Expand Down Expand Up @@ -78,6 +79,23 @@ public static string ExtractReleaseNotes(string changeLog, string version)
.Trim();
}

public static async Task<int?> FindFirstReleaseVersionPositionAsync(string changeLogFileName)
{
IReadOnlyList<string> changelog = await File.ReadAllLinesAsync(path: changeLogFileName, encoding: Encoding.UTF8);

for (int lineIndex = 0; lineIndex < changelog.Count; ++lineIndex)
{
string line = changelog[lineIndex];

if (VersionHeaderMatch.IsMatch(line))
{
return lineIndex;
}
}

return null;
}

private static void FindSectionForBuild(string[] text, Version? version, out int foundStart, out int foundEnd)
{
foundStart = -1;
Expand Down
2 changes: 1 addition & 1 deletion src/Credfeto.ChangeLog/ChangeLogUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Credfeto.ChangeLog.Management
{
public sealed class ChangeLogUpdater
public static class ChangeLogUpdater
{
public static async Task AddEntryAsync(string changeLogFileName, string type, string message)
{
Expand Down
6 changes: 5 additions & 1 deletion src/Credfeto.ChangeLog/Credfeto.ChangeLog.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<WarningsAsErrors/>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
Expand All @@ -25,6 +25,10 @@
<NeutralLanguage>en-GB</NeutralLanguage>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="LibGit2Sharp" Version="0.26.2"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.3.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.8.55" PrivateAssets="All"/>
Expand Down

0 comments on commit 5369d73

Please sign in to comment.