Skip to content

Commit 41f86e5

Browse files
Rework documentation generation
1 parent c0cbd25 commit 41f86e5

File tree

6 files changed

+281
-234
lines changed

6 files changed

+281
-234
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ It's no harder than writing unit tests!
2929
Under the hood, it performs a lot of [magic](#automation) that guarantees [reliable and precise](#reliability) results thanks to the [perfolizer](https://github.com/AndreyAkinshin/perfolizer) statistical engine.
3030
BenchmarkDotNet protects you from popular benchmarking mistakes and warns you if something is wrong with your benchmark design or obtained measurements.
3131
The results are presented in a [user-friendly](#friendliness) form that highlights all the important facts about your experiment.
32-
The library is adopted by [16500+ GitHub projects](#who-uses-benchmarkdotnet) including .NET Runtime.
32+
The library is adopted by [16600+ GitHub projects](#who-uses-benchmarkdotnet) including .NET Runtime.
3333

3434
It's [easy](#simplicity) to start writing benchmarks, check out the following example
3535
(copy-pastable version is [here](https://benchmarkdotnet.org/articles/guides/getting-started.html)):
@@ -231,7 +231,7 @@ If you don't customize the summary view,
231231
## Who uses BenchmarkDotNet?
232232

233233
Everyone!
234-
BenchmarkDotNet is already adopted by more than [16500+](https://github.com/dotnet/BenchmarkDotNet/network/dependents?package_id=UGFja2FnZS0xNTY3MzExMzE%3D) projects including
234+
BenchmarkDotNet is already adopted by more than [16600+](https://github.com/dotnet/BenchmarkDotNet/network/dependents?package_id=UGFja2FnZS0xNTY3MzExMzE%3D) projects including
235235
[dotnet/performance](https://github.com/dotnet/performance) (reference benchmarks for all .NET Runtimes),
236236
[dotnet/runtime](https://github.com/dotnet/runtime/issues?utf8=%E2%9C%93&q=BenchmarkDotNet) (.NET runtime and libraries),
237237
[Roslyn](https://github.com/dotnet/roslyn/search?q=BenchmarkDotNet&type=Issues&utf8=✓) (C# and Visual Basic compiler),

build/BenchmarkDotNet.Build/BuildContext.cs

Lines changed: 44 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,6 @@ public class BuildContext : FrostingContext
2929
public DirectoryPath RootDirectory { get; }
3030
public DirectoryPath BuildDirectory { get; }
3131
public DirectoryPath ArtifactsDirectory { get; }
32-
public DirectoryPath DocsDirectory { get; }
33-
public FilePath DocfxJsonFile { get; }
34-
35-
public DirectoryPath ChangeLogDirectory { get; }
36-
public DirectoryPath ChangeLogGenDirectory { get; }
37-
38-
public DirectoryPath RedirectRootDirectory { get; }
39-
public DirectoryPath RedirectTargetDirectory { get; }
4032

4133
public FilePath SolutionFile { get; }
4234
public FilePath TemplatesTestsProjectFile { get; }
@@ -56,9 +48,9 @@ public class BuildContext : FrostingContext
5648

5749
public bool IsLocalBuild => this.BuildSystem().IsLocalBuild;
5850
public bool IsCiBuild => !this.BuildSystem().IsLocalBuild;
59-
51+
6052
public VersionHistory VersionHistory { get; }
61-
53+
6254
public UnitTestRunner UnitTestRunner { get; }
6355
public DocumentationRunner DocumentationRunner { get; }
6456
public BuildRunner BuildRunner { get; }
@@ -69,17 +61,10 @@ public BuildContext(ICakeContext context)
6961
RootDirectory = new DirectoryPath(new DirectoryInfo(Directory.GetCurrentDirectory()).Parent?.Parent?.FullName);
7062
BuildDirectory = RootDirectory.Combine("build");
7163
ArtifactsDirectory = RootDirectory.Combine("artifacts");
72-
DocsDirectory = RootDirectory.Combine("docs");
73-
DocfxJsonFile = DocsDirectory.CombineWithFilePath("docfx.json");
74-
75-
ChangeLogDirectory = RootDirectory.Combine("docs").Combine("changelog");
76-
ChangeLogGenDirectory = RootDirectory.Combine("docs").Combine("_changelog");
7764

78-
RedirectRootDirectory = RootDirectory.Combine("docs").Combine("_redirects");
79-
RedirectTargetDirectory = RootDirectory.Combine("docs").Combine("_site");
8065

8166
SolutionFile = RootDirectory.CombineWithFilePath("BenchmarkDotNet.sln");
82-
67+
8368
TemplatesTestsProjectFile = RootDirectory.Combine("templates")
8469
.CombineWithFilePath("BenchmarkDotNet.Templates.csproj");
8570
AllPackableSrcProjects = new FilePathCollection(context.GetFiles(RootDirectory.FullPath + "/src/**/*.csproj")
@@ -127,7 +112,7 @@ public BuildContext(ICakeContext context)
127112
}
128113
}
129114
}
130-
115+
131116
// NativeAOT build requires VS C++ tools to be added to $path via vcvars64.bat
132117
// but once we do that, dotnet restore fails with:
133118
// "Please specify a valid solution configuration using the Configuration and Platform properties"
@@ -143,92 +128,57 @@ public BuildContext(ICakeContext context)
143128
DocumentationRunner = new DocumentationRunner(this);
144129
BuildRunner = new BuildRunner(this);
145130
}
146-
147-
public void EnsureChangelogDetailsExist(bool forceClean = false)
148-
{
149-
var path = ChangeLogGenDirectory.Combine("details");
150-
if (this.DirectoryExists(path) && forceClean)
151-
this.DeleteDirectory(path, new DeleteDirectorySettings() { Force = true, Recursive = true });
152-
153-
if (!this.DirectoryExists(path))
154-
{
155-
var repo = Repo.HttpsGitUrl;
156-
var branchName = Repo.ChangelogDetailsBranch;
157-
var settings = new GitCloneSettings { Checkout = true, BranchName = branchName };
158-
this.Information($"Trying to clone {repo} to {path} (branch: '{branchName})");
159-
try
160-
{
161-
this.GitClone(repo, path, settings);
162-
}
163-
catch (Exception e)
164-
{
165-
this.Error($"Failed to clone {repo} to {path} (branch: '{branchName}), Exception: {e.GetType().Name}'");
166-
try
167-
{
168-
var gitArgs = $"clone -b {branchName} {repo} {path}";
169-
this.Information($"Trying to clone manually: 'git {gitArgs}'");
170-
this.StartProcess("git", gitArgs);
171-
}
172-
catch (Exception e2)
173-
{
174-
throw new Exception($"Failed to clone {repo} to {path} (branch: '{branchName})'", e2);
175-
}
176-
}
177131

178-
this.Information("Clone is successfully finished");
179-
this.Information("");
180-
}
181-
}
182-
183-
public void DocfxChangelogDownload(string version, string versionPrevious, string lastCommit = "")
132+
public void GenerateFile(FilePath filePath, StringBuilder content)
184133
{
185-
EnsureChangelogDetailsExist();
186-
this.Information("DocfxChangelogDownload: " + version);
187-
var path = ChangeLogGenDirectory.Combine("details");
188-
ChangeLogBuilder.Run(path, version, versionPrevious, lastCommit).Wait();
134+
GenerateFile(filePath, content.ToString());
189135
}
190136

191-
public void DocfxChangelogGenerate(string version)
137+
public void GenerateFile(FilePath filePath, string content)
192138
{
193-
EnsureChangelogDetailsExist();
194-
this.Information("DocfxChangelogGenerate: " + version);
195-
var header = ChangeLogGenDirectory.Combine("header").CombineWithFilePath(version + ".md");
196-
var footer = ChangeLogGenDirectory.Combine("footer").CombineWithFilePath(version + ".md");
197-
var details = ChangeLogGenDirectory.Combine("details").CombineWithFilePath(version + ".md");
198-
var release = ChangeLogDirectory.CombineWithFilePath(version + ".md");
199-
200-
var content = new StringBuilder();
201-
content.AppendLine("---");
202-
content.AppendLine("uid: changelog." + version);
203-
content.AppendLine("---");
204-
content.AppendLine("");
205-
content.AppendLine("# BenchmarkDotNet " + version);
206-
content.AppendLine("");
207-
content.AppendLine("");
208-
209-
if (this.FileExists(header))
139+
var relativePath = RootDirectory.GetRelativePath(filePath);
140+
if (this.FileExists(filePath))
210141
{
211-
content.AppendLine(this.FileReadText(header));
212-
content.AppendLine("");
213-
content.AppendLine("");
214-
}
142+
var oldContent = this.FileReadText(filePath);
143+
if (content == oldContent)
144+
return;
215145

216-
if (this.FileExists(details))
146+
this.FileWriteText(filePath, content);
147+
this.Information("[Updated] " + relativePath);
148+
}
149+
else
217150
{
218-
content.AppendLine(this.FileReadText(details));
219-
content.AppendLine("");
220-
content.AppendLine("");
151+
this.FileWriteText(filePath, content);
152+
this.Information("[Generated] " + relativePath);
221153
}
154+
}
222155

223-
if (this.FileExists(footer))
156+
public void Clone(DirectoryPath path, string repoUrl, string branchName)
157+
{
158+
this.Information($"[GitClone]");
159+
this.Information($" Repo: {repoUrl}");
160+
this.Information($" Branch: {branchName}");
161+
this.Information($" Path: {path}");
162+
var settings = new GitCloneSettings { Checkout = true, BranchName = branchName };
163+
try
224164
{
225-
content.AppendLine("## Additional details");
226-
content.AppendLine("");
227-
content.AppendLine(this.FileReadText(footer));
165+
this.GitClone(repoUrl, path, settings);
166+
this.Information(" Success");
167+
}
168+
catch (Exception e)
169+
{
170+
this.Error($" Failed to clone via API (Exception: {e.GetType().Name})'");
171+
try
172+
{
173+
var gitArgs = $"clone -b {branchName} {repoUrl} {path}";
174+
this.Information($" Trying to clone manually using 'git {gitArgs}'");
175+
this.StartProcess("git", gitArgs);
176+
this.Information(" Success");
177+
}
178+
catch (Exception e2)
179+
{
180+
throw new Exception($"Failed to clone {repoUrl} to {path} (branch: '{branchName})'", e2);
181+
}
228182
}
229-
230-
this.FileWriteText(release, content.ToString());
231183
}
232-
233-
234184
}

build/BenchmarkDotNet.Build/ChangeLogBuilder.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ public static class ChangeLogBuilder
1616
{
1717
private class Config
1818
{
19-
public string CurrentMilestone { get; }
20-
public string PreviousMilestone { get; }
19+
public string CurrentVersion { get; }
20+
public string PreviousVersion { get; }
2121
public string LastCommit { get; }
2222

2323
public void Deconstruct(out string currentMilestone, out string previousMilestone, out string lastCommit)
2424
{
25-
currentMilestone = CurrentMilestone;
26-
previousMilestone = PreviousMilestone;
25+
currentMilestone = CurrentVersion;
26+
previousMilestone = PreviousVersion;
2727
lastCommit = LastCommit;
2828
}
2929

30-
public Config(string currentMilestone, string previousMilestone, string lastCommit)
30+
public Config(string currentVersion, string previousVersion, string lastCommit)
3131
{
32-
CurrentMilestone = currentMilestone;
33-
PreviousMilestone = previousMilestone;
32+
CurrentVersion = currentVersion;
33+
PreviousVersion = previousVersion;
3434
LastCommit = lastCommit;
3535
}
3636
}
@@ -56,15 +56,15 @@ private MarkdownBuilder(Config config)
5656

5757
private async Task<string> Build()
5858
{
59-
var (milestone, previousMilestone, lastCommit) = config;
59+
var (currentVersion, previousVersion, lastCommit) = config;
6060
if (string.IsNullOrEmpty(lastCommit))
61-
lastCommit = milestone;
61+
lastCommit = currentVersion;
6262

63-
var client = new GitHubClient(new ProductHeaderValue(Repo.ProductHeader));
64-
var tokenAuth = new Credentials(Repo.Token);
63+
var client = new GitHubClient(new ProductHeaderValue(GitHubCredentials.ProductHeader));
64+
var tokenAuth = new Credentials(GitHubCredentials.Token);
6565
client.Credentials = tokenAuth;
6666

67-
if (milestone == "_")
67+
if (currentVersion == "_")
6868
{
6969
var allContributors = await client.Repository.GetAllContributors(Repo.Owner, Repo.Name);
7070
builder.AppendLine("# All contributors");
@@ -87,11 +87,12 @@ private async Task<string> Build()
8787
{
8888
State = ItemStateFilter.All
8989
};
90-
allMilestones = await client.Issue.Milestone.GetAllForRepository(Repo.Owner, Repo.Name, milestoneRequest);
90+
allMilestones =
91+
await client.Issue.Milestone.GetAllForRepository(Repo.Owner, Repo.Name, milestoneRequest);
9192
}
9293

9394
IReadOnlyList<Issue> allIssues = Array.Empty<Issue>();
94-
var targetMilestone = allMilestones.FirstOrDefault(m => m.Title == milestone);
95+
var targetMilestone = allMilestones.FirstOrDefault(m => m.Title == $"v{currentVersion}");
9596
if (targetMilestone != null)
9697
{
9798
var issueRequest = new RepositoryIssueRequest
@@ -112,10 +113,10 @@ private async Task<string> Build()
112113
.OrderBy(issue => issue.Number)
113114
.ToList();
114115

115-
var compare = await client.Repository.Commit.Compare(Repo.Owner, Repo.Name, previousMilestone, lastCommit);
116+
var compare =
117+
await client.Repository.Commit.Compare(Repo.Owner, Repo.Name, $"v{previousVersion}", lastCommit);
116118
var commits = compare.Commits;
117119

118-
119120
foreach (var contributor in commits.Select(commit => commit.Author))
120121
if (contributor != null && !AuthorNames.ContainsKey(contributor.Login))
121122
{
@@ -137,11 +138,11 @@ string PresentContributor(GitHubCommit commit)
137138
.Distinct()
138139
.ToImmutableList();
139140

140-
var milestoneHtmlUlr = $"https://github.com/{Repo.Owner}/{Repo.Name}/issues?q=milestone:{milestone}";
141+
var milestoneHtmlUlr = $"https://github.com/{Repo.Owner}/{Repo.Name}/issues?q=milestone:{currentVersion}";
141142

142143
builder.AppendLine("## Milestone details");
143144
builder.AppendLine();
144-
builder.AppendLine($"In the [{milestone}]({milestoneHtmlUlr}) scope, ");
145+
builder.AppendLine($"In the [{currentVersion}]({milestoneHtmlUlr}) scope, ");
145146
builder.Append(issues.Count + " issues were resolved and ");
146147
builder.AppendLine(pullRequests.Count + " pull requests were merged.");
147148
builder.AppendLine($"This release includes {commits.Count} commits by {contributors.Count} contributors.");
@@ -175,14 +176,13 @@ private void AppendList<T>(string title, IReadOnlyList<T> items, Func<T, string>
175176
}
176177
}
177178

178-
public static async Task Run(DirectoryPath path, string currentMilestone, string previousMilestone,
179-
string lastCommit)
179+
public static async Task Run(DirectoryPath path, string currentVersion, string previousVersion, string lastCommit)
180180
{
181181
try
182182
{
183-
var config = new Config(currentMilestone, previousMilestone, lastCommit);
183+
var config = new Config(currentVersion, previousVersion, lastCommit);
184184
var releaseNotes = await MarkdownBuilder.Build(config);
185-
await File.WriteAllTextAsync(path.Combine(config.CurrentMilestone + ".md").FullPath, releaseNotes);
185+
await File.WriteAllTextAsync(path.Combine(config.CurrentVersion + ".md").FullPath, releaseNotes);
186186
}
187187
catch (Exception e)
188188
{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace BenchmarkDotNet.Build.Meta;
4+
5+
public static class GitHubCredentials
6+
{
7+
public const string TokenVariableName = "GITHUB_TOKEN";
8+
9+
public const string ProductHeader = "BenchmarkDotNet";
10+
public static string? Token => Environment.GetEnvironmentVariable(TokenVariableName);
11+
}
Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System;
2-
31
namespace BenchmarkDotNet.Build.Meta;
42

53
public static class Repo
@@ -9,10 +7,4 @@ public static class Repo
97
public const string HttpsUrlBase = $"https://github.com/{Owner}/{Name}";
108
public const string HttpsGitUrl = $"{HttpsUrlBase}.git";
119
public const string ChangelogDetailsBranch = "docs-changelog-details";
12-
13-
public const string ProductHeaderVar = "GITHUB_PRODUCT";
14-
public const string TokenVar = "GITHUB_TOKEN";
15-
16-
public static string? ProductHeader => Environment.GetEnvironmentVariable(ProductHeaderVar);
17-
public static string? Token => Environment.GetEnvironmentVariable(TokenVar);
1810
}

0 commit comments

Comments
 (0)