diff --git a/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.props b/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.props index 71784e621a88..f4a738e81de0 100644 --- a/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.props +++ b/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.props @@ -31,5 +31,11 @@ --> $(BaseIntermediateOutputPath) + + + diff --git a/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.targets b/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.targets index f5b2839bd16d..131ae0efa1b9 100644 --- a/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.targets +++ b/src/Tools/Extensions.ApiDescription.Server/src/build/Microsoft.Extensions.ApiDescription.Server.targets @@ -59,6 +59,7 @@ <_DotNetGetDocumentCommand Condition=" '$(PlatformTarget)' != '' ">$(_DotNetGetDocumentCommand) --platform "$(PlatformTarget)" <_DotNetGetDocumentCommand Condition=" '$(PlatformTarget)' == '' AND '$(Platform)' != '' ">$(_DotNetGetDocumentCommand) --platform "$(Platform)" <_DotNetGetDocumentCommand Condition=" '$(RuntimeIdentifier)' != '' ">$(_DotNetGetDocumentCommand) --runtime "$(RuntimeIdentifier) --self-contained" + <_DotNetGetDocumentCommand Condition=" '$(OpenApiGenerateEnvironment)' != '' ">$(_DotNetGetDocumentCommand) --environment "$(OpenApiGenerateEnvironment)" <_DotNetGetDocumentCommand>$(_DotNetGetDocumentCommand) $(OpenApiGenerateDocumentsOptions) diff --git a/src/Tools/GetDocumentInsider/sample/Program.cs b/src/Tools/GetDocumentInsider/sample/Program.cs index 065f8479a925..6f5ee6e6ce60 100644 --- a/src/Tools/GetDocumentInsider/sample/Program.cs +++ b/src/Tools/GetDocumentInsider/sample/Program.cs @@ -9,8 +9,21 @@ private static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - builder.Services.AddOpenApi(); - builder.Services.AddOpenApi("internal"); + builder.Services.AddOpenApi(options => + { + options.AddDocumentTransformer((document, context, cancellationToken) => + { + return TransformDocument(document, builder); + }); + }); + + builder.Services.AddOpenApi("internal", options => + { + options.AddDocumentTransformer((document, context, cancellationToken) => + { + return TransformDocument(document, builder); + }); + }); var app = builder.Build(); @@ -22,4 +35,16 @@ private static void Main(string[] args) app.Run(); } + + private static Task TransformDocument( + Microsoft.OpenApi.OpenApiDocument document, + WebApplicationBuilder builder) + { + var env = builder.Environment.EnvironmentName; + if (!string.IsNullOrEmpty(env)) + { + document.Info.Summary += $"Running in '{env}' environment"; + } + return Task.CompletedTask; + } } diff --git a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommand.cs b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommand.cs index e127254ef409..901632b08762 100644 --- a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommand.cs +++ b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommand.cs @@ -20,6 +20,7 @@ internal sealed class GetDocumentCommand : ProjectCommandBase private CommandOption _openApiVersion; private CommandOption _documentName; private CommandOption _fileName; + private CommandOption _environment; public GetDocumentCommand(IConsole console) : base(console) { @@ -34,6 +35,7 @@ public override void Configure(CommandLineApplication command) _openApiVersion = command.Option("--openapi-version ", Resources.OpenApiVersionDescription); _documentName = command.Option("--document-name ", Resources.DocumentNameDescription); _fileName = command.Option("--file-name ", Resources.FileNameDescription); + _environment = command.Option("--environment ", Resources.EnvironmentDescription); } protected override void Validate() @@ -144,7 +146,8 @@ protected override int Execute() DocumentName = _documentName.Value(), ProjectName = ProjectName.Value(), Reporter = Reporter, - FileName = _fileName.Value() + FileName = _fileName.Value(), + Environment = _environment.Value() }; return new GetDocumentCommandWorker(context).Process(); diff --git a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandContext.cs b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandContext.cs index 2ec4f44457fe..d5d1ec517919 100644 --- a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandContext.cs +++ b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandContext.cs @@ -38,5 +38,11 @@ public class GetDocumentCommandContext /// public string FileName { get; set; } + /// + /// The environment name to use when executing the application. + /// Sets the ASPNETCORE_ENVIRONMENT environment variable. + /// + public string Environment { get; set; } + public IReporter Reporter { get; set; } } diff --git a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandWorker.cs b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandWorker.cs index 0bd4ed9be2dd..9b5119d700bb 100644 --- a/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandWorker.cs +++ b/src/Tools/GetDocumentInsider/src/Commands/GetDocumentCommandWorker.cs @@ -112,8 +112,15 @@ void OnEntryPointExit(Exception exception) try { + // Build the arguments array for the host factory + var hostArgs = new List { $"--{HostDefaults.ApplicationKey}={assemblyName}" }; + if (!string.IsNullOrEmpty(_context.Environment)) + { + hostArgs.Add($"--environment={_context.Environment}"); + } + // Retrieve the service provider from the target host. - var services = ((IHost)factory([$"--{HostDefaults.ApplicationKey}={assemblyName}"])).Services; + var services = ((IHost)factory(hostArgs.ToArray())).Services; if (services == null) { _reporter.WriteError(Resources.FormatServiceProviderNotFound( @@ -159,7 +166,14 @@ void OnEntryPointExit(Exception exception) return 4; } - var services = serviceFactory(Array.Empty()); + // Build the arguments array for the service factory + var hostArgs = new List(); + if (!string.IsNullOrEmpty(_context.Environment)) + { + hostArgs.Add($"--environment={_context.Environment}"); + } + + var services = serviceFactory(hostArgs.ToArray()); if (services == null) { _reporter.WriteError(Resources.FormatServiceProviderNotFound( diff --git a/src/Tools/GetDocumentInsider/src/Resources.resx b/src/Tools/GetDocumentInsider/src/Resources.resx index ca5d34bc6642..b71ac7af436e 100644 --- a/src/Tools/GetDocumentInsider/src/Resources.resx +++ b/src/Tools/GetDocumentInsider/src/Resources.resx @@ -200,6 +200,9 @@ The name of the OpenAPI document to generate. Optional. + + The environment name to use (e.g., Development, Production). + Invalid OpenAPI spec version '{0}' provided. Falling back to default: v3.0. diff --git a/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs b/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs index 712ef8bc1f8c..a0074de5e0c9 100644 --- a/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs +++ b/src/Tools/GetDocumentInsider/tests/GetDocumentTests.cs @@ -237,4 +237,34 @@ public void GetDocument_WithEmptyFileName_Works() Assert.True(File.Exists(Path.Combine(outputPath.FullName, "Sample.json"))); Assert.True(File.Exists(Path.Combine(outputPath.FullName, "Sample_internal.json"))); } + + [Theory] + [InlineData("Development")] + [InlineData("Staging")] + [InlineData("Production")] + public void GetDocument_WithDifferentEnvironments_Works(string environment) + { + // Arrange + var outputPath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())); + var app = new Program(_console); + + // Act + app.Run([ + "--assembly", _testAppAssembly, + "--project", _testAppProject, + "--framework", _testAppFrameworkMoniker, + "--tools-directory", _toolsDirectory, + "--output", outputPath.FullName, + "--file-list", Path.Combine(outputPath.FullName, "file-list.cache"), + "--environment", environment + ], new GetDocumentCommand(_console), throwOnUnexpectedArg: false); + + // Assert + using var stream = new MemoryStream(File.ReadAllBytes(Path.Combine(outputPath.FullName, "Sample.json"))); + var result = OpenApiDocument.Load(stream, "json"); + Assert.Equal(OpenApiSpecVersion.OpenApi3_1, result.Diagnostic.SpecificationVersion); + + // Verify environment appears in summary - this proves --environment parameter is used + Assert.Equal($"Running in '{environment}' environment", result.Document.Info.Summary); + } } diff --git a/src/Tools/dotnet-getdocument/src/Commands/InvokeCommand.cs b/src/Tools/dotnet-getdocument/src/Commands/InvokeCommand.cs index a04aab04701f..31675af24cff 100644 --- a/src/Tools/dotnet-getdocument/src/Commands/InvokeCommand.cs +++ b/src/Tools/dotnet-getdocument/src/Commands/InvokeCommand.cs @@ -141,6 +141,13 @@ protected override int Execute() args.Add("--tools-directory"); args.Add(toolsDirectory); + var environment = _projectOptions.Environment.Value(); + if (!string.IsNullOrEmpty(environment)) + { + args.Add("--environment"); + args.Add(environment); + } + if (ReporterExtensions.PrefixOutput) { args.Add("--prefix-output"); diff --git a/src/Tools/dotnet-getdocument/src/ProjectOptions.cs b/src/Tools/dotnet-getdocument/src/ProjectOptions.cs index f2b55eec5eb2..62ef438f80a3 100644 --- a/src/Tools/dotnet-getdocument/src/ProjectOptions.cs +++ b/src/Tools/dotnet-getdocument/src/ProjectOptions.cs @@ -19,6 +19,8 @@ internal sealed class ProjectOptions public CommandOption TargetFramework { get; private set; } + public CommandOption Environment { get; private set; } + public void Configure(CommandLineApplication command) { AssemblyPath = command.Option("--assembly ", Resources.AssemblyDescription); @@ -27,6 +29,7 @@ public void Configure(CommandLineApplication command) Platform = command.Option("--platform ", Resources.PlatformDescription); ProjectName = command.Option("--project ", Resources.ProjectDescription); RuntimeFrameworkVersion = command.Option("--runtime ", Resources.RuntimeDescription); + Environment = command.Option("--environment ", Resources.EnvironmentDescription); } public void Validate() diff --git a/src/Tools/dotnet-getdocument/src/Resources.resx b/src/Tools/dotnet-getdocument/src/Resources.resx index 3f0b6440ad1f..5c8bc4a5068c 100644 --- a/src/Tools/dotnet-getdocument/src/Resources.resx +++ b/src/Tools/dotnet-getdocument/src/Resources.resx @@ -156,6 +156,9 @@ The assembly path to use. Required. + + The environment name to use (e.g., Development, Production). + Cannot specify both '--quiet' and '--verbose' options.