Skip to content

Commit ad18d2b

Browse files
Mpdreamzclaude
andcommitted
feat(tooling): upgrade to Nullean.Argh 0.11.0; add [Existing], [RejectSymbolicLinks], [ExpandUserProfile]
- Bump Nullean.Argh, Nullean.Argh.Hosting, Nullean.Argh.Interfaces to 0.11.0 - [Existing] on all input FileInfo/DirectoryInfo params that must be present: CertificatePath, all codex config files, changelog config/bundlePath, deploy planFile/redirectsFile, navigation/inbound-links file, bloom-filter builtDocsDir, serve path params, IsolatedBuildOptions.Path (source dir must exist) - [RejectSymbolicLinks] on every FileInfo/DirectoryInfo param and property - [ExpandUserProfile] on every FileInfo/DirectoryInfo param and property (fixes ~/path expansion for all path arguments) - IsolatedBuildOptions.Output intentionally omitted from [Existing] (created by build) - Codex and changelog output directories omitted from [Existing] (created by commands) Help output now shows: [existing] [no symlinks] [expand ~ profile] on appropriate args. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent cb4bc5b commit ad18d2b

13 files changed

Lines changed: 37 additions & 35 deletions

File tree

Directory.Packages.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@
6969
<PackageVersion Include="FSharp.Core" Version="10.1.201" />
7070
</ItemGroup>
7171
<ItemGroup>
72-
<PackageVersion Include="Nullean.Argh" Version="0.9.1" />
73-
<PackageVersion Include="Nullean.Argh.Hosting" Version="0.9.1" />
74-
<PackageVersion Include="Nullean.Argh.Interfaces" Version="0.9.1" />
72+
<PackageVersion Include="Nullean.Argh" Version="0.11.0" />
73+
<PackageVersion Include="Nullean.Argh.Hosting" Version="0.11.0" />
74+
<PackageVersion Include="Nullean.Argh.Interfaces" Version="0.11.0" />
7575
<PackageVersion Include="Crayon" Version="2.0.69" />
7676
<PackageVersion Include="DotNet.Glob" Version="3.1.3" />
7777
<PackageVersion Include="Errata" Version="0.16.0" />

src/Elastic.Documentation.Configuration/ElasticsearchEndpointConfigurator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ 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-
[FileExtensions(Extensions = "pem,der,crt,cer")]
91+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "pem,der,crt,cer")]
9292
public FileInfo? CertificatePath { get; init; }
9393

9494
/// <summary>Set when the certificate is an intermediate CA rather than the root.</summary>

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ 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+
[Existing, ExpandUserProfile, RejectSymbolicLinks]
1415
public DirectoryInfo? Path { get; init; }
1516

1617
/// <summary>-o, Destination for generated HTML. Defaults to <c>.artifacts/html</c>.</summary>
18+
[ExpandUserProfile, RejectSymbolicLinks]
1719
public DirectoryInfo? Output { get; init; }
1820

1921
/// <summary>URL path prefix prepended to every generated link.</summary>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ 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, DirectoryInfo? path = null, CancellationToken ct = default)
160+
public async Task Serve(int port = 4000, [Existing, ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? path = null, CancellationToken ct = default)
161161
{
162162
var host = new StaticWebHost(port, path?.FullName);
163163
await host.RunAsync(ct);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ 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(DirectoryInfo builtDocsDir, CancellationToken ct = default)
25+
public async Task<int> Create([Existing, ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo builtDocsDir, CancellationToken ct = default)
2626
{
2727
await using var serviceInvoker = new ServiceInvoker(collector);
2828

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ ICoreService githubActionsService
3434
/// <param name="out">Path to write the plan file. Defaults to <c>stdout</c>.</param>
3535
/// <param name="deleteThreshold">Abort if the plan would delete more than this percentage of objects (0–100).</param>
3636
[NoOptionsInjection]
37-
public async Task<int> Plan(string environment, string s3BucketName, FileInfo? @out = null, float? deleteThreshold = null, CancellationToken ct = default)
37+
public async Task<int> Plan(string environment, string s3BucketName, [ExpandUserProfile, RejectSymbolicLinks] FileInfo? @out = null, float? deleteThreshold = null, CancellationToken ct = default)
3838
{
3939
await using var serviceInvoker = new ServiceInvoker(collector);
4040

@@ -51,7 +51,7 @@ static async (s, collector, state, ctx) => await s.Plan(collector, state.environ
5151
/// <param name="s3BucketName">S3 bucket to deploy to.</param>
5252
/// <param name="planFile">Path to the plan file produced by <c>assembler deploy plan</c>.</param>
5353
[NoOptionsInjection]
54-
public async Task<int> Apply(string environment, string s3BucketName, [FileExtensions(Extensions = "json")] FileInfo planFile, CancellationToken ct = default)
54+
public async Task<int> Apply(string environment, string s3BucketName, [Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "json")] FileInfo planFile, CancellationToken ct = default)
5555
{
5656
await using var serviceInvoker = new ServiceInvoker(collector);
5757

@@ -67,7 +67,7 @@ static async (s, collector, state, ctx) => await s.Apply(collector, state.enviro
6767
/// <param name="environment">Named deployment target.</param>
6868
/// <param name="redirectsFile">Path to <c>redirects.json</c>. Defaults to <c>.artifacts/docs/redirects.json</c>.</param>
6969
[NoOptionsInjection]
70-
public async Task<int> UpdateRedirects(string environment, [FileExtensions(Extensions = "json")] FileInfo? redirectsFile = null, CancellationToken ct = default)
70+
public async Task<int> UpdateRedirects(string environment, [Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "json")] FileInfo? redirectsFile = null, CancellationToken ct = default)
7171
{
7272
await using var serviceInvoker = new ServiceInvoker(collector);
7373

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public async Task<int> Validate(CancellationToken ct = default)
3636
/// <summary>Check that no link in a local <c>links.json</c> conflicts with a path prefix defined in <c>navigation.yml</c>.</summary>
3737
/// <param name="file">Path to <c>links.json</c>. Defaults to <c>.artifacts/docs/html/links.json</c>.</param>
3838
[NoOptionsInjection]
39-
public async Task<int> ValidateLinkReference([Argument, FileExtensions(Extensions = "json")] FileInfo? file = null, CancellationToken ct = default)
39+
public async Task<int> ValidateLinkReference([Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "json")] FileInfo? file = null, CancellationToken ct = default)
4040
{
4141
await using var serviceInvoker = new ServiceInvoker(collector);
4242
var service = new GlobalNavigationService(logFactory, configuration, configurationContext, FileSystemFactory.RealRead);

src/tooling/docs-builder/Commands/ChangelogCommand.cs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ IEnvironmentVariables environmentVariables
5757
/// <param name="repo">GitHub repository name for seeding bundle defaults. Overrides the value inferred from git remote origin.</param>
5858
[NoOptionsInjection]
5959
public Task<int> Init(
60-
DirectoryInfo? path = null,
61-
DirectoryInfo? changelogDir = null,
62-
DirectoryInfo? bundlesDir = null,
60+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? path = null,
61+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? changelogDir = null,
62+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? bundlesDir = null,
6363
string? owner = null,
6464
string? repo = null
6565
)
@@ -238,7 +238,7 @@ public async Task<int> Add(
238238
string? action = null,
239239
string[]? areas = null,
240240
bool concise = false,
241-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
241+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
242242
string? description = null,
243243
bool noExtractReleaseNotes = false,
244244
bool noExtractIssues = false,
@@ -514,8 +514,8 @@ public async Task<int> Bundle(
514514
[Argument] string? profileArg = null,
515515
[Argument] string? profileReport = null,
516516
bool all = false,
517-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
518-
DirectoryInfo? directory = null,
517+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
518+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? directory = null,
519519
string? description = null,
520520
string[]? hideFeatures = null,
521521
bool noReleaseDate = false,
@@ -880,9 +880,9 @@ public async Task<int> Remove(
880880
[Argument] string? profileArg = null,
881881
[Argument] string? profileReport = null,
882882
bool all = false,
883-
DirectoryInfo? bundlesDir = null,
884-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
885-
DirectoryInfo? directory = null,
883+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? bundlesDir = null,
884+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
885+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? directory = null,
886886
bool dryRun = false,
887887
bool force = false,
888888
string[]? issues = null,
@@ -1096,7 +1096,7 @@ async static (s, collector, state, ctx) => await s.RemoveChangelogs(collector, s
10961096
[NoOptionsInjection]
10971097
public async Task<int> Render(
10981098
string[]? input = null,
1099-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
1099+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
11001100
string? fileType = "markdown",
11011101
string[]? hideFeatures = null,
11021102
string? output = null,
@@ -1159,7 +1159,7 @@ async static (s, collector, state, ctx) => await s.RenderChangelogs(collector, s
11591159
public async Task<int> GhRelease(
11601160
[Argument] string repo,
11611161
[Argument] string version = "latest",
1162-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
1162+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
11631163
string? description = null,
11641164
string? output = null,
11651165
string? releaseDate = null,
@@ -1216,7 +1216,7 @@ async static (s, collector, state, ctx) => await s.CreateChangelogsFromRelease(c
12161216
/// <param name="resolve">Optional: Copy the contents of each changelog file into the entries array. Use --no-resolve to explicitly turn off resolve (overrides inference from original bundle).</param>
12171217
[NoOptionsInjection]
12181218
public async Task<int> BundleAmend(
1219-
[Argument, FileExtensions(Extensions = "yml,yaml")] FileInfo bundlePath,
1219+
[Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo bundlePath,
12201220
string[]? add = null,
12211221
bool? resolve = null,
12221222
CancellationToken ct = default
@@ -1388,8 +1388,8 @@ public async Task<int> Upload(
13881388
string artifactType,
13891389
string target,
13901390
string s3BucketName = "",
1391-
[FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
1392-
DirectoryInfo? directory = null,
1391+
[Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo? config = null,
1392+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? directory = null,
13931393
CancellationToken ct = default
13941394
)
13951395
{

src/tooling/docs-builder/Commands/Codex/CodexCommands.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ IEnvironmentVariables environmentVariables
4949
[DefaultCommand]
5050
public async Task<int> CloneAndBuild(
5151
GlobalCliOptions _,
52-
[Argument, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
52+
[Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
5353
bool strict = false,
5454
bool fetchLatest = false,
5555
bool assumeCloned = false,
56-
DirectoryInfo? output = null,
56+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? output = null,
5757
bool serve = false,
5858
CancellationToken ct = default)
5959
{
@@ -121,7 +121,7 @@ public async Task<int> CloneAndBuild(
121121
/// <param name="assumeCloned">Skip cloning; assume repositories are already on disk.</param>
122122
[NoOptionsInjection]
123123
public async Task<int> Clone(
124-
[Argument, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
124+
[Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
125125
bool strict = false,
126126
bool fetchLatest = false,
127127
bool assumeCloned = false,
@@ -169,9 +169,9 @@ public async Task<int> Clone(
169169
/// <param name="output">Output directory. Defaults to <c>.artifacts/codex/</c>.</param>
170170
[NoOptionsInjection]
171171
public async Task<int> Build(
172-
[Argument, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
172+
[Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
173173
bool strict = false,
174-
DirectoryInfo? output = null,
174+
[ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? output = null,
175175
CancellationToken ct = default)
176176
{
177177
await using var serviceInvoker = new ServiceInvoker(collector);
@@ -221,7 +221,7 @@ public async Task<int> Build(
221221
/// <param name="port">Port to listen on. Default: 4000.</param>
222222
/// <param name="path">Path to the portal output. Defaults to <c>.artifacts/codex/docs/</c>.</param>
223223
[NoOptionsInjection]
224-
public async Task Serve(int port = 4000, DirectoryInfo? path = null, CancellationToken ct = default)
224+
public async Task Serve(int port = 4000, [Existing, ExpandUserProfile, RejectSymbolicLinks] DirectoryInfo? path = null, CancellationToken ct = default)
225225
{
226226
var fs = FileSystemFactory.RealRead;
227227
var servePath = path?.FullName ?? fs.Path.Join(Environment.CurrentDirectory, ".artifacts", "codex", "docs");

src/tooling/docs-builder/Commands/Codex/CodexIndexCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ IEnvironmentVariables environmentVariables
3737
/// <param name="config">Path to the <c>codex.yml</c> configuration file.</param>
3838
public async Task<int> Index(
3939
GlobalCliOptions _,
40-
[Argument, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
40+
[Argument, Existing, ExpandUserProfile, RejectSymbolicLinks, FileExtensions(Extensions = "yml,yaml")] FileInfo config,
4141
[AsParameters] ElasticsearchIndexOptions es,
4242
CancellationToken ct = default
4343
)

0 commit comments

Comments
 (0)