|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#pragma warning disable ASPIREPIPELINES001
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using Aspire.Hosting.Pipelines;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Aspire.Hosting.Publishing;
/// <summary>
/// Provides extension methods for adding manifest publishing to the pipeline.
/// </summary>
[Experimental("ASPIREPIPELINES001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
public static class ManifestPublishingExtensions
{
/// <summary>
/// Adds a step to the pipeline that publishes an Aspire manifest file.
/// </summary>
/// <param name="pipeline">The pipeline to add the manifest publishing step to.</param>
/// <returns>The pipeline for chaining.</returns>
public static IDistributedApplicationPipeline AddManifestPublishing(this IDistributedApplicationPipeline pipeline)
{
var step = new PipelineStep
{
Name = "publish-manifest",
Action = async context =>
{
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("Aspire.Hosting.Publishing.ManifestPublisher");
var pipelineOptions = context.Services.GetRequiredService<IOptions<PipelineOptions>>();
var executionContext = context.Services.GetRequiredService<DistributedApplicationExecutionContext>();
if (pipelineOptions.Value.OutputPath == null)
{
throw new DistributedApplicationException(
"The '--output-path [path]' option was not specified even though manifest publishing was requested."
);
}
var outputPath = pipelineOptions.Value.OutputPath;
if (!outputPath.EndsWith(".json"))
{
// If the manifest path ends with .json we assume that the output path was specified
// as a filename. If not, we assume that the output path was specified as a directory
// and append aspire-manifest.json to the path. This is so that we retain backwards
// compatibility with AZD, but also support manifest publishing via the Aspire CLI
// where the output path is a directory (since not all publishers use a manifest).
outputPath = Path.Combine(outputPath, "aspire-manifest.json");
}
var parentDirectory = Directory.GetParent(outputPath);
if (!Directory.Exists(parentDirectory!.FullName))
{
// Create the directory if it does not exist
Directory.CreateDirectory(parentDirectory.FullName);
}
using var stream = new FileStream(outputPath, FileMode.Create);
using var jsonWriter = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
var manifestPath = outputPath;
var publishingContext = new ManifestPublishingContext(executionContext, manifestPath, jsonWriter, context.CancellationToken);
await publishingContext.WriteModel(context.Model, context.CancellationToken).ConfigureAwait(false);
var fullyQualifiedPath = Path.GetFullPath(outputPath);
logger.LogInformation("Published manifest to: {ManifestPath}", fullyQualifiedPath);
}
};
pipeline.AddStep(step);
return pipeline;
}
}
|