diff --git a/.github/workflows/docs-preview-local.yml b/.github/workflows/docs-preview-local.yml index 764adb6b51..f322a726da 100644 --- a/.github/workflows/docs-preview-local.yml +++ b/.github/workflows/docs-preview-local.yml @@ -189,7 +189,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - deployments: none + deployments: write id-token: write pull-requests: none outputs: @@ -216,10 +216,8 @@ jobs: persist-credentials: false - name: Create Deployment - # disabled: deployments are not enabled on this branch if: > - false - && env.MATCH == 'true' + env.MATCH == 'true' && needs.check.outputs.any_modified != 'false' && ( github.event_name == 'push' @@ -363,10 +361,8 @@ jobs: - name: Update deployment status uses: actions/github-script@v8 - # disabled: deployments are not enabled on this branch if: > - false - && env.MATCH == 'true' + env.MATCH == 'true' && always() && steps.deployment.outputs.result env: @@ -382,3 +378,80 @@ jobs: environment_url: `https://docs-v3-preview.elastic.dev${process.env.LANDING_PAGE_PATH}`, log_url: `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, }) + + comment: + if: > + github.event_name == 'pull_request' + && needs.check.outputs.any_modified == 'true' + && needs.build.outputs.path_prefix != '' + && needs.build.result == 'success' + runs-on: ubuntu-latest + needs: + - check + - build + permissions: + contents: none + deployments: none + id-token: none + pull-requests: write + steps: + - name: Comment handbook preview links on PR + uses: actions/github-script@v8 + env: + PATH_PREFIX: ${{ needs.build.outputs.path_prefix }} + ALL_CHANGED_FILES: ${{ needs.check.outputs.all_changed_files }} + with: + script: | + const title = '## Docs preview (local build)' + const base = `https://docs-v3-preview.elastic.dev${process.env.PATH_PREFIX}` + const changedMdFiles = process.env.ALL_CHANGED_FILES + .split(/\s+/) + .filter(Boolean) + .filter((i) => i.endsWith('.md')) + .filter((i) => !i.includes('/_snippets/')) + + const lines = [title, '', `**Handbook preview:** ${base}/`, ''] + + if (changedMdFiles.length > 0) { + lines.push('Sample changed pages:') + for (const file of changedMdFiles.slice(0, 15)) { + const path = file + .replace(/^docs\//, '') + .replace(/\/index\.md$/, '') + .replace(/\.md$/, '') + lines.push(`- [${file}](${base}/${path})`) + } + if (changedMdFiles.length > 15) { + lines.push(`- …and ${changedMdFiles.length - 15} more`) + } + } + + const body = lines.join('\n') + const owner = context.repo.owner + const repo = context.repo.repo + const issue_number = context.payload.pull_request.number + + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number, + }) + const existing = comments.find( + (c) => + c.user.type === 'Bot' && c.body.startsWith(title) + ) + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body, + }) + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body, + }) + } diff --git a/tests-integration/Elastic.Documentation.Api.IntegrationTests/OtlpProxyIntegrationTests.cs b/tests-integration/Elastic.Documentation.Api.IntegrationTests/OtlpProxyIntegrationTests.cs index 8f5c48dff9..d5ca5472dd 100644 --- a/tests-integration/Elastic.Documentation.Api.IntegrationTests/OtlpProxyIntegrationTests.cs +++ b/tests-integration/Elastic.Documentation.Api.IntegrationTests/OtlpProxyIntegrationTests.cs @@ -8,27 +8,24 @@ using Elastic.Documentation.Api.Infrastructure.Adapters.Telemetry; using Elastic.Documentation.Api.IntegrationTests.Fixtures; using FakeItEasy; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Elastic.Documentation.Api.IntegrationTests; -public class OtlpProxyIntegrationTests : IAsyncLifetime +public class OtlpProxyIntegrationTests { private const string OtlpEndpoint = "http://localhost:4318"; - public ValueTask InitializeAsync() - { - Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT", OtlpEndpoint); - return ValueTask.CompletedTask; - } - - public ValueTask DisposeAsync() - { - GC.SuppressFinalize(this); - Environment.SetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT", null); - return ValueTask.CompletedTask; - } + /// + /// Ensure OTLP routes are mapped by wiring the endpoint into host configuration (same key Program.cs reads). + /// Relying only on IAsyncLifetime + env vars is flaky under parallel test execution on CI. + /// + private static WebApplicationFactory WithOtlpConfigured(WebApplicationFactory factory) => + factory.WithWebHostBuilder(builder => + builder.UseSetting("OTEL_EXPORTER_OTLP_ENDPOINT", OtlpEndpoint)); [Fact] public async Task OtlpProxyTracesEndpointForwardsToCorrectUrl() @@ -49,12 +46,12 @@ public async Task OtlpProxyTracesEndpointForwardsToCorrectUrl() .Invokes((HttpRequestMessage req, CancellationToken ct) => capturedRequest = req) .Returns(Task.FromResult(mockResponse)); - using var factory = ApiWebApplicationFactory.WithMockedServices(services => + using var factory = WithOtlpConfigured(ApiWebApplicationFactory.WithMockedServices(services => { // Replace the named HttpClient with our mock _ = services.AddHttpClient(AdotOtlpGateway.HttpClientName) .ConfigurePrimaryHttpMessageHandler(() => mockHandler); - }); + })); var client = factory.CreateClient(); var otlpPayload = /*lang=json,strict*/ """ @@ -114,11 +111,11 @@ public async Task OtlpProxyLogsEndpointForwardsToCorrectUrl() .Invokes((HttpRequestMessage req, CancellationToken ct) => capturedRequest = req) .Returns(Task.FromResult(mockResponse)); - using var factory = ApiWebApplicationFactory.WithMockedServices(services => + using var factory = WithOtlpConfigured(ApiWebApplicationFactory.WithMockedServices(services => { _ = services.AddHttpClient(AdotOtlpGateway.HttpClientName) .ConfigurePrimaryHttpMessageHandler(() => mockHandler); - }); + })); var client = factory.CreateClient(); var otlpPayload = /*lang=json,strict*/ """ @@ -171,11 +168,11 @@ public async Task OtlpProxyMetricsEndpointForwardsToCorrectUrl() .Invokes((HttpRequestMessage req, CancellationToken ct) => capturedRequest = req) .Returns(Task.FromResult(mockResponse)); - using var factory = ApiWebApplicationFactory.WithMockedServices(services => + using var factory = WithOtlpConfigured(ApiWebApplicationFactory.WithMockedServices(services => { _ = services.AddHttpClient(AdotOtlpGateway.HttpClientName) .ConfigurePrimaryHttpMessageHandler(() => mockHandler); - }); + })); var client = factory.CreateClient(); var otlpPayload = /*lang=json,strict*/ """ @@ -222,14 +219,14 @@ public async Task OtlpProxyReturnsCollectorErrorStatusCode() .WithReturnType>() .Returns(Task.FromResult(mockResponse)); - using var factory = ApiWebApplicationFactory.WithMockedServices(services => + using var factory = WithOtlpConfigured(ApiWebApplicationFactory.WithMockedServices(services => { #pragma warning disable EXTEXP0001 // Experimental API - needed for test to bypass resilience handlers _ = services.AddHttpClient(AdotOtlpGateway.HttpClientName) .ConfigurePrimaryHttpMessageHandler(() => mockHandler) .RemoveAllResilienceHandlers(); #pragma warning restore EXTEXP0001 - }); + })); var client = factory.CreateClient(); using var content = new StringContent("{}", Encoding.UTF8, "application/json"); @@ -250,7 +247,7 @@ public async Task OtlpProxyReturnsCollectorErrorStatusCode() public async Task OtlpProxyInvalidSignalTypeReturns404() { // Arrange - using var factory = new ApiWebApplicationFactory(); + using var factory = WithOtlpConfigured(new ApiWebApplicationFactory()); using var client = factory.CreateClient(); using var content = new StringContent("{}", Encoding.UTF8, "application/json");