Skip to content

Commit cb4bc5b

Browse files
Mpdreamzclaude
andcommitted
refactor(cli): migrate file/directory path params to FileInfo and DirectoryInfo
- ElasticsearchIndexOptions.CertificatePath: string? -> FileInfo? [FileExtensions("pem,der,crt,cer")] - IsolatedBuildOptions.Path, Output: string? -> DirectoryInfo? - Codex config params (all four commands): string -> FileInfo [FileExtensions("yml,yaml")] - Codex output params: string? -> DirectoryInfo? - DeployCommands: planFile -> FileInfo [json], @out -> FileInfo?, redirectsFile -> FileInfo? [json] - CodexUpdateRedirectsCommand.redirectsFile: string? -> FileInfo? [json] - NavigationCommands.ValidateLinkReference file: string? -> FileInfo? [json] - InboundLinkCommands.ValidateLinkReference file: string? -> FileInfo? [json] - BloomFilterCommands.Create builtDocsDir: string -> DirectoryInfo - AssemblerCommands.Serve path: string? -> DirectoryInfo? - ServeCommand path: string? -> DirectoryInfo? - ChangelogCommand.Init path/changelogDir/bundlesDir: string? -> DirectoryInfo? - ChangelogCommand config params (Add, Bundle, Remove, Render, GhRelease, Upload, EvaluatePr): string? -> FileInfo? [yml,yaml] - ChangelogCommand directory params: string? -> DirectoryInfo? - ChangelogCommand.BundleAmend bundlePath: string -> FileInfo [yml,yaml] - Help text: path/file/dir params now show as <dir>, <file>, <path> with extension hints Tilde expansion report (params needing future argh [ExpandTilde] attribute): changelog init path/changelogDir/bundlesDir, all config params, all directory params, assembler deploy planFile/@out, CertificatePath, build Path/Output. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent e7d3111 commit cb4bc5b

16 files changed

Lines changed: 105 additions & 99 deletions

src/Elastic.Documentation.Configuration/ElasticsearchEndpointConfigurator.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ public record ElasticsearchIndexOptions
8888
public string? CertificateFingerprint { get; init; }
8989

9090
/// <summary>Path to a PEM or DER certificate file for SSL validation.</summary>
91-
public string? CertificatePath { get; init; }
91+
[FileExtensions(Extensions = "pem,der,crt,cer")]
92+
public FileInfo? CertificatePath { get; init; }
9293

9394
/// <summary>Set when the certificate is an intermediate CA rather than the root.</summary>
9495
public bool? CertificateNotRoot { get; init; }
@@ -138,11 +139,11 @@ public static async Task ApplyAsync(
138139
cfg.ProxyUsername = options.ProxyUsername;
139140
if (options.DisableSslVerification.HasValue)
140141
cfg.DisableSslVerification = options.DisableSslVerification.Value;
141-
if (!string.IsNullOrEmpty(options.CertificatePath))
142+
if (options.CertificatePath is not null)
142143
{
143-
if (!fileSystem.File.Exists(options.CertificatePath))
144-
collector.EmitGlobalError($"'{options.CertificatePath}' does not exist");
145-
var bytes = await fileSystem.File.ReadAllBytesAsync(options.CertificatePath, ctx);
144+
if (!fileSystem.File.Exists(options.CertificatePath.FullName))
145+
collector.EmitGlobalError($"'{options.CertificatePath.FullName}' does not exist");
146+
var bytes = await fileSystem.File.ReadAllBytesAsync(options.CertificatePath.FullName, ctx);
146147
cfg.Certificate = X509CertificateLoader.LoadCertificate(bytes);
147148
}
148149
if (options.CertificateNotRoot.HasValue)

src/services/Elastic.Documentation.Isolated/IsolatedBuildOptions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ namespace Elastic.Documentation.Isolated;
1111
public record IsolatedBuildOptions
1212
{
1313
/// <summary>-p, Root directory of the documentation source. Defaults to <c>cwd/docs</c>.</summary>
14-
public string? Path { get; init; }
14+
public DirectoryInfo? Path { get; init; }
1515

1616
/// <summary>-o, Destination for generated HTML. Defaults to <c>.artifacts/html</c>.</summary>
17-
public string? Output { get; init; }
17+
public DirectoryInfo? Output { get; init; }
1818

1919
/// <summary>URL path prefix prepended to every generated link.</summary>
2020
public string? PathPrefix { get; init; }

src/services/Elastic.Documentation.Isolated/IsolatedBuildService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public async Task<bool> Build(
5050
Cancel ctx = default
5151
)
5252
{
53-
var path = options.Path;
54-
var output = options.Output;
53+
var path = options.Path?.FullName;
54+
var output = options.Output?.FullName;
5555
var pathPrefix = options.PathPrefix;
5656
var force = options.Force;
5757
var strict = options.Strict;

src/services/Elastic.Documentation.Isolated/IsolatedIndexService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public async Task<bool> Index(
3535

3636
return await Build(collector, fileSystem, new IsolatedBuildOptions
3737
{
38-
Path = path,
38+
Path = path != null ? new DirectoryInfo(path) : null,
3939
MetadataOnly = true,
4040
Strict = false,
4141
Force = true,

src/tooling/docs-builder/Commands/Assembler/AssemblerCommands.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ static async (s, col, state, ctx) => await s.BuildAll(col, state.options, state.
157157
/// <param name="port">Port to listen on. Default: 4000.</param>
158158
/// <param name="path">Path to the built site. Defaults to <c>.artifacts/docs/</c>.</param>
159159
[NoOptionsInjection]
160-
public async Task Serve(int port = 4000, string? path = null, CancellationToken ct = default)
160+
public async Task Serve(int port = 4000, DirectoryInfo? path = null, CancellationToken ct = default)
161161
{
162-
var host = new StaticWebHost(port, path);
162+
var host = new StaticWebHost(port, path?.FullName);
163163
await host.RunAsync(ct);
164164
await host.StopAsync(ct);
165165
await collector.StopAsync(ct);

src/tooling/docs-builder/Commands/Assembler/BloomFilterCommands.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ internal sealed class BloomFilterCommands(ILoggerFactory logFactory, IDiagnostic
2222
/// </remarks>
2323
/// <param name="builtDocsDir">Path to the local legacy-docs repository checkout.</param>
2424
[NoOptionsInjection]
25-
public async Task<int> Create(string builtDocsDir, CancellationToken ct = default)
25+
public async Task<int> Create(DirectoryInfo builtDocsDir, CancellationToken ct = default)
2626
{
2727
await using var serviceInvoker = new ServiceInvoker(collector);
2828

29-
var pagesProvider = new LocalPagesProvider(builtDocsDir);
29+
var pagesProvider = new LocalPagesProvider(builtDocsDir.FullName);
3030
var legacyPageService = new LegacyPageService(logFactory);
3131

3232
serviceInvoker.AddCommand(legacyPageService, pagesProvider, static (s, _, pagesProvider, _) =>

src/tooling/docs-builder/Commands/Assembler/DeployCommands.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.ComponentModel.DataAnnotations;
56
using Actions.Core.Services;
67
using Elastic.Documentation;
78
using Elastic.Documentation.Assembler.Deploying;
@@ -33,13 +34,13 @@ ICoreService githubActionsService
3334
/// <param name="out">Path to write the plan file. Defaults to <c>stdout</c>.</param>
3435
/// <param name="deleteThreshold">Abort if the plan would delete more than this percentage of objects (0–100).</param>
3536
[NoOptionsInjection]
36-
public async Task<int> Plan(string environment, string s3BucketName, string @out = "", float? deleteThreshold = null, CancellationToken ct = default)
37+
public async Task<int> Plan(string environment, string s3BucketName, FileInfo? @out = null, float? deleteThreshold = null, CancellationToken ct = default)
3738
{
3839
await using var serviceInvoker = new ServiceInvoker(collector);
3940

4041
var service = new IncrementalDeployService(logFactory, assemblyConfiguration, configurationContext, githubActionsService, FileSystemFactory.RealRead, FileSystemFactory.RealWrite);
4142
serviceInvoker.AddCommand(service, (environment, s3BucketName, @out, deleteThreshold),
42-
static async (s, collector, state, ctx) => await s.Plan(collector, state.environment, state.s3BucketName, state.@out, state.deleteThreshold, ctx)
43+
static async (s, collector, state, ctx) => await s.Plan(collector, state.environment, state.s3BucketName, state.@out?.FullName ?? "", state.deleteThreshold, ctx)
4344
);
4445
return await serviceInvoker.InvokeAsync(ct);
4546
}
@@ -50,13 +51,13 @@ static async (s, collector, state, ctx) => await s.Plan(collector, state.environ
5051
/// <param name="s3BucketName">S3 bucket to deploy to.</param>
5152
/// <param name="planFile">Path to the plan file produced by <c>assembler deploy plan</c>.</param>
5253
[NoOptionsInjection]
53-
public async Task<int> Apply(string environment, string s3BucketName, string planFile, CancellationToken ct = default)
54+
public async Task<int> Apply(string environment, string s3BucketName, [FileExtensions(Extensions = "json")] FileInfo planFile, CancellationToken ct = default)
5455
{
5556
await using var serviceInvoker = new ServiceInvoker(collector);
5657

5758
var service = new IncrementalDeployService(logFactory, assemblyConfiguration, configurationContext, githubActionsService, FileSystemFactory.RealRead, FileSystemFactory.RealWrite);
5859
serviceInvoker.AddCommand(service, (environment, s3BucketName, planFile),
59-
static async (s, collector, state, ctx) => await s.Apply(collector, state.environment, state.s3BucketName, state.planFile, ctx)
60+
static async (s, collector, state, ctx) => await s.Apply(collector, state.environment, state.s3BucketName, state.planFile.FullName, ctx)
6061
);
6162
return await serviceInvoker.InvokeAsync(ct);
6263
}
@@ -66,14 +67,14 @@ static async (s, collector, state, ctx) => await s.Apply(collector, state.enviro
6667
/// <param name="environment">Named deployment target.</param>
6768
/// <param name="redirectsFile">Path to <c>redirects.json</c>. Defaults to <c>.artifacts/docs/redirects.json</c>.</param>
6869
[NoOptionsInjection]
69-
public async Task<int> UpdateRedirects(string environment, string? redirectsFile = null, CancellationToken ct = default)
70+
public async Task<int> UpdateRedirects(string environment, [FileExtensions(Extensions = "json")] FileInfo? redirectsFile = null, CancellationToken ct = default)
7071
{
7172
await using var serviceInvoker = new ServiceInvoker(collector);
7273

7374
var fs = FileSystemFactory.RealRead;
7475
var service = new DeployUpdateRedirectsService(logFactory, fs);
7576
serviceInvoker.AddCommand(service, (environment, redirectsFile),
76-
static async (s, collector, state, ctx) => await s.UpdateRedirects(collector, state.environment, state.redirectsFile, ctx: ctx)
77+
static async (s, collector, state, ctx) => await s.UpdateRedirects(collector, state.environment, state.redirectsFile?.FullName, ctx: ctx)
7778
);
7879
return await serviceInvoker.InvokeAsync(ct);
7980
}

src/tooling/docs-builder/Commands/Assembler/NavigationCommands.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33
// See the LICENSE file in the project root for more information
44

5+
using System.ComponentModel.DataAnnotations;
56
using System.IO.Abstractions;
67
using Elastic.Documentation;
78
using Elastic.Documentation.Assembler.Navigation;
@@ -35,11 +36,11 @@ public async Task<int> Validate(CancellationToken ct = default)
3536
/// <summary>Check that no link in a local <c>links.json</c> conflicts with a path prefix defined in <c>navigation.yml</c>.</summary>
3637
/// <param name="file">Path to <c>links.json</c>. Defaults to <c>.artifacts/docs/html/links.json</c>.</param>
3738
[NoOptionsInjection]
38-
public async Task<int> ValidateLinkReference([Argument] string? file = null, CancellationToken ct = default)
39+
public async Task<int> ValidateLinkReference([Argument, FileExtensions(Extensions = "json")] FileInfo? file = null, CancellationToken ct = default)
3940
{
4041
await using var serviceInvoker = new ServiceInvoker(collector);
4142
var service = new GlobalNavigationService(logFactory, configuration, configurationContext, FileSystemFactory.RealRead);
42-
serviceInvoker.AddCommand(service, file, static async (s, collector, file, ctx) => await s.ValidateLocalLinkReference(collector, file, ctx));
43+
serviceInvoker.AddCommand(service, file, static async (s, collector, file, ctx) => await s.ValidateLocalLinkReference(collector, file?.FullName, ctx));
4344
return await serviceInvoker.InvokeAsync(ct);
4445
}
4546
}

0 commit comments

Comments
 (0)