Skip to content

Add Microsoft.Extensions.ApiDesription.Server project and package #10669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 4, 2019
3 changes: 3 additions & 0 deletions eng/ProjectReferences.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.Specification.Tests" ProjectPath="$(RepoRoot)src\Identity\Specification.Tests\src\Microsoft.AspNetCore.Identity.Specification.Tests.csproj" />
<ProjectReferenceProvider Include="Microsoft.Web.Xdt.Extensions" ProjectPath="$(RepoRoot)src\SiteExtensions\Microsoft.Web.Xdt.Extensions\src\Microsoft.Web.Xdt.Extensions.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" ProjectPath="$(RepoRoot)src\Tools\FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj" />
<ProjectReferenceProvider Include="dotnet-getdocument" ProjectPath="$(RepoRoot)src\Mvc\dotnet-getdocument\src\dotnet-getdocument.csproj" />
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Client" ProjectPath="$(RepoRoot)src\Mvc\Extensions.ApiDescription.Client\src\Microsoft.Extensions.ApiDescription.Client.csproj" />
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Server" ProjectPath="$(RepoRoot)src\Mvc\Extensions.ApiDescription.Server\src\Microsoft.Extensions.ApiDescription.Server.csproj" />
<ProjectReferenceProvider Include="GetDocument.Insider" ProjectPath="$(RepoRoot)src\Mvc\GetDocumentInsider\src\GetDocumentInsider.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Specification.Tests" ProjectPath="$(RepoRoot)src\SignalR\server\Specification.Tests\src\Microsoft.AspNetCore.SignalR.Specification.Tests.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Build" ProjectPath="$(RepoRoot)src\Components\Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" RefProjectPath="$(RepoRoot)src\DefaultBuilder\ref\Microsoft.AspNetCore.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
<!-- Execute PopulateNuspec fairly late. -->
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);PopulateNuspec</GenerateNuspecDependsOn>

<!-- Do not complain about lack of lib folder. -->
<NoPackageAnalysis>true</NoPackageAnalysis>

<!-- Included primarily to ensure dotnet-getdocument and GetDocument.Insider can be referenced. -->
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this tool when only a .NET Core 3.0 SDK is installed? I didn't see anything which configures rollforward, so I would expect the dotnet get-document.dll command to fail with a "Could not find .NET Core 2.1..." error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #10667. That adds runtimeconfig.template.json files for dotnet-getdocument and GetDocument.Insider

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I also confirmed this works fine in a 3.0-only environment with 3.0 projects


<Description>MSBuild tasks and targets for build-time Swagger and OpenApi document generation</Description>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
<IncludeBuildOutput>false</IncludeBuildOutput>
<HasReferenceAssembly>false</HasReferenceAssembly>
<IncludeSource>false</IncludeSource>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
<PackageId>$(MSBuildProjectName)</PackageId>
<PackageTags>MSBuild;Swagger;Open API;code generation;Web API</PackageTags>
<IsShippingPackage>true</IsShippingPackage>
<PackageVersion>$(ExperimentalPackageVersion)</PackageVersion>
<VerifyVersion>false</VerifyVersion>
<VersionPrefix>$(ExperimentalVersionPrefix)</VersionPrefix>
<VersionSuffix>$(ExperimentalVersionSuffix)</VersionSuffix>
</PropertyGroup>

<ItemGroup>
<Reference Include="dotnet-getdocument" Condition=" '$(TargetFramework)' == 'netcoreapp2.1' " />
<Reference Include="GetDocument.Insider" />
</ItemGroup>

<Target Name="PopulateNuspec">
<MSBuild Projects="../../dotnet-getdocument/src/dotnet-getdocument.csproj"
BuildInParallel="$(BuildInParallel)"
RemoveProperties="RuntimeIdentifier;TargetFrameworks;TargetFramework"
Targets="Publish" />

<PropertyGroup>
<NuspecProperties>
id=$(PackageId);
artifactsBinDir=$(ArtifactsBinDir);
authors=$(Authors);
configuration=$(Configuration);
copyright=$(Copyright);
description=$(PackageDescription);
iconUrl=$(PackageIconUrl);
licenseUrl=$(PackageLicenseUrl);
owners=$(Company);
projectUrl=$(PackageProjectUrl);
repositoryCommit=$(SourceRevisionId);
repositoryUrl=$(RepositoryUrl);
tags=$(PackageTags.Replace(';', ' '));
version=$(PackageVersion);
</NuspecProperties>
</PropertyGroup>
</Target>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<Target Name="Compile" />
<Target Name="CopyFilesToOutputDirectory" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.8">
<id>$id$</id>
<authors>$authors$</authors>
<copyright>$copyright$</copyright>
<description>$description$</description>
<developmentDependency>true</developmentDependency>
<iconUrl>$iconUrl$</iconUrl>
<licenseUrl>$licenseUrl$</licenseUrl>
<owners>$owners$</owners>
<projectUrl>$projectUrl$</projectUrl>
<repository type="git" url="$repositoryUrl$" commit="$repositoryCommit$" />
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<tags>$tags$</tags>
<version>$version$</version>
</metadata>

<files>
<file src="build\*" target="build" />
<file src="buildMultiTargeting\*" target="buildMultiTargeting" />
<file src="$artifactsBinDir$\dotnet-getdocument\$configuration$\netcoreapp2.1\publish\*.*" target="tools" />
<file src="$artifactsBinDir$\GetDocumentInsider\$configuration$\net461\GetDocument.Insider.*" target="tools\net461" />
<file src="$artifactsBinDir$\GetDocumentInsider\x86\$configuration$\net461\GetDocument.Insider.*" target="tools\net461-x86" />
<file src="$artifactsBinDir$\GetDocumentInsider\$configuration$\netcoreapp2.1\GetDocument.Insider.*" target="tools\netcoreapp2.1" />
</files>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project>
<!--
Settings users may update as they see fit.
-->
<PropertyGroup>
<!--
Options added to the Open API document generation tool ('dotnet-getdocument') command line. Available options
control console output: 'no-color', 'prefix-output' and 'verbose'. All require a double-dash prefix.
-->
<OpenApiGenerateDocumentsOptions Condition=" '$(OpenApiGenerateDocumentsOptions)' == '' "></OpenApiGenerateDocumentsOptions>

<!--
If 'true' (the default), enable generation of Open API documents. Otherwise, this feature is completely disabled.
This controls whether the 'OpenApiGenerateDocuments' project capability is visible, enables / disables the
'GenerateOpenApiDocuments' target and provides the $(OpenApiGenerateDocumentsOnBuild) default.
-->
<OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' ">true</OpenApiGenerateDocuments>

<!--
If 'true' (the default if $(OpenApiGenerateDocuments) is 'true'), will generate Open API documents after every
build. Set to 'false' when targets are invoked from the command line or tied to another target.
-->
<OpenApiGenerateDocumentsOnBuild
Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' ">$(OpenApiGenerateDocuments)</OpenApiGenerateDocumentsOnBuild>

<!--
Where to place Open API documents generated from the application. Value is interpreted relative to the project
folder, unless already an absolute path.
-->
<OpenApiDocumentsDirectory
Condition=" '$(OpenApiDocumentsDirectory)' == '' ">$(BaseIntermediateOutputPath)</OpenApiDocumentsDirectory>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project>
<PropertyGroup>
<_OpenApiDocumentsCache>$(BaseIntermediateOutputPath)$(MSBuildProjectName).OpenApiFiles.cache</_OpenApiDocumentsCache>
</PropertyGroup>
<ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' ">
<ProjectCapability Include="OpenApiGenerateDocuments" />
</ItemGroup>

<Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)">
<ReadLinesFromFile File="$(_OpenApiDocumentsCache)">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually a cache? or is this just the output of generating the documents?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR

Is your question aimed at my naming (and life) choices? I don't see much consistency in how similar MSBuild properties are named and chose something that fit.

Make a suggestion if you feel strongly please.

Details

This file is many things…

It's a cache in the sense seen in lots of MSBuild code: It's a way to avoid redoing an action (calling a task, executing a too, whatever). In particular, this file avoids reopening the app whenever a client project calls OpenApiGetDocuments.

Yes, as an implementation detail, this file is one of the files written as a result of running the tool. It lists the document files.


The file is also like many used in MSBuild code in that it summarizes multiple inputs or outputs of a task or tool. For example, I could do the Inputs=$(TargetPath)Outputs=$(_OpenApiDocumentsCache) batching trick to avoid running dotnet-getdocument even if there are multiple document files.


Finally, this file is the communication mechanism between the GenerateOpenApiDocuments and OpenApiGetDocuments targets.

<Output TaskParameter="Lines" ItemName="_OpenApiProjectDocuments" />
</ReadLinesFromFile>
</Target>

<Target Name="GenerateOpenApiDocuments" Condition=" '$(OpenApiGenerateDocuments)' == 'true' ">
<PropertyGroup>
<_Command>dotnet "$(MSBuildThisFileDirectory)/../tools/dotnet-getdocument.dll" --assembly "$(TargetPath)"</_Command>
<_Command>$(_Command) --file-list "$(_OpenApiDocumentsCache)" --framework "$(TargetFrameworkMoniker)"</_Command>
<_Command>$(_Command) --output "$(OpenApiDocumentsDirectory.TrimEnd('\'))" --project "$(MSBuildProjectName)"</_Command>
<_Command Condition=" '$(ProjectAssetsFile)' != '' ">$(_Command) --assets-file "$(ProjectAssetsFile)"</_Command>
<_Command Condition=" '$(PlatformTarget)' != '' ">$(_Command) --platform "$(PlatformTarget)"</_Command>
<_Command Condition=" '$(PlatformTarget)' == '' AND '$(Platform)' != '' ">$(_Command) --platform "$(Platform)"</_Command>
<_Command Condition=" '$(RuntimeIdentifier)' != '' ">$(_Command) --runtime "$(RuntimeIdentifier)"</_Command>
<_Command>$(_Command) $(OpenApiGenerateDocumentsOptions)</_Command>
</PropertyGroup>

<Message Importance="high" Text="%0AGenerateOpenApiDocuments:" />
<Message Importance="high" Text=" $(_Command)" />
<Exec Command="$(_Command)" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the caching expectations of this? Should we be adding some things to FileWrites so they can be removed by incremental clean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been thinking about FileWrites both here and in the client-side glue. But, every time I start making those changes, I hit the "What if the user plans to check these files in?" question. These files aren't always throw-away. But, I could probably complicate things enough to avoid that concern e.g. with conditions on $(OpenApiDocumentsDirectory) matching the default.

I'll add a note to #4923 reminding me to work through the implications and do something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed in person. Right now there is no input/output checking and this command will re-run every time you build, even if the assembly does not change.

This is tracked separately and will be improved in the next preview.

</Target>

<!-- Unless this is an inner build or default timing is disabled, tie document retrieval into the build. -->

<Target Name="_GenerateOpenApiDocuments"
AfterTargets="Build"
Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == 'true' AND ('$(TargetFramework)' == '' OR '$(TargetFrameworks)' == '') "
DependsOnTargets="GenerateOpenApiDocuments" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project>
<Import Project="../build/Microsoft.Extensions.ApiDescription.Server.props" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project>
<ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' ">
<ProjectCapability Include="OpenApiGenerateDocuments" />
</ItemGroup>

<Target Name="GenerateOpenApiDocuments">
<MSBuild Projects="$(MSBuildProjectFile)"
Targets="GenerateOpenApiDocuments"
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])"
RemoveProperties="RuntimeIdentifier" />
</Target>

<Target Name="_GenerateOpenApiDocuments"
AfterTargets="Build"
Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == 'true' "
DependsOnTargets="GenerateOpenApiDocuments" />

<Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)">
<MSBuild Projects="$(MSBuildProjectFile)"
Targets="OpenApiGetDocuments"
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])"
RemoveProperties="RuntimeIdentifier">
<Output TaskParameter="TargetOutputs" ItemName="_OpenApiProjectDocuments" />
</MSBuild>
</Target>
</Project>
2 changes: 1 addition & 1 deletion src/Mvc/GetDocumentInsider/src/GetDocumentInsider.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<PropertyGroup>
<AssemblyName>GetDocument.Insider</AssemblyName>
<Description>GetDocument Command-line Tool inside man</Description>
<HasReferenceAssembly>false</HasReferenceAssembly>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<RootNamespace>Microsoft.Extensions.ApiDescription.Tool</RootNamespace>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<VerifyVersion>false</VerifyVersion>
<VersionPrefix>$(ExperimentalVersionPrefix)</VersionPrefix>
<VersionSuffix>$(ExperimentalVersionSuffix)</VersionSuffix>
<IsImplementationProject>false</IsImplementationProject>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
Expand Down
17 changes: 17 additions & 0 deletions src/Mvc/Mvc.sln
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Co
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.Json", "..\SignalR\common\Protocols.Json\src\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj", "{637119E8-5BBB-4FC7-A372-DAF38FF5EBD9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions.ApiDescription.Server", "Extensions.ApiDescription.Server", "{C15AA245-9E54-4FD6-90FF-B46F47779C46}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.ApiDescription.Server", "Extensions.ApiDescription.Server\src\Microsoft.Extensions.ApiDescription.Server.csproj", "{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1825,6 +1829,18 @@ Global
{637119E8-5BBB-4FC7-A372-DAF38FF5EBD9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{637119E8-5BBB-4FC7-A372-DAF38FF5EBD9}.Release|x86.ActiveCfg = Release|Any CPU
{637119E8-5BBB-4FC7-A372-DAF38FF5EBD9}.Release|x86.Build.0 = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|x86.ActiveCfg = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Debug|x86.Build.0 = Debug|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|Any CPU.Build.0 = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|x86.ActiveCfg = Release|Any CPU
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1955,6 +1971,7 @@ Global
{6D6489E5-48BD-4F9B-9EEE-22AEEA1E1890} = {45CE788D-4B69-4F83-981C-F43D8F15B0F1}
{C6F3BCE6-1EFD-4360-932B-B98573E78926} = {45CE788D-4B69-4F83-981C-F43D8F15B0F1}
{637119E8-5BBB-4FC7-A372-DAF38FF5EBD9} = {5FE3048A-E96B-44F8-A7C4-FC590D7E04B4}
{D7CF2A1E-A29E-45AB-9C2A-CD6C3BAE54F2} = {C15AA245-9E54-4FD6-90FF-B46F47779C46}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}
Expand Down
2 changes: 1 addition & 1 deletion src/Mvc/dotnet-getdocument/src/dotnet-getdocument.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<AssemblyName>dotnet-getdocument</AssemblyName>
<Description>GetDocument Command-line Tool outside man</Description>
<HasReferenceAssembly>false</HasReferenceAssembly>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<RootNamespace>Microsoft.Extensions.ApiDescription.Tool</RootNamespace>
Expand All @@ -10,7 +11,6 @@
<VerifyVersion>false</VerifyVersion>
<VersionPrefix>$(ExperimentalVersionPrefix)</VersionPrefix>
<VersionSuffix>$(ExperimentalVersionSuffix)</VersionSuffix>
<IsImplementationProject>false</IsImplementationProject>
</PropertyGroup>

<ItemGroup>
Expand Down