diff --git a/config/products.yml b/config/products.yml index 0a35f5dd9..7c735a5da 100644 --- a/config/products.yml +++ b/config/products.yml @@ -91,18 +91,25 @@ products: versioning: 'stack' edot-ios: display: 'Elastic Distribution of OpenTelemetry iOS' + repository: 'apm-agent-ios' edot-android: display: 'Elastic Distribution of OpenTelemetry Android' + repository: 'apm-agent-android' edot-dotnet: display: 'Elastic Distribution of OpenTelemetry .NET' + repository: 'elastic-otel-dotnet' edot-java: display: 'Elastic Distribution of OpenTelemetry Java' + repository: 'elastic-otel-java' edot-node: display: 'Elastic Distribution of OpenTelemetry Node' + repository: 'elastic-otel-node' edot-php: display: 'Elastic Distribution of OpenTelemetry PHP' + repository: 'elastic-otel-php' edot-python: display: 'Elastic Distribution of OpenTelemetry Python' + repository: 'elastic-otel-python' edot-cf-aws: display: 'EDOT Cloud Forwarder for AWS' edot-cf-azure: diff --git a/docs/configure/site/products.md b/docs/configure/site/products.md index 9a5ca5164..e8d228c68 100644 --- a/docs/configure/site/products.md +++ b/docs/configure/site/products.md @@ -10,6 +10,7 @@ products: edot-collector: display: 'Elastic Distribution of OpenTelemetry Collector' versioning: 'stack' + repository: 'elastic-edot-collector' #... ``` @@ -19,6 +20,7 @@ products: : A YAML mapping where each key is an Elastic product. * `display`: A friendly name for the product. * `versioning`: The versioning system used by the project. The value for this field must match one of the versioning systems defined in [`versions.yml`](https://github.com/elastic/docs-builder/blob/main/config/versions.yml) +* `repository`: The repository name for the product. It's optional and primarily intended for handling edge cases where there is a mismatch between the repository name and the product identifier. diff --git a/src/Elastic.Documentation.Configuration/Products/Product.cs b/src/Elastic.Documentation.Configuration/Products/Product.cs index 9dabeb1eb..74a1afd96 100644 --- a/src/Elastic.Documentation.Configuration/Products/Product.cs +++ b/src/Elastic.Documentation.Configuration/Products/Product.cs @@ -19,5 +19,6 @@ public record Product public required string Id { get; init; } public required string DisplayName { get; init; } public VersioningSystem? VersioningSystem { get; init; } + public string? Repository { get; init; } } diff --git a/src/Elastic.Documentation.Configuration/Products/ProductExtensions.cs b/src/Elastic.Documentation.Configuration/Products/ProductExtensions.cs index eab68d0bb..b4920d65b 100644 --- a/src/Elastic.Documentation.Configuration/Products/ProductExtensions.cs +++ b/src/Elastic.Documentation.Configuration/Products/ProductExtensions.cs @@ -21,7 +21,8 @@ public static ProductsConfiguration CreateProducts(this ConfigurationFileProvide { Id = kvp.Key, DisplayName = kvp.Value.Display, - VersioningSystem = versionsConfiguration.GetVersioningSystem(VersionsConfigurationExtensions.ToVersioningSystemId(kvp.Value.Versioning ?? kvp.Key)) + VersioningSystem = versionsConfiguration.GetVersioningSystem(VersionsConfigurationExtensions.ToVersioningSystemId(kvp.Value.Versioning ?? kvp.Key)), + Repository = kvp.Value.Repository ?? kvp.Key }); return new ProductsConfiguration @@ -41,4 +42,5 @@ internal sealed record ProductDto { public string Display { get; set; } = string.Empty; public string? Versioning { get; set; } + public string? Repository { get; set; } } diff --git a/src/Elastic.Documentation.Configuration/Versions/VersionInference.cs b/src/Elastic.Documentation.Configuration/Versions/VersionInference.cs new file mode 100644 index 000000000..fde4230cb --- /dev/null +++ b/src/Elastic.Documentation.Configuration/Versions/VersionInference.cs @@ -0,0 +1,42 @@ +// 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 Elastic.Documentation.Configuration.LegacyUrlMappings; +using Elastic.Documentation.Configuration.Products; + +namespace Elastic.Documentation.Configuration.Versions; + +public interface IVersionInferrerService +{ + VersioningSystem InferVersion(string repositoryName, IReadOnlyCollection? legacyPages); +} + +public class ProductVersionInferrerService(ProductsConfiguration productsConfiguration, VersionsConfiguration versionsConfiguration) : IVersionInferrerService +{ + private ProductsConfiguration ProductsConfiguration { get; } = productsConfiguration; + private VersionsConfiguration VersionsConfiguration { get; } = versionsConfiguration; + public VersioningSystem InferVersion(string repositoryName, IReadOnlyCollection? legacyPages) + { + var versioning = legacyPages is not null && legacyPages.Count > 0 + ? legacyPages.ElementAt(0).Product.VersioningSystem! // If the page has a legacy page mapping, use the versioning system of the legacy page + : ProductsConfiguration.Products.TryGetValue(repositoryName, out var belonging) + ? belonging.VersioningSystem! //If the page's docset has a name with a direct product match, use the versioning system of the product + : ProductsConfiguration.Products.Values.SingleOrDefault(p => + p.Repository is not null && p.Repository.Equals(repositoryName, StringComparison.OrdinalIgnoreCase)) is { } repositoryMatch + ? repositoryMatch.VersioningSystem! // Verify if the page belongs to a repository linked to a product, and if so, use the versioning system of the product + : VersionsConfiguration.VersioningSystems[VersioningSystemId.Stack]; // Fallback to the stack versioning system + + return versioning; + } +} + +public class NoopVersionInferrer : IVersionInferrerService +{ + public VersioningSystem InferVersion(string repositoryName, IReadOnlyCollection? legacyPages) => new() + { + Id = VersioningSystemId.Stack, + Base = new SemVersion(0, 0, 0), + Current = new SemVersion(0, 0, 0) + }; +} diff --git a/src/Elastic.Markdown/DocumentationGenerator.cs b/src/Elastic.Markdown/DocumentationGenerator.cs index 34ece3528..5aeb99861 100644 --- a/src/Elastic.Markdown/DocumentationGenerator.cs +++ b/src/Elastic.Markdown/DocumentationGenerator.cs @@ -7,6 +7,7 @@ using Elastic.Documentation; using Elastic.Documentation.Configuration; using Elastic.Documentation.Configuration.LegacyUrlMappings; +using Elastic.Documentation.Configuration.Versions; using Elastic.Documentation.Links; using Elastic.Documentation.Links.CrossLinks; using Elastic.Documentation.Serialization; @@ -71,8 +72,9 @@ public DocumentationGenerator( DocumentationSet = docSet; Context = docSet.Context; CrossLinkResolver = docSet.CrossLinkResolver; + var productVersionInferrer = new ProductVersionInferrerService(DocumentationSet.Context.ProductsConfiguration, DocumentationSet.Context.VersionsConfiguration); HtmlWriter = new HtmlWriter(DocumentationSet, _writeFileSystem, new DescriptionGenerator(), navigationHtmlWriter, legacyUrlMapper, - positionalNavigation); + positionalNavigation, productVersionInferrer); _documentationFileExporter = docSet.Context.AvailableExporters.Contains(Exporter.Html) ? docSet.EnabledExtensions.FirstOrDefault(e => e.FileExporter != null)?.FileExporter diff --git a/src/Elastic.Markdown/HtmlWriter.cs b/src/Elastic.Markdown/HtmlWriter.cs index 804d12e01..761e8b1ad 100644 --- a/src/Elastic.Markdown/HtmlWriter.cs +++ b/src/Elastic.Markdown/HtmlWriter.cs @@ -25,7 +25,8 @@ public class HtmlWriter( IDescriptionGenerator descriptionGenerator, INavigationHtmlWriter? navigationHtmlWriter = null, ILegacyUrlMapper? legacyUrlMapper = null, - IPositionalNavigation? positionalNavigation = null + IPositionalNavigation? positionalNavigation = null, + IVersionInferrerService? versionInferrerService = null ) : IMarkdownStringRenderer { @@ -38,6 +39,8 @@ public class HtmlWriter( private ILegacyUrlMapper LegacyUrlMapper { get; } = legacyUrlMapper ?? new NoopLegacyUrlMapper(); private IPositionalNavigation PositionalNavigation { get; } = positionalNavigation ?? documentationSet; + private IVersionInferrerService VersionInferrerService { get; } = versionInferrerService ?? new NoopVersionInferrer(); + /// public string Render(string markdown, IFileInfo? source) { @@ -102,9 +105,10 @@ private async Task RenderLayout(MarkdownFile markdown, MarkdownDoc fullNavigationRenderResult ); - var currentBaseVersion = legacyPages is { Count: > 0 } - ? $"{legacyPages.ElementAt(0).Product.VersioningSystem?.Base.Major}.{legacyPages.ElementAt(0).Product.VersioningSystem?.Base.Minor}+" - : $"{DocumentationSet.Context.VersionsConfiguration.VersioningSystems[VersioningSystemId.Stack].Base.Major}.{DocumentationSet.Context.VersionsConfiguration.VersioningSystems[VersioningSystemId.Stack].Base.Minor}+"; + var pageVersioning = VersionInferrerService.InferVersion(DocumentationSet.Context.Git.RepositoryName, legacyPages); + + var currentBaseVersion = $"{pageVersioning.Base.Major}.{pageVersioning.Base.Minor}+"; + //TODO should we even distinctby var breadcrumbs = parents.Reverse().DistinctBy(p => p.Url).ToArray(); var breadcrumbsList = CreateStructuredBreadcrumbsData(markdown, breadcrumbs);