Description
Playing around with the OpenAPI document CLI generation from Lint generated OpenAPI documents with Spectral I found a few issues and rough edges. Rather than create lots of small issues I figured I'd list them all here, and they can be spun off into dedicated issues based on feedback/triage.
OpenApiDocumentsDirectory is not resolved to a full path
If OpenApiDocumentsDirectory
is specified as a relative path (e.g. dotnet build ./src/API /p:OpenApiGenerateDocuments=true /p:OpenApiDocumentsDirectory="./artifacts/openapi"
), the path is not resolved to a full path, and then ends up as a path relative to the tool invocation, rather than relative to the current working directory of the command, so the document ends up in the bin\Debug
etc. folder rather than the folder the user expected.
Seems like resolving the full path here in the MSBuild targets before invoking the tool would resolve that:
"Invalid OpenAPI spec version" warning
If the target is run without explicitly an OpenAPI document version to generate, a warning is output:
Generating document named 'api'.
Using discovered `GenerateAsync` overload with version parameter.
Invalid OpenAPI spec version '' provided. Falling back to default: v3.0.
Writing document named 'api' to './artifacts/openapi\API_api.json'.
This comes from here:
If this Enum.TryParse()
call fails to parse anything:
It looks like there's a few ways to resolve this:
- Assign a default value for
GetDocumentCommandContext.OpenApiVersion
if no value is provided: - Don't emit the warning if
GetDocumentCommandContext.OpenApiVersion
is null/empty (rather than a value that doesn't parse) - Explicitly pass a value for
--openapi-version
through from the MSBuild target:
No MSBuild property for specifying the OpenAPI version
It's possible to add extra options to work around the above using OpenApiGenerateDocumentsOptions
(e.g. /p:OpenApiGenerateDocumentsOptions="--openapi-version OpenApi3_0"
), but there isn't a specific MSBuild property for this.
To make usage easier a property could be defined that the user can specify to set the version without needing to explicitly set command line parameters that the MSBuild target could transform and pass through to the tool (e.g. /p:OpenApiGenerateDocumentVersion=3.0
into --openapi-version OpenApi3_0
).
MSBuild properties not affecting "up-to-date-ness"
I noticed when the path wasn't being fully evaluated, if I re-ran the build with a different input property the document wouldn't be regenerated.
For example:
❯ dotnet build ./src/API /p:OpenApiGenerateDocuments=true /p:OpenApiDocumentsDirectory="${OutputDirectory}"
Restore complete (1.9s)
You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
API succeeded (16.5s) → artifacts\bin\API\debug\API.dll
Build succeeded in 21.8s
api on dotnet-nightly [$] via .NET v9.0.100-preview.7.24375.12 took 22s
❯ dotnet build ./src/API /p:OpenApiGenerateDocuments=true /p:OpenApiDocumentsDirectory="${OutputDirectory}2"
Restore complete (0.5s)
You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
API succeeded (1.0s) → artifacts\bin\API\debug\API.dll
Build succeeded in 4.4s
api on dotnet-nightly [$] via .NET v9.0.100-preview.7.24375.12 took 4s
The first command creates the API document at ${OutputDirectory}
in ~20 seconds.
The second command with the output path set to ${OutputDirectory}2
doesn't emit anything and takes ~4 seconds.
It seems like the properties being passed through aren't affecting MSBuild up-to-date checks and causing the document not to be re-generated.
Output directory value isn't checked for
I made a mistake during playing with the tool and accidentally un-defined the variable for the output path. This then causes an ArgumentException
to be thrown inside the tool (--output ""
). Should something check a value is specified first?
❯ dotnet build ./src/API /p:OpenApiGenerateDocuments=true /p:OpenApiDocumentsDirectory="${OutputDirectory}" /p:OpenApiGenerateDocumentsOptions="--openapi-version OpenApi3_0"
Restore complete (0.6s)
You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
API failed with 6 error(s) (12.4s) → artifacts\bin\API\debug\API.dll
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error : System.ArgumentException: The value cannot be an empty string. (Parameter 'path')
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error : at System.ArgumentException.ThrowNullOrEmptyException(String argument, String paramName)
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error : at System.IO.Directory.CreateDirectory(String path)
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error : at Microsoft.Extensions.ApiDescription.Tool.Commands.GetDocumentCommandWorker.GetDocuments(IServiceProvider services)
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error : at Microsoft.Extensions.ApiDescription.Tool.Commands.GetDocumentCommandWorker.Process()
C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\Microsoft.Extensions.ApiDescription.Server.targets(66,5): error MSB3073: The command "dotnet "C:\Users\Martin.Costello\.nuget\packages\microsoft.extensions.apidescription.server\9.0.0-preview.7.24375.8\build\../tools/dotnet-getdocument.dll" --assembly "C:\Coding\martincostello\api\artifacts\bin\API\debug\API.dll" --file-list "C:\Coding\martincostello\api\artifacts\obj\API\API.OpenApiFiles.cache" --framework ".NETCoreApp,Version=v9.0" --output "" --project "API" --assets-file "C:\Coding\martincostello\api\artifacts\obj\API\project.assets.json" --platform "AnyCPU" --openapi-version OpenApi3_0" exited with code 11.