Skip to content

swagger.json missing "paths" when deployed as Azure Functions from DevOps #157

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

Closed
binarybasher opened this issue Jun 30, 2021 · 18 comments
Closed

Comments

@binarybasher
Copy link

This works locally and works when I publish from VS directly to Azure Functions.

When I run this through DevOps Build Pipeline and Release to Azure Functions everything is working except the "paths" property in the swagger.json file is empty.

Windows target system.

{
  "swagger": "2.0",
  "info": {
    "title": "Azure Functions OpenAPI Extension",
    "version": "1.0.0"
  },
  "host": "........azurewebsites.net",
  "basePath": "/api/v1",
  "schemes": [
    "https"
  ],
  "paths": { }
}

No errors in the Azure Functions LogStream.

2021-06-30T21:02:59.179 [Information] Executing 'Functions.RenderSwaggerDocument' (Reason='This function was programmatically called via the host APIs.', Id=000000-c94f-4960-9752-5557d5d998e5)
2021-06-30T21:02:59.180 [Information] swagger.json was requested.
2021-06-30T21:02:59.180 [Information] Executed 'Functions.RenderSwaggerDocument' (Succeeded, Id=000000-c94f-4960-9752-5557d5d998e5, Duration=1ms)

What reasons might prevent the "paths" property from populating? I assume it's dynamically generated at runtime?

Does it require any write permissions to the file system for instance?

It's hard to debug as it doesn't appear to show any errors.

@justinyoo
Copy link
Contributor

@binarybasher Thanks for the issue! Please make sure that all four endpoint starting with Render* are only shown on your local dev environment. Once it's deployed to Azure, they're all encapsulated..

@binarybasher
Copy link
Author

binarybasher commented Jul 1, 2021

Thanks for your response @justinyoo

Are you saying that the automated swagger.json is not created in Azure because it's only for the dev environment?

And what do you mean by "they're all encapsulated"? I wanted to expose the API using this automated swagger.json and the Azure Functions API definition.

If I wanted to use this auto-generated swagger.json in Azure, could I use the proxy configuration to enable it?

https://github.com/Azure/azure-functions-openapi-extension/blob/main/docs/shortening-swagger-ui-page-url.md

@kvargas94
Copy link

I have the same issue...

@kvargas94
Copy link

@justinyoo
Copy link
Contributor

in this https://github.com/Azure/azure-functions-openapi-extension/blob/main/docs/enable-open-api-endpoints.md
image
you say that is deploying the swagger ui.

@kvargas94 Oh, yes. The screenshot should be updated. It reflects the old version of this library.

@justinyoo
Copy link
Contributor

justinyoo commented Jul 4, 2021

And what do you mean by "they're all encapsulated"? I wanted to expose the API using this automated swagger.json and the Azure Functions API definition.

@binarybasher Your function endpoints you write, excepts 4 endpoints starting with Render, will be shown on Azure. The 4 OpenAPI-specific endpoints are also deployed to Azure and working, but hidden on the Portal.

@binarybasher
Copy link
Author

binarybasher commented Jul 4, 2021

@justinyoo thanks, that explains why I couldn't see the swagger endpoints although I could see them running when called.

What I'm confused about is why the "paths" property of the dynamically generated swagger.json is empty, this happens when I publish from Azure DevOps Pipeline, but it works fine if I publish from VS to Azure.

Why would the "paths" property fail to generate anything? There doesn't appear to be any errors reported.

I suspect it is either by design and there's a setting for this? if so, please can you explain how I can activate it?

Otherwise, I'm thinking it relates to not loading the assembly or if it does load the assembly then it fails to locate the OpenApi attributes.

Could do with some help as to why the "paths" is empty and how I might populate that.

Thanks

@justinyoo
Copy link
Contributor

What I'm confused about is why the "paths" property of the dynamically generated swagger.json is empty, this happens when I publish from Azure DevOps Pipeline, but it works fine if I publish from VS to Azure.

Did you expect those 4 endpoints to be shown up on your swagger.json? They won't be showing up on your Swagger UI nor OpenAPI document (swagger.json), as they are NOT yours.

Why would the "paths" property fail to generate anything? There doesn't appear to be any errors reported.

Have you implemented any endpoint of yours? Again, only yours will be showing up, not those 4 endpoints (these are not "yours"). Did you fail to see your endpoints on swagger.json?

@binarybasher
Copy link
Author

@justinyoo I didn't expect to see the render endpoints no, I expected the swagger.json (dynamically created) to contain the "paths" data, which it does if I publish from VS or run locally.

It shows an empty "paths" property when deployed through DevOps to Azure, that's the issue, so the question is why and how to resolve?

{ "swagger": "2.0", "info": { "title": "Azure Functions OpenAPI Extension", "version": "1.0.0" }, "host": "........azurewebsites.net", "basePath": "/api/v1", "schemes": [ "https" ], "paths": { } }

Thanks

@justinyoo
Copy link
Contributor

That's what I'm asking.

Which endpoints are you expecting to see - yours or mine? Mines are those 4 endpoints and you won't be able to see mines on Azure - meaning, mines won't be included in the paths attribute of your swagger.json.

If you can't even see yours in the paths attribute, please let me know how to reproduce this error on my end.

@binarybasher
Copy link
Author

@justinyoo indeed it is our application endpoints that are missing from the generated "paths" property, they appear when running the project locally and they appear if we publish from visual studio to Azure Functions.

Example from project run locally
"paths": { "/application-settings": { "post": { "tags": [ "Application Settings" ], "summary": "Create new Application Settings", "operationId": "Create", "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "in": "body", "name": "body", "schema": { "$ref": "#/definitions/applicationSettings" } } ], "responses": { "200": { "description": "The OK response", "schema": { "$ref": "#/definitions/successResponseModel_applicationSettings" } }, "400": { "description": "The Bad Request response", "schema": { "$ref": "#/definitions/badResponseModel" } } }, "security": [ { "function_key": [ ] } ] }, "put": { "tags": [ "Application Settings" ], "summary": "Update existing Application Settings", "operationId": "Update", "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "in": "body", "name": "body", "schema": { "$ref": "#/definitions/applicationSettings" } } ], "responses": { "200": { "description": "The OK response", "schema": { "$ref": "#/definitions/successResponseModel_applicationSettings" } }, "400": { "description": "The Bad Request response", "schema": { "$ref": "#/definitions/badResponseModel" } } }, "security": [ { "function_key": [ ] } ] } }, "/application-settings/{id}": { "get": { "tags": [ "Application Settings" ], "summary": "Read existing Application Settings", "operationId": "Read", "produces": [ "application/json" ], "parameters": [ { "in": "path", "name": "id", "description": "The **id** parameter", "required": true, "type": "string" } ], "responses": { "200": { "description": "The OK response", "schema": { "$ref": "#/definitions/successResponseModel_applicationSettings" } }, "400": { "description": "The Bad Request response", "schema": { "$ref": "#/definitions/badResponseModel" } } }, "security": [ { "function_key": [ ] } ] }, "delete": { "tags": [ "Application Settings" ], "summary": "Delete existing Application Settings", "operationId": "Delete", "produces": [ "application/json" ], "parameters": [ { "in": "path", "name": "id", "description": "The **id** parameter", "required": true, "type": "string" } ], "responses": { "200": { "description": "The OK response", "schema": { "$ref": "#/definitions/successResponseModel_object" } }, "400": { "description": "The Bad Request response", "schema": { "$ref": "#/definitions/badResponseModel" } } }, "security": [ { "function_key": [ ] } ] } } }

However, they do not appear when we deploy using DevOps pipeline.

Actually, I've just done some testing and it seems it is not the deployment, but rather the build itself that is causing the issue.

Something in the DevOps build pipeline is causing the "paths" to be empty, tested by downloading the artifacts zip and running from the func cli.

If you have any thoughts then please let me know, I'll continue to investigate.

@binarybasher
Copy link
Author

binarybasher commented Jul 4, 2021

@justinyoo I tried a few build commands locally and I can reproduce the issue with the missing 'paths' property values.

The following build commands are successful and the functions run just fine, except the swagger.json 'paths' is empty.

dotnet build --output .\bin\Release\netcoreapp3.1
dotnet build ....csproj /p:DeployOnBuild=false -c Release -o ".\Properties\PublishProfiles\temp3" -p:PublishReadyToRun=true -p:PublishTrimmed=true -f "netcoreapp3.1"

I've found that I need to use the msbuild option to build and then the swagger.json 'paths' property has the values as expected.

dotnet msbuild "....csproj" -p:Configuration=Release;TargetFramworkVersion=netcoreapp3.1  -property:OutDir=".\publish_output" -ds -verbosity:n

@binarybasher
Copy link
Author

@justinyoo weirdly when I use the msbuild command in the DevOps pipeline it produces output that runs but doesn't generate the 'paths' value, still....

@justinyoo
Copy link
Contributor

Alright, we're now on the same page (at least I understand what I am talking...).

  • What version of AzFunc OpenAPI extension did you use? The latest one is 0.7.2-preview.
  • What NuGet packages are you using, other than this extension?
  • Can you please share bare minimum repro code with me? I don't need your business logic but the methods decorated with those [OpenApi...] attribute classes. Replace all the business logic in the method with return new OkResult(); like:
// Function1.cs
[FunctionName(...)]
[OpenApiXXX(...)]
[OpenApiXXX(...)]
public static async Task<IActionResult> Run([HttpTrigger(...)] HttpRequest req, ILogger log)
{
    return new OkResult();
}
  • Can you also share your .csproj file with NuGet package references and other specific settings that are worth considering?
// Function.csproj
<Project Sdk="Microsoft.NET.Sdk">
  ...
  <ItemGroup>
    <PackageReference Include="XXXXX" Version="a.b.c" />
  </ItemGroup>
  ...

  <!-- Any other specific settings worth sharing -->
</Project>

For now, I can think of the workaround is...

  1. Build the artifact on your local machine through CLI - either dotnet CLI or azfunc CLI, not Visual Studio
  2. Deploy the artifact to Azure through CLI - either azure CLI or azfunc CLI or PowerShell
  3. If it works as expected, do the same thing on your AzDevOps pipeline

@justinyoo
Copy link
Contributor

Just FYI - here's my GitHub Actions workflow for my toy project using this extension:

https://github.com/aliencube/GymLog/blob/main/.github/workflows/app.yaml

Which uses dotnet CLI and azure CLI for build, test and deploy.


Here's another suggestion:

If you can capture the build/test/deploy commands from the Visual Studio output window, can you apply those commands to your AzDevOps pipeline and see how it's going?

@binarybasher
Copy link
Author

@justinyoo I prepared the minimum code to send over to you, but then decided to review your yaml settings beforehand.

I noticed that you was performing a restore, build and publish (artifacts) separately and thought I should try this too.

I setup my pipeline in the same way, with the following:

  • dotnet restore . (retrieves resources/packages)
  • dotnet build -c Release (builds project)
  • dotnet publish -c Release -o (not entirely sure this is necessary, but it basically moves the build files to a publish folder)
  • archive to zip (compresses published build folder, may not be necessary as publish option can zip files)
  • publish build artifacts (published to a artifacts folder reader for a release pipeline to push to Azure)

Interestingly this solved the issue... at least it worked when I tested just now 👍

I guess there's no need to send the minimum code now :-)

It's odd that the issue exists though and it's not entirely clear why, happy to investigate further but it does appear to be build related.

Thanks @justinyoo for your help with this matter.

@justinyoo
Copy link
Contributor

@binarybasher Glad it's sorted out! Yeah, I agree that there are some odds during the build, which is a bit unclear. It would be great if you can do further investigation.

For now, I'm closing this issue.

@agravity-philipp
Copy link

Hi @binarybasher ! As you are using Azure DevOps and I ran in the same issue may I ask you to share the pipeline.yaml file?

Hi @justinyoo - Is this solved in 0.9.0-preview (#225) and when will this be released?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants