Skip to content

Commit cc5dd2b

Browse files
committed
Further adjustments
1 parent e12a953 commit cc5dd2b

File tree

7 files changed

+70
-44
lines changed

7 files changed

+70
-44
lines changed

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ Options:
2525
--force <bool?> Force a full rebuild of the destination folder (Default: null)
2626

2727
Commands:
28-
generate Converts a source markdown folder or file to an output folder
29-
serve Continuously serve a documentation folder at http://localhost:3000.
28+
generate Converts a source markdown folder or file to an output folder
29+
serve Continuously serve a documentation folder at http://localhost:3000.
30+
diff validate Validates redirect rules have been applied to the current branch.
3031
File systems changes will be reflected without having to restart the server.
3132
```
3233

@@ -118,6 +119,16 @@ https://github.com/elastic/{your-repository}/settings/pages
118119
119120
---
120121
122+
## Validating redirection rules
123+
124+
If documentation is moved, renamed or deleted, `docs-builder` can verify if changes in the working branch in relation to the default branch are reflected in the repository's `redirects.yml`. Verification in the local machine is currently supported.
125+
126+
`docs-builder diff validate <path>`
127+
128+
`<path>` is an optional parameter to customize the documentation folder path. It defaults to `docs`.
129+
130+
---
131+
121132
## Run without docker
122133

123134
You can use the .NET CLI to publish a self-contained `docs-builder` native code
@@ -140,7 +151,7 @@ existing surveyed tools
140151

141152
# Local Development
142153

143-
## Preqrequisites
154+
## Prerequisites
144155

145156
- [.NET 9.0 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/9.0)
146157
- [Node.js 22.13.1 (LTS)](https://nodejs.org/en/blog/release/v22.13.1)

src/tooling/Elastic.Documentation.Tooling/ExternalCommands/ExternalCommandExecutor.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ string[] CaptureOutput()
6464
}
6565

6666

67-
protected string Capture(string binary, params string[] args)
67+
protected string Capture(string binary, params string[] args) => Capture(false, binary, args);
68+
69+
protected string Capture(bool muteExceptions, string binary, params string[] args)
6870
{
6971
// Try 10 times to capture the output of the command, if it fails, we'll throw an exception on the last try
7072
Exception? e = null;
@@ -81,7 +83,7 @@ protected string Capture(string binary, params string[] args)
8183
}
8284
}
8385

84-
if (e is not null)
86+
if (e is not null && !muteExceptions)
8587
collector.EmitError("", "failure capturing stdout", e);
8688

8789
return string.Empty;
@@ -96,9 +98,11 @@ string CaptureOutput()
9698
ConsoleOutWriter = NoopConsoleWriter.Instance
9799
};
98100
var result = Proc.Start(arguments);
99-
var line = result.ExitCode != 0
100-
? throw new Exception($"Exit code is not 0. Received {result.ExitCode} from {binary}: {workingDirectory}")
101-
: result.ConsoleOut.FirstOrDefault()?.Line ?? throw new Exception($"No output captured for {binary}: {workingDirectory}");
101+
var line = (result.ExitCode, muteExceptions) switch
102+
{
103+
(0, _) or (not 0, true) => result.ConsoleOut.FirstOrDefault()?.Line ?? throw new Exception($"No output captured for {binary}: {workingDirectory}"),
104+
(not 0, false) => throw new Exception($"Exit code is not 0. Received {result.ExitCode} from {binary}: {workingDirectory}")
105+
};
102106
return line;
103107
}
104108
}

src/tooling/docs-builder/Cli/ValidationCommands.cs renamed to src/tooling/docs-builder/Cli/DiffCommands.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,25 @@
1515

1616
namespace Documentation.Builder.Cli;
1717

18-
internal sealed class ValidationCommands(ILoggerFactory logger, ICoreService githubActionsService)
18+
internal sealed class DiffCommands(ILoggerFactory logger, ICoreService githubActionsService)
1919
{
2020
/// <summary>
2121
/// Validates redirect updates in the current branch using the redirects file against changes reported by git.
2222
/// </summary>
23+
/// <param name="path">The baseline path to perform the check</param>
2324
/// <param name="ctx"></param>
2425
[SuppressMessage("Usage", "CA2254:Template should be a static expression")]
2526
[Command("validate")]
2627
[ConsoleAppFilter<StopwatchFilter>]
2728
[ConsoleAppFilter<CatchExceptionFilter>]
28-
public async Task<int> ValidateRedirects(Cancel ctx = default)
29+
public async Task<int> ValidateRedirects([Argument] string? path = null, Cancel ctx = default)
2930
{
3031
var log = logger.CreateLogger<Program>();
3132
ConsoleApp.Log = msg => log.LogInformation(msg);
3233
ConsoleApp.LogError = msg => log.LogError(msg);
3334

35+
path ??= "docs";
36+
3437
await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx);
3538

3639
var fs = new FileSystem();
@@ -51,11 +54,11 @@ public async Task<int> ValidateRedirects(Cancel ctx = default)
5154
return collector.Errors;
5255
}
5356

54-
var tracker = new GitRepositoryTracker(collector, root);
55-
var changed = tracker.GetChangedFiles();
57+
var tracker = new LocalGitRepositoryTracker(collector, root);
58+
var changed = tracker.GetChangedFiles(path);
5659

5760
foreach (var notFound in changed.Where(c => !redirects.ContainsKey(c)))
58-
collector.EmitError(notFound, $"{notFound} has been moved or deleted without a redirect rule being set for it. Please add a redirect rule in this project's {redirectFileInfo.Name}.");
61+
collector.EmitError(notFound, $"{notFound} does not have a redirect rule set. Please add a redirect rule in this project's {redirectFileInfo.Name}.");
5962

6063
await collector.StopAsync(ctx);
6164
return collector.Errors;

src/tooling/docs-builder/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
var app = ConsoleApp.Create();
1818
app.Add<Commands>();
1919
app.Add<InboundLinkCommands>("inbound-links");
20-
app.Add<ValidationCommands>("diff");
20+
app.Add<DiffCommands>("diff");
2121

2222
await app.RunAsync(args).ConfigureAwait(false);

src/tooling/docs-builder/Tracking/GitRepositoryTracker.cs

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/tooling/docs-builder/Tracking/IRepositoryTracker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ namespace Documentation.Builder.Tracking;
66

77
public interface IRepositoryTracker
88
{
9-
IEnumerable<string> GetChangedFiles();
9+
IEnumerable<string> GetChangedFiles(string lookupPath);
1010
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.IO.Abstractions;
6+
using Elastic.Documentation.Diagnostics;
7+
using Elastic.Documentation.Tooling.ExternalCommands;
8+
namespace Documentation.Builder.Tracking;
9+
10+
public partial class LocalGitRepositoryTracker(DiagnosticsCollector collector, IDirectoryInfo workingDirectory) : ExternalCommandExecutor(collector, workingDirectory), IRepositoryTracker
11+
{
12+
public IEnumerable<string> GetChangedFiles(string lookupPath)
13+
{
14+
var defaultBranch = GetDefaultBranch();
15+
var commitChanges = CaptureMultiple("git", "diff", "--name-status", $"{defaultBranch}...HEAD", "--", $"./{lookupPath}");
16+
var localChanges = CaptureMultiple("git", "status", "--porcelain");
17+
List<string> output = [
18+
.. commitChanges
19+
.Where(line => line.StartsWith('R') || line.StartsWith('D') || line.StartsWith('A'))
20+
.Select(line => line.Split('\t')[1]),
21+
.. localChanges
22+
.Select(x => x.TrimStart())
23+
.Where(line => line.StartsWith('R') || line.StartsWith('D') || line.StartsWith("A ", StringComparison.Ordinal) || line.StartsWith("??"))
24+
.Select(line => line.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)[1])
25+
];
26+
return output.Where(line => line.StartsWith(lookupPath));
27+
}
28+
29+
private string GetDefaultBranch()
30+
{
31+
if (!Capture(true, "git", "merge-base", "-a", "HEAD", "main").StartsWith("fatal", StringComparison.InvariantCulture))
32+
return "main";
33+
if (!Capture(true, "git", "merge-base", "-a", "HEAD", "master").StartsWith("fatal", StringComparison.InvariantCulture))
34+
return "master";
35+
return Capture("git", "symbolic-ref", "refs/remotes/origin/HEAD").Split('/').Last();
36+
}
37+
}

0 commit comments

Comments
 (0)