From 18730b4edefe761f794d556c62fd3527ffe2a71f Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 1 May 2025 12:46:24 +0200 Subject: [PATCH 1/2] Refactor our usage of DiagnosticCollector --- .../YamlStreamReader.cs | 8 ++-- .../Diagnostics/DiagnosticsCollector.cs | 23 ++++++++--- .../Diagnostics/IDiagnosticsCollector.cs | 40 +++++++++++++++++++ .../IDocumentationContext.cs | 2 +- src/Elastic.Markdown/BuildContext.cs | 9 ++--- .../ProcessorDiagnosticExtensions.cs | 12 +++--- .../DocumentationGenerator.cs | 12 ------ src/Elastic.Markdown/Helpers/Interpolation.cs | 4 +- src/Elastic.Markdown/IO/MarkdownFile.cs | 2 +- .../InboundLinks/LinkIndexLinkChecker.cs | 30 ++++++-------- .../Building/AssemblerBuilder.cs | 1 - .../docs-assembler/Cli/InboundLinkCommands.cs | 18 ++++++--- .../docs-assembler/Cli/NavigationCommands.cs | 3 -- .../docs-assembler/Cli/RepositoryCommands.cs | 6 ++- src/tooling/docs-builder/Cli/Commands.cs | 20 +++++----- .../docs-builder/Cli/InboundLinkCommands.cs | 18 ++++++--- .../docs-builder/Http/DocumentationWebHost.cs | 8 ++-- .../docs-builder/Http/StaticWebHost.cs | 11 ++--- .../Directives/DirectiveBaseTests.cs | 1 - .../Inline/InlneBaseTests.cs | 1 - .../OutputDirectoryTests.cs | 6 ++- tests/authoring/Framework/TestValues.fs | 2 +- 22 files changed, 139 insertions(+), 98 deletions(-) create mode 100644 src/Elastic.Documentation/Diagnostics/IDiagnosticsCollector.cs diff --git a/src/Elastic.Documentation.Configuration/YamlStreamReader.cs b/src/Elastic.Documentation.Configuration/YamlStreamReader.cs index 7e88b6008..9148e016d 100644 --- a/src/Elastic.Documentation.Configuration/YamlStreamReader.cs +++ b/src/Elastic.Documentation.Configuration/YamlStreamReader.cs @@ -16,10 +16,10 @@ public record YamlToplevelKey public required KeyValuePair Entry { get; init; } } -public class YamlStreamReader(IFileInfo source, DiagnosticsCollector collector) +public class YamlStreamReader(IFileInfo source, IDiagnosticsCollector collector) { private IFileInfo Source { get; init; } = source; - private DiagnosticsCollector Collector { get; init; } = collector; + private IDiagnosticsCollector Collector { get; init; } = collector; public IEnumerable Read() { @@ -185,7 +185,7 @@ private void EmitError(string message, Mark? start = null, Mark? end = null, int Column = start.HasValue ? (int)start.Value.Column : null, Length = length }; - Collector.Channel.Write(d); + Collector.Write(d); } public void EmitWarning(string message, Mark? start = null, Mark? end = null, int? length = null) { @@ -199,6 +199,6 @@ public void EmitWarning(string message, Mark? start = null, Mark? end = null, in Column = start.HasValue ? (int)start.Value.Column : null, Length = length }; - Collector.Channel.Write(d); + Collector.Write(d); } } diff --git a/src/Elastic.Documentation/Diagnostics/DiagnosticsCollector.cs b/src/Elastic.Documentation/Diagnostics/DiagnosticsCollector.cs index 84144ba46..9859dd8e2 100644 --- a/src/Elastic.Documentation/Diagnostics/DiagnosticsCollector.cs +++ b/src/Elastic.Documentation/Diagnostics/DiagnosticsCollector.cs @@ -8,9 +8,10 @@ namespace Elastic.Documentation.Diagnostics; -public class DiagnosticsCollector(IReadOnlyCollection outputs) : IHostedService, IAsyncDisposable +public class DiagnosticsCollector(IReadOnlyCollection outputs) + : IDiagnosticsCollector, IHostedService { - public DiagnosticsChannel Channel { get; } = new(); + private DiagnosticsChannel Channel { get; } = new(); private int _errors; private int _warnings; @@ -29,7 +30,13 @@ public class DiagnosticsCollector(IReadOnlyCollection output public bool NoHints { get; init; } - public Task StartAsync(Cancel cancellationToken) + public DiagnosticsCollector StartAsync(Cancel ctx) + { + _ = ((IHostedService)this).StartAsync(ctx); + return this; + } + + Task IHostedService.StartAsync(Cancel cancellationToken) { if (_started is not null) return _started; @@ -59,7 +66,6 @@ void Drain() { if (item.Severity == Severity.Hint && NoHints) continue; - IncrementSeverityCount(item); HandleItem(item); _ = OffendingFiles.Add(item.File); foreach (var output in outputs) @@ -82,6 +88,7 @@ protected virtual void HandleItem(Diagnostic diagnostic) { } public virtual async Task StopAsync(Cancel cancellationToken) { + Channel.TryComplete(); if (_started is not null) await _started; await Channel.Reader.Completion; @@ -89,8 +96,14 @@ public virtual async Task StopAsync(Cancel cancellationToken) public void EmitCrossLink(string link) => CrossLinks.Add(link); + public void Write(Diagnostic diagnostic) + { + IncrementSeverityCount(diagnostic); + Channel.Write(diagnostic); + } + private void Emit(Severity severity, string file, string message) => - Channel.Write(new Diagnostic + Write(new Diagnostic { Severity = severity, File = file, diff --git a/src/Elastic.Documentation/Diagnostics/IDiagnosticsCollector.cs b/src/Elastic.Documentation/Diagnostics/IDiagnosticsCollector.cs new file mode 100644 index 000000000..fc98220dd --- /dev/null +++ b/src/Elastic.Documentation/Diagnostics/IDiagnosticsCollector.cs @@ -0,0 +1,40 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.Concurrent; +using System.IO.Abstractions; + +namespace Elastic.Documentation.Diagnostics; + +public interface IDiagnosticsCollector : IAsyncDisposable +{ + int Warnings { get; } + int Errors { get; } + int Hints { get; } + + ConcurrentBag CrossLinks { get; } + HashSet OffendingFiles { get; } + ConcurrentDictionary InUseSubstitutionKeys { get; } + + void EmitError(string file, string message, Exception? e = null); + void EmitWarning(string file, string message); + void EmitHint(string file, string message); + void Write(Diagnostic diagnostic); + void CollectUsedSubstitutionKey(ReadOnlySpan key); + void EmitCrossLink(string link); +} + +public static class DiagnosticsCollectorExtensions +{ + public static void EmitError(this IDiagnosticsCollector collector, IFileInfo file, string message, Exception? e = null) => + collector.EmitError(file.FullName, message, e); + + public static void EmitWarning(this IDiagnosticsCollector collector, IFileInfo file, string message) => + collector.EmitWarning(file.FullName, message); + + public static void EmitHint(this IDiagnosticsCollector collector, IFileInfo file, string message) => + collector.EmitHint(file.FullName, message); +} + + diff --git a/src/Elastic.Documentation/IDocumentationContext.cs b/src/Elastic.Documentation/IDocumentationContext.cs index c23aa0d8d..cfbff226f 100644 --- a/src/Elastic.Documentation/IDocumentationContext.cs +++ b/src/Elastic.Documentation/IDocumentationContext.cs @@ -9,7 +9,7 @@ namespace Elastic.Documentation; public interface IDocumentationContext { - DiagnosticsCollector Collector { get; } + IDiagnosticsCollector Collector { get; } IDirectoryInfo DocumentationSourceDirectory { get; } GitCheckoutInformation Git { get; } IFileSystem ReadFileSystem { get; } diff --git a/src/Elastic.Markdown/BuildContext.cs b/src/Elastic.Markdown/BuildContext.cs index fdb6a65ed..e4a04b046 100644 --- a/src/Elastic.Markdown/BuildContext.cs +++ b/src/Elastic.Markdown/BuildContext.cs @@ -26,7 +26,7 @@ public record BuildContext : IDocumentationContext public GitCheckoutInformation Git { get; } - public DiagnosticsCollector Collector { get; } + public IDiagnosticsCollector Collector { get; } public bool Force { get; init; } @@ -47,14 +47,11 @@ public string? UrlPathPrefix init => _urlPathPrefix = value; } - public BuildContext(IFileSystem fileSystem) - : this(new DiagnosticsCollector([]), fileSystem, fileSystem, null, null) { } - - public BuildContext(DiagnosticsCollector collector, IFileSystem fileSystem) + public BuildContext(IDiagnosticsCollector collector, IFileSystem fileSystem) : this(collector, fileSystem, fileSystem, null, null) { } public BuildContext( - DiagnosticsCollector collector, + IDiagnosticsCollector collector, IFileSystem readFileSystem, IFileSystem writeFileSystem, string? source = null, diff --git a/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs b/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs index 9825671a5..fefe25d45 100644 --- a/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs +++ b/src/Elastic.Markdown/Diagnostics/ProcessorDiagnosticExtensions.cs @@ -30,7 +30,7 @@ public static void EmitError(this InlineProcessor processor, int line, int colum Message = message, Length = length }; - context.Build.Collector.Channel.Write(d); + context.Build.Collector.Write(d); } @@ -48,7 +48,7 @@ public static void EmitWarning(this InlineProcessor processor, int line, int col Message = message, Length = length }; - context.Build.Collector.Channel.Write(d); + context.Build.Collector.Write(d); } public static void EmitError(this ParserContext context, string message, Exception? e = null) @@ -61,7 +61,7 @@ public static void EmitError(this ParserContext context, string message, Excepti File = context.MarkdownSourcePath.FullName, Message = CreateExceptionMessage(message, e), }; - context.Build.Collector.Channel.Write(d); + context.Build.Collector.Write(d); } public static void EmitWarning(this ParserContext context, int line, int column, int length, string message) @@ -77,7 +77,7 @@ public static void EmitWarning(this ParserContext context, int line, int column, Message = message, Length = length }; - context.Build.Collector.Channel.Write(d); + context.Build.Collector.Write(d); } public static void EmitError(this IBlockExtension block, string message, Exception? e = null) => EmitDiagnostic(block, Severity.Error, message, e); @@ -100,7 +100,7 @@ private static void EmitDiagnostic(IBlockExtension block, Severity severity, str Length = block.OpeningLength + 5, Message = CreateExceptionMessage(message, e), }; - block.Build.Collector.Channel.Write(d); + block.Build.Collector.Write(d); } @@ -121,7 +121,7 @@ private static void LinkDiagnostic(InlineProcessor processor, Severity severity, Message = CreateExceptionMessage(message, e), Length = Math.Max(length, 1) }; - context.Build.Collector.Channel.Write(d); + context.Build.Collector.Write(d); } public static void EmitError(this InlineProcessor processor, LinkInline inline, string message) => diff --git a/src/Elastic.Markdown/DocumentationGenerator.cs b/src/Elastic.Markdown/DocumentationGenerator.cs index 882365cb0..44916bd7c 100644 --- a/src/Elastic.Markdown/DocumentationGenerator.cs +++ b/src/Elastic.Markdown/DocumentationGenerator.cs @@ -117,23 +117,11 @@ public async Task GenerateAll(Cancel ctx) await GenerateLinkReference(ctx); } - public async Task StopDiagnosticCollection(Cancel ctx) - { - _logger.LogInformation($"Completing diagnostics channel"); - Context.Collector.Channel.TryComplete(); - - _logger.LogInformation($"Stopping diagnostics collector"); - await Context.Collector.StopAsync(ctx); - - _logger.LogInformation($"Completed diagnostics channel"); - } - private async Task ProcessDocumentationFiles(HashSet offendingFiles, DateTimeOffset outputSeenChanges, Cancel ctx) { var processedFileCount = 0; var exceptionCount = 0; var totalFileCount = DocumentationSet.Files.Count; - _ = Context.Collector.StartAsync(ctx); await Parallel.ForEachAsync(DocumentationSet.Files, ctx, async (file, token) => { var processedFiles = Interlocked.Increment(ref processedFileCount); diff --git a/src/Elastic.Markdown/Helpers/Interpolation.cs b/src/Elastic.Markdown/Helpers/Interpolation.cs index 332c5e172..48ffee0f7 100644 --- a/src/Elastic.Markdown/Helpers/Interpolation.cs +++ b/src/Elastic.Markdown/Helpers/Interpolation.cs @@ -31,7 +31,7 @@ ParserContext context public static bool ReplaceSubstitutions( this ReadOnlySpan span, IReadOnlyDictionary? properties, - DiagnosticsCollector? collector, + IDiagnosticsCollector? collector, [NotNullWhen(true)] out string? replacement ) { @@ -43,7 +43,7 @@ public static bool ReplaceSubstitutions( private static bool ReplaceSubstitutions( this ReadOnlySpan span, IReadOnlyDictionary[] properties, - DiagnosticsCollector? collector, + IDiagnosticsCollector? collector, [NotNullWhen(true)] out string? replacement ) { diff --git a/src/Elastic.Markdown/IO/MarkdownFile.cs b/src/Elastic.Markdown/IO/MarkdownFile.cs index d5a68ed7d..f11e1d6f4 100644 --- a/src/Elastic.Markdown/IO/MarkdownFile.cs +++ b/src/Elastic.Markdown/IO/MarkdownFile.cs @@ -66,7 +66,7 @@ DocumentationSet set public string Id { get; } = Guid.NewGuid().ToString("N")[..8]; - private DiagnosticsCollector Collector { get; } + private IDiagnosticsCollector Collector { get; } public bool Hidden { get; internal set; } public string? UrlPathPrefix { get; } diff --git a/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs index 3a5ba457d..d5a24b0b5 100644 --- a/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs +++ b/src/Elastic.Markdown/Links/InboundLinks/LinkIndexLinkChecker.cs @@ -17,22 +17,22 @@ public class LinkIndexLinkChecker(ILoggerFactory logger) private sealed record RepositoryFilter { - public string? LinksTo { get; set; } - public string? LinksFrom { get; set; } + public string? LinksTo { get; init; } + public string? LinksFrom { get; init; } public static RepositoryFilter None => new(); } - public async Task CheckAll(DiagnosticsCollector collector, Cancel ctx) + public async Task CheckAll(IDiagnosticsCollector collector, Cancel ctx) { var fetcher = new LinksIndexCrossLinkFetcher(logger); var resolver = new CrossLinkResolver(fetcher); var crossLinks = await resolver.FetchLinks(ctx); - return await ValidateCrossLinks(collector, crossLinks, resolver, RepositoryFilter.None, ctx); + ValidateCrossLinks(collector, crossLinks, resolver, RepositoryFilter.None); } - public async Task CheckRepository(DiagnosticsCollector collector, string? toRepository, string? fromRepository, Cancel ctx) + public async Task CheckRepository(IDiagnosticsCollector collector, string? toRepository, string? fromRepository, Cancel ctx) { var fetcher = new LinksIndexCrossLinkFetcher(logger); var resolver = new CrossLinkResolver(fetcher); @@ -43,10 +43,10 @@ public async Task CheckRepository(DiagnosticsCollector collector, string? t LinksFrom = fromRepository }; - return await ValidateCrossLinks(collector, crossLinks, resolver, filter, ctx); + ValidateCrossLinks(collector, crossLinks, resolver, filter); } - public async Task CheckWithLocalLinksJson(DiagnosticsCollector collector, string repository, string localLinksJson, Cancel ctx) + public async Task CheckWithLocalLinksJson(IDiagnosticsCollector collector, string repository, string localLinksJson, Cancel ctx) { var fetcher = new LinksIndexCrossLinkFetcher(logger); var resolver = new CrossLinkResolver(fetcher); @@ -80,17 +80,16 @@ public async Task CheckWithLocalLinksJson(DiagnosticsCollector collector, s LinksTo = repository }; - return await ValidateCrossLinks(collector, crossLinks, resolver, filter, ctx); + ValidateCrossLinks(collector, crossLinks, resolver, filter); } - private async Task ValidateCrossLinks( - DiagnosticsCollector collector, + private void ValidateCrossLinks( + IDiagnosticsCollector collector, FetchedCrossLinks crossLinks, CrossLinkResolver resolver, - RepositoryFilter filter, - Cancel ctx) + RepositoryFilter filter + ) { - _ = collector.StartAsync(ctx); foreach (var (repository, linkReference) in crossLinks.LinkReferences) { if (!string.IsNullOrEmpty(filter.LinksTo)) @@ -130,11 +129,6 @@ private async Task ValidateCrossLinks( }, s => collector.EmitWarning(linksJson, s), uri, out _); } } - - collector.Channel.TryComplete(); - await collector.StopAsync(ctx); // non-strict for now - return collector.Errors; - // return collector.Errors + collector.Warnings; } } diff --git a/src/tooling/docs-assembler/Building/AssemblerBuilder.cs b/src/tooling/docs-assembler/Building/AssemblerBuilder.cs index c4e42c7c3..54c97ab44 100644 --- a/src/tooling/docs-assembler/Building/AssemblerBuilder.cs +++ b/src/tooling/docs-assembler/Building/AssemblerBuilder.cs @@ -53,7 +53,6 @@ public async Task BuildAllAsync(FrozenDictionary ValidateAllInboundLinks(Cancel ctx = default) { AssignOutputLogger(); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckAll(collector, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckAll(collector, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } /// Validate all published cross_links in all published links.json files. @@ -52,8 +54,10 @@ public async Task ValidateRepoInboundLinks(string? from = null, string? to if (from == null) throw new Exception("Unable to determine repository name"); } - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckRepository(collector, to, from, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckRepository(collector, to, from, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } /// @@ -71,7 +75,9 @@ public async Task ValidateLocalLinkReference([Argument] string? file = null var repository = GitCheckoutInformation.Create(root, new FileSystem(), logger.CreateLogger(nameof(GitCheckoutInformation))).RepositoryName ?? throw new Exception("Unable to determine repository name"); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckWithLocalLinksJson(collector, repository, file, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckWithLocalLinksJson(collector, repository, file, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } } diff --git a/src/tooling/docs-assembler/Cli/NavigationCommands.cs b/src/tooling/docs-assembler/Cli/NavigationCommands.cs index 64deccc8c..b9ac0bc4a 100644 --- a/src/tooling/docs-assembler/Cli/NavigationCommands.cs +++ b/src/tooling/docs-assembler/Cli/NavigationCommands.cs @@ -41,7 +41,6 @@ public async Task Validate(Cancel ctx = default) // this validates all path prefixes are unique, early exit if duplicates are detected if (!GlobalNavigationFile.ValidatePathPrefixes(assembleContext) || assembleContext.Collector.Errors > 0) { - assembleContext.Collector.Channel.TryComplete(); await assembleContext.Collector.StopAsync(ctx); return 1; } @@ -50,7 +49,6 @@ public async Task Validate(Cancel ctx = default) await namespaceChecker.CheckAllPublishedLinks(assembleContext.Collector, ctx); - assembleContext.Collector.Channel.TryComplete(); await assembleContext.Collector.StopAsync(ctx); return collector.Errors; } @@ -80,7 +78,6 @@ public async Task ValidateLocalLinkReference([Argument] string? file = null await namespaceChecker.CheckWithLocalLinksJson(assembleContext.Collector, repository, file, ctx); - assembleContext.Collector.Channel.TryComplete(); await assembleContext.Collector.StopAsync(ctx); return collector.Errors; } diff --git a/src/tooling/docs-assembler/Cli/RepositoryCommands.cs b/src/tooling/docs-assembler/Cli/RepositoryCommands.cs index 703684489..2e0c7aafc 100644 --- a/src/tooling/docs-assembler/Cli/RepositoryCommands.cs +++ b/src/tooling/docs-assembler/Cli/RepositoryCommands.cs @@ -96,7 +96,6 @@ public async Task BuildAll( // this validates all path prefixes are unique, early exit if duplicates are detected if (!GlobalNavigationFile.ValidatePathPrefixes(assembleContext) || assembleContext.Collector.Errors > 0) { - assembleContext.Collector.Channel.TryComplete(); await assembleContext.Collector.StopAsync(ctx); return 1; } @@ -122,6 +121,8 @@ public async Task BuildAll( var sitemapBuilder = new SitemapBuilder(navigation.NavigationItems, assembleContext.WriteFileSystem, assembleContext.OutputDirectory); sitemapBuilder.Generate(); + await collector.StopAsync(ctx); + if (strict ?? false) return collector.Errors + collector.Warnings; return collector.Errors; @@ -186,6 +187,9 @@ await Parallel.ForEachAsync(repositories, collector.EmitError(kv.Key, $"Failed to update link index for {kv.Key}: {e.Message}", e); } }).ConfigureAwait(false); + + await collector.StopAsync(ctx); + return collector.Errors > 0 ? 1 : 0; } } diff --git a/src/tooling/docs-builder/Cli/Commands.cs b/src/tooling/docs-builder/Cli/Commands.cs index f567a2a1a..be4211b51 100644 --- a/src/tooling/docs-builder/Cli/Commands.cs +++ b/src/tooling/docs-builder/Cli/Commands.cs @@ -49,17 +49,14 @@ public async Task Serve(string? path = null, int port = 3000, Cancel ctx = defau /// /// Serve html files directly /// - /// -p, Path to serve the documentation. - /// Defaults to the`{pwd}/docs` folder - /// /// Port to serve the documentation. /// [Command("serve-static")] [ConsoleAppFilter] - public async Task ServeStatic(string? path = null, int port = 4000, Cancel ctx = default) + public async Task ServeStatic(int port = 4000, Cancel ctx = default) { AssignOutputLogger(); - var host = new StaticWebHost(path, port, new FileSystem()); + var host = new StaticWebHost(port); await host.RunAsync(ctx); await host.StopAsync(ctx); } @@ -97,7 +94,7 @@ public async Task Generate( AssignOutputLogger(); pathPrefix ??= githubActionsService.GetInput("prefix"); var fileSystem = new FileSystem(); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); var runningOnCi = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("GITHUB_ACTIONS")); BuildContext context; @@ -157,12 +154,13 @@ public async Task Generate( var generator = new DocumentationGenerator(set, logger, null, null, exporter); await generator.GenerateAll(ctx); - await generator.StopDiagnosticCollection(ctx); + if (runningOnCi) await githubActionsService.SetOutputAsync("landing-page-path", set.MarkdownFiles.First().Value.Url); + + await collector.StopAsync(ctx); if (bool.TryParse(githubActionsService.GetInput("strict"), out var strictValue) && strictValue) strict ??= strictValue; - if (strict ?? false) return context.Collector.Errors + context.Collector.Warnings; return context.Collector.Errors; @@ -220,11 +218,13 @@ public async Task Move( { AssignOutputLogger(); var fileSystem = new FileSystem(); - await using var collector = new ConsoleDiagnosticsCollector(logger, null); + await using var collector = new ConsoleDiagnosticsCollector(logger, null).StartAsync(ctx); var context = new BuildContext(collector, fileSystem, fileSystem, path, null); var set = new DocumentationSet(context, logger); var moveCommand = new Move(fileSystem, fileSystem, set, logger); - return await moveCommand.Execute(source, target, dryRun ?? false, ctx); + var result = await moveCommand.Execute(source, target, dryRun ?? false, ctx); + await collector.StopAsync(ctx); + return result; } } diff --git a/src/tooling/docs-builder/Cli/InboundLinkCommands.cs b/src/tooling/docs-builder/Cli/InboundLinkCommands.cs index 7463a854a..5de07d6a0 100644 --- a/src/tooling/docs-builder/Cli/InboundLinkCommands.cs +++ b/src/tooling/docs-builder/Cli/InboundLinkCommands.cs @@ -35,8 +35,10 @@ private void AssignOutputLogger() public async Task ValidateAllInboundLinks(Cancel ctx = default) { AssignOutputLogger(); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckAll(collector, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckAll(collector, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } /// Validate a single repository against the published cross_links in all published links.json files. @@ -57,8 +59,10 @@ public async Task ValidateRepoInboundLinks(string? from = null, string? to if (from == null) throw new Exception("Unable to determine repository name"); } - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckRepository(collector, to, from, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckRepository(collector, to, from, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } /// @@ -78,7 +82,9 @@ public async Task ValidateLocalLinkReference([Argument] string? file = null var repository = GitCheckoutInformation.Create(root, new FileSystem(), logger.CreateLogger(nameof(GitCheckoutInformation))).RepositoryName ?? throw new Exception("Unable to determine repository name"); - await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService); - return await _linkIndexLinkChecker.CheckWithLocalLinksJson(collector, repository, file, ctx); + await using var collector = new ConsoleDiagnosticsCollector(logger, githubActionsService).StartAsync(ctx); + await _linkIndexLinkChecker.CheckWithLocalLinksJson(collector, repository, file, ctx); + await collector.StopAsync(ctx); + return collector.Errors; } } diff --git a/src/tooling/docs-builder/Http/DocumentationWebHost.cs b/src/tooling/docs-builder/Http/DocumentationWebHost.cs index 6c14b154a..1be4d0284 100644 --- a/src/tooling/docs-builder/Http/DocumentationWebHost.cs +++ b/src/tooling/docs-builder/Http/DocumentationWebHost.cs @@ -24,6 +24,7 @@ public class DocumentationWebHost private readonly WebApplication _webApplication; private readonly BuildContext _context; + private readonly IHostedService _hostedService; public DocumentationWebHost(string? path, int port, ILoggerFactory logger, IFileSystem fileSystem) { @@ -39,6 +40,7 @@ public DocumentationWebHost(string? path, int port, ILoggerFactory logger, IFile var hostUrl = $"http://localhost:{port}"; + _hostedService = collector; _context = new BuildContext(collector, fileSystem, fileSystem, path, null) { CanonicalBaseUrl = new Uri(hostUrl), @@ -67,14 +69,14 @@ public DocumentationWebHost(string? path, int port, ILoggerFactory logger, IFile public async Task RunAsync(Cancel ctx) { - _ = _context.Collector.StartAsync(ctx); + _ = _hostedService.StartAsync(ctx); await _webApplication.RunAsync(ctx); } public async Task StopAsync(Cancel ctx) { - _context.Collector.Channel.TryComplete(); - await _context.Collector.StopAsync(ctx); + await _webApplication.StopAsync(ctx); + await _hostedService.StopAsync(ctx); } private void SetUpRoutes() diff --git a/src/tooling/docs-builder/Http/StaticWebHost.cs b/src/tooling/docs-builder/Http/StaticWebHost.cs index a6599e121..6b2ef0648 100644 --- a/src/tooling/docs-builder/Http/StaticWebHost.cs +++ b/src/tooling/docs-builder/Http/StaticWebHost.cs @@ -2,7 +2,6 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using System.IO.Abstractions; using Elastic.Documentation.Diagnostics; using Elastic.Documentation.Tooling; using Elastic.Markdown; @@ -20,9 +19,7 @@ public class StaticWebHost { private readonly WebApplication _webApplication; - private readonly BuildContext _context; - - public StaticWebHost(string? path, int port, IFileSystem fileSystem) + public StaticWebHost(int port) { var builder = WebApplication.CreateSlimBuilder(); DocumentationTooling.CreateServiceCollection(builder.Services, LogLevel.Warning); @@ -34,13 +31,12 @@ public StaticWebHost(string? path, int port, IFileSystem fileSystem) _ = builder.WebHost.UseUrls($"http://localhost:{port}"); _webApplication = builder.Build(); - _context = new BuildContext(new DiagnosticsCollector([]), fileSystem, fileSystem, path, null); SetUpRoutes(); } public async Task RunAsync(Cancel ctx) => await _webApplication.RunAsync(ctx); - public async Task StopAsync(Cancel ctx) => await _context.Collector.StopAsync(ctx); + public async Task StopAsync(Cancel ctx) => await _webApplication.StopAsync(ctx); private void SetUpRoutes() { @@ -50,8 +46,7 @@ private void SetUpRoutes() _ = _webApplication.MapGet("/", (Cancel _) => Results.Redirect("docs")); - _ = _webApplication.MapGet("{**slug}", (string slug, Cancel ctx) => - ServeDocumentationFile(slug, ctx)); + _ = _webApplication.MapGet("{**slug}", ServeDocumentationFile); } private static async Task ServeDocumentationFile(string slug, Cancel _) diff --git a/tests/Elastic.Markdown.Tests/Directives/DirectiveBaseTests.cs b/tests/Elastic.Markdown.Tests/Directives/DirectiveBaseTests.cs index 4b900ffdf..2fcf94e93 100644 --- a/tests/Elastic.Markdown.Tests/Directives/DirectiveBaseTests.cs +++ b/tests/Elastic.Markdown.Tests/Directives/DirectiveBaseTests.cs @@ -89,7 +89,6 @@ public virtual async ValueTask InitializeAsync() Html = start >= 0 ? html[(start + find.Length)..].ToString().Trim(Environment.NewLine.ToCharArray()) : html.ToString().Trim(Environment.NewLine.ToCharArray()); - Collector.Channel.TryComplete(); await Collector.StopAsync(TestContext.Current.CancellationToken); } diff --git a/tests/Elastic.Markdown.Tests/Inline/InlneBaseTests.cs b/tests/Elastic.Markdown.Tests/Inline/InlneBaseTests.cs index 4229a7c80..3ad3c8c1d 100644 --- a/tests/Elastic.Markdown.Tests/Inline/InlneBaseTests.cs +++ b/tests/Elastic.Markdown.Tests/Inline/InlneBaseTests.cs @@ -138,7 +138,6 @@ public virtual async ValueTask InitializeAsync() Html = start >= 0 && !TestingFullDocument ? html[(start + find.Length)..].ToString().Trim(Environment.NewLine.ToCharArray()) : html.ToString().Trim(Environment.NewLine.ToCharArray()); - Collector.Channel.TryComplete(); await Collector.StopAsync(TestContext.Current.CancellationToken); } diff --git a/tests/Elastic.Markdown.Tests/OutputDirectoryTests.cs b/tests/Elastic.Markdown.Tests/OutputDirectoryTests.cs index 540d6d424..ee0eb8657 100644 --- a/tests/Elastic.Markdown.Tests/OutputDirectoryTests.cs +++ b/tests/Elastic.Markdown.Tests/OutputDirectoryTests.cs @@ -2,6 +2,7 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information using System.IO.Abstractions.TestingHelpers; +using Elastic.Documentation.Diagnostics; using Elastic.Markdown.IO; using FluentAssertions; @@ -27,13 +28,14 @@ public async Task CreatesDefaultOutputDirectory() { CurrentDirectory = Paths.WorkingDirectoryRoot.FullName }); - var context = new BuildContext(fileSystem); + await using var collector = new DiagnosticsCollector([]).StartAsync(TestContext.Current.CancellationToken); + var context = new BuildContext(collector, fileSystem); var linkResolver = new TestCrossLinkResolver(); var set = new DocumentationSet(context, logger, linkResolver); var generator = new DocumentationGenerator(set, logger); await generator.GenerateAll(TestContext.Current.CancellationToken); - await generator.StopDiagnosticCollection(TestContext.Current.CancellationToken); + await collector.StopAsync(TestContext.Current.CancellationToken); fileSystem.Directory.Exists(".artifacts").Should().BeTrue(); diff --git a/tests/authoring/Framework/TestValues.fs b/tests/authoring/Framework/TestValues.fs index 63dffdabd..5a711aab0 100644 --- a/tests/authoring/Framework/TestValues.fs +++ b/tests/authoring/Framework/TestValues.fs @@ -99,7 +99,7 @@ and MarkdownTestContext = member this.Bootstrap () = backgroundTask { let! ctx = Async.CancellationToken do! this.Generator.GenerateAll(ctx) - do! this.Generator.StopDiagnosticCollection(ctx) + do! this.Collector.StopAsync(ctx) let results = this.ConversionCollector.Results From 4b3f083d0daa2f5c9fdae84e323c817977dbab30 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 1 May 2025 14:18:23 +0200 Subject: [PATCH 2/2] fix tests not starting collector --- tests/authoring/Framework/TestValues.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/authoring/Framework/TestValues.fs b/tests/authoring/Framework/TestValues.fs index 5a711aab0..1ad29ec06 100644 --- a/tests/authoring/Framework/TestValues.fs +++ b/tests/authoring/Framework/TestValues.fs @@ -98,6 +98,7 @@ and MarkdownTestContext = member this.Bootstrap () = backgroundTask { let! ctx = Async.CancellationToken + let _ = this.Collector.StartAsync(ctx) do! this.Generator.GenerateAll(ctx) do! this.Collector.StopAsync(ctx)