Skip to content

Commit 7c16c75

Browse files
gep13AdmiringWorm
andcommitted
(GH-136) Allow configuration of SHA256 entries
After discussion on Twitch stream, it was decided that it should be possible to configure the SHA256 entries that are added into the generated release notes. This includes showing/hiding the entries, controlling the heading that is added, as well as the format of each line that is added to the notes. To allow for this, there was some general re-formatting of the codebase, to correctly provide the configuration to each command, as weel as ensuring default configuration is always provided. Co-Authored-By: Kim J. Nordmo <[email protected]>
1 parent 4bdb006 commit 7c16c75

File tree

5 files changed

+75
-35
lines changed

5 files changed

+75
-35
lines changed

Source/GitReleaseManager.Cli/Program.cs

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ namespace GitReleaseManager.Cli
2525

2626
public static class Program
2727
{
28-
private static StringBuilder log = new StringBuilder();
28+
private static StringBuilder _log = new StringBuilder();
29+
private static FileSystem _fileSystem;
30+
private static Config _configuration;
2931

3032
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Not required")]
3133
private static int Main(string[] args)
@@ -34,29 +36,29 @@ private static int Main(string[] args)
3436
// we've upgraded to latest Octokit.
3537
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
3638

37-
var fileSystem = new FileSystem();
39+
_fileSystem = new FileSystem();
3840

3941
return Parser.Default.ParseArguments<CreateSubOptions, AddAssetSubOptions, CloseSubOptions, PublishSubOptions, ExportSubOptions, InitSubOptions, ShowConfigSubOptions, LabelSubOptions>(args)
4042
.MapResult(
41-
(CreateSubOptions opts) => CreateReleaseAsync(opts, fileSystem).Result,
43+
(CreateSubOptions opts) => CreateReleaseAsync(opts).Result,
4244
(AddAssetSubOptions opts) => AddAssetsAsync(opts).Result,
4345
(CloseSubOptions opts) => CloseMilestoneAsync(opts).Result,
4446
(PublishSubOptions opts) => PublishReleaseAsync(opts).Result,
45-
(ExportSubOptions opts) => ExportReleasesAsync(opts, fileSystem).Result,
46-
(InitSubOptions opts) => CreateSampleConfigFile(opts, fileSystem),
47-
(ShowConfigSubOptions opts) => ShowConfig(opts, fileSystem),
47+
(ExportSubOptions opts) => ExportReleasesAsync(opts).Result,
48+
(InitSubOptions opts) => CreateSampleConfigFile(opts),
49+
(ShowConfigSubOptions opts) => ShowConfig(opts),
4850
(LabelSubOptions opts) => CreateLabelsAsync(opts).Result,
4951
errs => 1);
5052
}
5153

52-
private static async Task<int> CreateReleaseAsync(CreateSubOptions subOptions, IFileSystem fileSystem)
54+
private static async Task<int> CreateReleaseAsync(CreateSubOptions subOptions)
5355
{
5456
try
5557
{
5658
ConfigureLogging(subOptions.LogFilePath);
5759

5860
var github = subOptions.CreateGitHubClient();
59-
var configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, fileSystem);
61+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
6062

6163
Release release;
6264
if (!string.IsNullOrEmpty(subOptions.Milestone))
@@ -67,7 +69,7 @@ private static async Task<int> CreateReleaseAsync(CreateSubOptions subOptions, I
6769
releaseName = subOptions.Milestone;
6870
}
6971

70-
release = await CreateReleaseFromMilestone(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.Milestone, releaseName, subOptions.TargetCommitish, subOptions.AssetPaths, subOptions.Prerelease, configuration);
72+
release = await CreateReleaseFromMilestone(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.Milestone, releaseName, subOptions.TargetCommitish, subOptions.AssetPaths, subOptions.Prerelease);
7173
}
7274
else
7375
{
@@ -92,6 +94,7 @@ private static async Task<int> AddAssetsAsync(AddAssetSubOptions subOptions)
9294
ConfigureLogging(subOptions.LogFilePath);
9395

9496
var github = subOptions.CreateGitHubClient();
97+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
9598

9699
await AddAssets(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.TagName, subOptions.AssetPaths);
97100

@@ -112,6 +115,7 @@ private static async Task<int> CloseMilestoneAsync(CloseSubOptions subOptions)
112115
ConfigureLogging(subOptions.LogFilePath);
113116

114117
var github = subOptions.CreateGitHubClient();
118+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
115119

116120
await CloseMilestone(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.Milestone);
117121

@@ -132,6 +136,7 @@ private static async Task<int> PublishReleaseAsync(PublishSubOptions subOptions)
132136
ConfigureLogging(subOptions.LogFilePath);
133137

134138
var github = subOptions.CreateGitHubClient();
139+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
135140

136141
await PublishRelease(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.TagName);
137142

@@ -145,16 +150,16 @@ private static async Task<int> PublishReleaseAsync(PublishSubOptions subOptions)
145150
}
146151
}
147152

148-
private static async Task<int> ExportReleasesAsync(ExportSubOptions subOptions, IFileSystem fileSystem)
153+
private static async Task<int> ExportReleasesAsync(ExportSubOptions subOptions)
149154
{
150155
try
151156
{
152157
ConfigureLogging(subOptions.LogFilePath);
153158

154159
var github = subOptions.CreateGitHubClient();
155-
var configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, fileSystem);
160+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
156161

157-
var releasesMarkdown = await ExportReleases(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.TagName, configuration);
162+
var releasesMarkdown = await ExportReleases(github, subOptions.RepositoryOwner, subOptions.RepositoryName, subOptions.TagName);
158163

159164
using (var sw = new StreamWriter(File.Open(subOptions.FileOutputPath, FileMode.OpenOrCreate)))
160165
{
@@ -171,19 +176,19 @@ private static async Task<int> ExportReleasesAsync(ExportSubOptions subOptions,
171176
}
172177
}
173178

174-
private static int CreateSampleConfigFile(InitSubOptions subOptions, IFileSystem fileSystem)
179+
private static int CreateSampleConfigFile(InitSubOptions subOptions)
175180
{
176181
ConfigureLogging(subOptions.LogFilePath);
177182

178-
ConfigurationProvider.WriteSample(subOptions.TargetDirectory ?? Environment.CurrentDirectory, fileSystem);
183+
ConfigurationProvider.WriteSample(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
179184
return 0;
180185
}
181186

182-
private static int ShowConfig(ShowConfigSubOptions subOptions, IFileSystem fileSystem)
187+
private static int ShowConfig(ShowConfigSubOptions subOptions)
183188
{
184189
ConfigureLogging(subOptions.LogFilePath);
185190

186-
Console.WriteLine(ConfigurationProvider.GetEffectiveConfigAsString(subOptions.TargetDirectory ?? Environment.CurrentDirectory, fileSystem));
191+
Console.WriteLine(ConfigurationProvider.GetEffectiveConfigAsString(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem));
187192
return 0;
188193
}
189194

@@ -205,6 +210,7 @@ private static async Task<int> CreateLabelsAsync(LabelSubOptions subOptions)
205210
newLabels.Add(new NewLabel("help wanted", "33aa3f"));
206211

207212
var github = subOptions.CreateGitHubClient();
213+
_configuration = ConfigurationProvider.Provide(subOptions.TargetDirectory ?? Environment.CurrentDirectory, _fileSystem);
208214

209215
var labels = await github.Issue.Labels.GetAllForRepository(subOptions.RepositoryOwner, subOptions.RepositoryName);
210216

@@ -227,9 +233,10 @@ private static async Task<int> CreateLabelsAsync(LabelSubOptions subOptions)
227233
return 1;
228234
}
229235
}
230-
private static async Task<Release> CreateReleaseFromMilestone(GitHubClient github, string owner, string repository, string milestone, string releaseName, string targetCommitish, IList<string> assets, bool prerelease, Config configuration)
236+
237+
private static async Task<Release> CreateReleaseFromMilestone(GitHubClient github, string owner, string repository, string milestone, string releaseName, string targetCommitish, IList<string> assets, bool prerelease)
231238
{
232-
var releaseNotesBuilder = new ReleaseNotesBuilder(new DefaultGitHubClient(github, owner, repository), owner, repository, milestone, configuration);
239+
var releaseNotesBuilder = new ReleaseNotesBuilder(new DefaultGitHubClient(github, owner, repository), owner, repository, milestone, _configuration);
233240

234241
var result = await releaseNotesBuilder.BuildReleaseNotes();
235242

@@ -275,9 +282,9 @@ private static async Task AddAssets(GitHubClient github, string owner, string re
275282
await AddAssets(github, owner, repository, assets, release);
276283
}
277284

278-
private static async Task<string> ExportReleases(GitHubClient github, string owner, string repository, string tagName, Config configuration)
285+
private static async Task<string> ExportReleases(GitHubClient github, string owner, string repository, string tagName)
279286
{
280-
var releaseNotesExporter = new ReleaseNotesExporter(new DefaultGitHubClient(github, owner, repository), configuration);
287+
var releaseNotesExporter = new ReleaseNotesExporter(new DefaultGitHubClient(github, owner, repository), _configuration);
281288

282289
var result = await releaseNotesExporter.ExportReleaseNotes(tagName);
283290

@@ -343,11 +350,14 @@ private static async Task AddAssets(GitHubClient github, string owner, string re
343350

344351
private static async Task AddAssetsSha256(GitHubClient github, string owner, string repository, IList<string> assets, Release release)
345352
{
346-
if (assets != null && assets.Any())
353+
if (assets != null && assets.Any() && _configuration.Create.IncludeShaSection)
347354
{
348355
var stringBuilder = new StringBuilder(release.Body);
349356

350-
stringBuilder.AppendLine("__SHA256 Hashes of the release artifacts__");
357+
if (!release.Body.Contains(_configuration.Create.ShaSectionHeading))
358+
{
359+
stringBuilder.AppendLine(string.Format("### {0}", _configuration.Create.ShaSectionHeading));
360+
}
351361

352362
foreach (var asset in assets)
353363
{
@@ -358,8 +368,8 @@ private static async Task AddAssetsSha256(GitHubClient github, string owner, str
358368
continue;
359369
}
360370

361-
stringBuilder.AppendFormat("- `{0}`\r\n", file.Name);
362-
stringBuilder.AppendFormat("\t- {0}\r\n", ComputeSha256Hash(asset));
371+
stringBuilder.AppendFormat(_configuration.Create.ShaSectionLineFormat, file.Name, ComputeSha256Hash(asset));
372+
stringBuilder.AppendLine();
363373
}
364374

365375
stringBuilder.AppendLine();
@@ -394,7 +404,7 @@ private static void ConfigureLogging(string logFilePath)
394404
{
395405
var writeActions = new List<Action<string>>
396406
{
397-
s => log.AppendLine(s)
407+
s => _log.AppendLine(s)
398408
};
399409

400410
if (!string.IsNullOrEmpty(logFilePath))
@@ -433,17 +443,17 @@ private static void WriteLogEntry(string logFilePath, string s)
433443
File.AppendAllText(logFilePath, contents);
434444
}
435445

436-
private static string ComputeSha256Hash(string asset)
446+
private static string ComputeSha256Hash(string asset)
437447
{
438-
// Create a SHA256
448+
// Create a SHA256
439449
using (var sha256Hash = SHA256.Create())
440450
{
441451
using (var fileStream = File.Open(asset, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
442452
{
443-
// ComputeHash - returns byte array
453+
// ComputeHash - returns byte array
444454
var bytes = sha256Hash.ComputeHash(fileStream);
445455

446-
// Convert byte array to a string
456+
// Convert byte array to a string
447457
var builder = new StringBuilder();
448458

449459
foreach (var t in bytes)
@@ -454,6 +464,6 @@ private static string ComputeSha256Hash(string asset)
454464
return builder.ToString();
455465
}
456466
}
457-
}
467+
}
458468
}
459469
}

Source/GitReleaseManager/Configuration/Config.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ public Config()
1919
FooterHeading = string.Empty,
2020
FooterContent = string.Empty,
2121
FooterIncludesMilestone = false,
22-
MilestoneReplaceText = string.Empty
23-
};
22+
MilestoneReplaceText = string.Empty,
23+
IncludeShaSection = false,
24+
ShaSectionHeading = "__SHA256 Hashes of the release artifacts__",
25+
ShaSectionLineFormat = "- `{1}\t{0}`"
26+
};
2427

2528
this.Export = new ExportConfig
2629
{
@@ -67,4 +70,4 @@ public Config()
6770
[YamlMember(Alias = "issue-labels-alias")]
6871
public IList<LabelAlias> LabelAliases { get; private set; }
6972
}
70-
}
73+
}

Source/GitReleaseManager/Configuration/ConfigurationProvider.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ public static Config Provide(string gitDirectory, IFileSystem fileSystem)
2828
{
2929
var readAllText = fileSystem.ReadAllText(configFilePath);
3030

31-
return ConfigSerializer.Read(new StringReader(readAllText));
31+
var deserializedConfig = ConfigSerializer.Read(new StringReader(readAllText));
32+
33+
EnsureDefaultConfig(deserializedConfig);
34+
35+
return deserializedConfig;
3236
}
3337

3438
return new Config();
@@ -75,5 +79,18 @@ private static string GetConfigFilePath(string targetDirectory)
7579
{
7680
return Path.Combine(targetDirectory, "GitReleaseManager.yaml");
7781
}
82+
83+
private static void EnsureDefaultConfig(Config configuration)
84+
{
85+
if(configuration.Create.ShaSectionHeading == null)
86+
{
87+
configuration.Create.ShaSectionHeading = "__SHA256 Hashes of the release artifacts__";
88+
}
89+
90+
if(configuration.Create.ShaSectionLineFormat == null)
91+
{
92+
configuration.Create.ShaSectionLineFormat = "- `{1}\t{0}`";
93+
}
94+
}
7895
}
79-
}
96+
}

Source/GitReleaseManager/Configuration/CreateConfig.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,14 @@ public class CreateConfig
2424

2525
[YamlMember(Alias = "milestone-replace-text")]
2626
public string MilestoneReplaceText { get; set; }
27+
28+
[YamlMember(Alias = "include-sha-section")]
29+
public bool IncludeShaSection { get; set; }
30+
31+
[YamlMember(Alias = "sha-section-heading")]
32+
public string ShaSectionHeading { get; set; }
33+
34+
[YamlMember(Alias = "sha-section-line-format")]
35+
public string ShaSectionLineFormat { get; set; }
2736
}
2837
}

Source/GitReleaseManager/ReleaseNotesBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ private void AddFooter(StringBuilder stringBuilder)
175175
}
176176

177177
stringBuilder.Append(footerContent);
178+
stringBuilder.AppendLine();
178179
}
179180

180181
private void LoadMilestones()

0 commit comments

Comments
 (0)