Around five years ago, for OSN 2021, I gave a talk on Full Stack CICD of Kubernetes Microservices using DevOps and IAC. I was discussing some of our setup we used at Medtronic for the CRHF group and specifically I spoke on using Swagger gen for .NET and Java client bindings.
Recently, I was made aware of a refresh of that Swagger gen project called OpenAPITools/OpenApi-Generator.
It is a java app so you can easily pull it down and run it with anything newer than JDK 11. However, I had adding Java to anything (not because I have a hatred of Java, just it’s a lot of bloat just to run a tool).
Docker
That’s when I saw that it actually has a docker invokation we can use:
$ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml \
-g go \
-o /local/out/go
Unable to find image 'openapitools/openapi-generator-cli:latest' locally
latest: Pulling from openapitools/openapi-generator-cli
0926a8eb0e60: Pull complete
2ea1b5f47032: Pull complete
0976d588e0c1: Pull complete
92228cd89f0b: Pull complete
0036e81299df: Pull complete
11f24e9ce103: Pull complete
1309e6003457: Pull complete
9a17b487c630: Pull complete
Digest: sha256:03b6ef20a0b31ed7bc9fbb2bd4bd6c2ffdc76c6a8e1fec519d6fd032acf3f95b
Status: Downloaded newer image for openapitools/openapi-generator-cli:latest
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/local/out/go) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: go (client)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'go' is considered stable.
[main] INFO o.o.c.languages.AbstractGoCodegen - Environment variable GO_POST_PROCESS_FILE not defined so Go code may not be properly formatted. To define it, try `export GO_POST_PROCESS_FILE="/usr/local/bin/gofmt -w"` (Linux/Mac)
[main] INFO o.o.c.languages.AbstractGoCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO o.o.codegen.InlineModelResolver - Inline schema created as updatePetWithForm_request. To have complete control of the model name, set the `title` field or use the modelNameMapping option (e.g. --model-name-mappings updatePetWithForm_request=NewModel,ModelA=NewModelA in CLI) or inlineSchemaNameMapping option (--inline-schema-name-mappings updatePetWithForm_request=NewModel,ModelA=NewModelA in CLI).
[main] INFO o.o.codegen.InlineModelResolver - Inline schema created as uploadFile_request. To have complete control of the model name, set the `title` field or use the modelNameMapping option (e.g. --model-name-mappings uploadFile_request=NewModel,ModelA=NewModelA in CLI) or inlineSchemaNameMapping option (--inline-schema-name-mappings uploadFile_request=NewModel,ModelA=NewModelA in CLI).
[main] INFO o.o.codegen.DefaultGenerator - Model updatePetWithForm_request not generated since it's marked as unused (due to form parameters) and `skipFormModel` (global property) set to true (default)
[main] INFO o.o.codegen.DefaultGenerator - Model uploadFile_request not generated since it's marked as unused (due to form parameters) and `skipFormModel` (global property) set to true (default)
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_api_response.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/ApiResponse.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_category.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/Category.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_order.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/Order.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_pet.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/Pet.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_tag.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/Tag.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/model_user.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/User.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/api_pet.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/test/api_pet_test.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/PetAPI.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/api_store.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/test/api_store_test.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/StoreAPI.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/api_user.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/test/api_user_test.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/docs/UserAPI.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/api/openapi.yaml
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/README.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/git_push.sh
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/.gitignore
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/configuration.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/client.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/response.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/go.mod
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/go.sum
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/.travis.yml
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/utils.go
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/.openapi-generator-ignore
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/.openapi-generator/VERSION
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/go/.openapi-generator/FILES
############################################################################################
# Thanks for using OpenAPI Generator. #
# We appreciate your support! Please consider donating to help us maintain this project. #
# https://opencollective.com/openapi_generator/donate #
############################################################################################
We can see that command produced go bindings in the “./out” directory for the swagger at https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
That is a good test, but what about a real service?
I have a FastAPI service I use for posting to Bluesky, Threads and Mastodon at bskyposter.steeped.icu. Can it generate from that swagger?
Let’s try passing in the OpenAPI JSON and creating some Python bindings:
$ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
-i https://bskyposter.steeped.icu/openapi.json \
-g python \
-o /local/out/python
Here we can see it created them without issue
builder@bosgamerz9:~/Workspaces/fbsnew/out/python$ ls
README.md docs git_push.sh openapi_client pyproject.toml requirements.txt setup.cfg setup.py test test-requirements.txt tox.ini
builder@bosgamerz9:~/Workspaces/fbsnew/out/python$ ls openapi_client/
__init__.py api api_client.py api_response.py configuration.py exceptions.py models py.typed rest.py
We can look at the test files for example usage
builder@bosgamerz9:~/Workspaces/fbsnew/out/python/test$ cat test_social_post.py
# coding: utf-8
"""
FastAPI
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.1.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import unittest
from openapi_client.models.social_post import SocialPost
class TestSocialPost(unittest.TestCase):
"""SocialPost unit test stubs"""
def setUp(self):
pass
def tearDown(self):
pass
def make_instance(self, include_optional) -> SocialPost:
"""Test SocialPost
include_optional is a boolean, when False only required
params are included, when True both required and
optional params are included """
# uncomment below to create an instance of `SocialPost`
"""
model = SocialPost()
if include_optional:
return SocialPost(
username = '',
password = '',
text = '',
link = '',
baseurl = ''
)
else:
return SocialPost(
username = '',
password = '',
text = '',
)
"""
def testSocialPost(self):
"""Test SocialPost"""
# inst_req_only = self.make_instance(include_optional=False)
# inst_req_and_optional = self.make_instance(include_optional=True)
if __name__ == '__main__':
unittest.main()
I couldn’t find docs for what languages were supported so on a whim I tried my favourite, Perl.
$ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate -i https://bskyposter.steeped.icu/openapi.json -g perl -o /local/out/perl
[main] WARN o.o.codegen.DefaultCodegen - OpenAPI 3.1 support is still in beta. To report an issue related to 3.1 spec, please kindly open an issue in the Github repo: https://github.com/openAPITools/openapi-generator.
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/local/out/perl) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: perl (client)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'perl' is considered stable.
[main] INFO o.o.c.languages.PerlClientCodegen - Environment variable PERL_POST_PROCESS_FILE not defined so the Perl code may not be properly formatted. To define it, try 'export PERL_POST_PROCESS_FILE=/usr/local/bin/perltidy -b -bext="/"' (Linux/Mac)
[main] INFO o.o.c.languages.PerlClientCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO o.o.codegen.InlineModelResolver - Inline schema created as Location_inner. To have complete control of the model name, set the `title` field or use the modelNameMapping option (e.g. --model-name-mappings Location_inner=NewModel,ModelA=NewModelA in CLI) or inlineSchemaNameMapping option (--inline-schema-name-mappings Location_inner=NewModel,ModelA=NewModelA in CLI).
[main] INFO o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Object/HTTPValidationError.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/HTTPValidationErrorTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/HTTPValidationError.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Object/LocationInner.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/LocationInnerTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/LocationInner.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Object/SocialPost.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/SocialPostTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/SocialPost.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Object/ThreadsPost.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/ThreadsPostTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/ThreadsPost.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Object/ValidationError.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/ValidationErrorTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/ValidationError.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/DefaultApi.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/t/DefaultApiTest.t
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/docs/DefaultApi.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/ApiClient.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Configuration.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/ApiFactory.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Role.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/lib/WWW/OpenAPIClient/Role/AutoDoc.pm
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/bin/autodoc
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/README.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/.gitignore
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/git_push.sh
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/.travis.yml
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/cpanfile
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/.openapi-generator-ignore
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/.openapi-generator/VERSION
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/perl/.openapi-generator/FILES
################################################################################
# Thanks for using OpenAPI Generator. #
# Please consider donating to help us maintain this project 🙏 #
# https://opencollective.com/openapi_generator/donate #
# #
# This generator is created by wing328 (https://github.com/wing328) #
# Please support his work directly by purchasing a copy of the eBook 📘 #
# - OpenAPI Generator for Perl Developers https://bit.ly/2OId6p3 #
################################################################################
And indeed it created the Perl modules (pm) and markdown docs
builder@bosgamerz9:~/Workspaces/fbsnew/out/python/test/out$ tree ./perl/
./perl/
├── bin
│ └── autodoc
├── cpanfile
├── docs
│ ├── DefaultApi.md
│ ├── HTTPValidationError.md
│ ├── LocationInner.md
│ ├── SocialPost.md
│ ├── ThreadsPost.md
│ └── ValidationError.md
├── git_push.sh
├── lib
│ └── WWW
│ └── OpenAPIClient
│ ├── ApiClient.pm
│ ├── ApiFactory.pm
│ ├── Configuration.pm
│ ├── DefaultApi.pm
│ ├── Object
│ │ ├── HTTPValidationError.pm
│ │ ├── LocationInner.pm
│ │ ├── SocialPost.pm
│ │ ├── ThreadsPost.pm
│ │ └── ValidationError.pm
│ ├── Role
│ │ └── AutoDoc.pm
│ └── Role.pm
├── README.md
└── t
├── DefaultApiTest.t
├── HTTPValidationErrorTest.t
├── LocationInnerTest.t
├── SocialPostTest.t
├── ThreadsPostTest.t
└── ValidationErrorTest.t
9 directories, 27 files
I threw a made up command just to see the supported languages:
- ada
- ada-server
- android
- apache2
- apex
- asciidoc
- aspnet-fastendpoints
- aspnetcore
- avro-schema
- bash
- crystal
- c
- clojure
- cwiki
- cpp-httplib-server
- cpp-boost-beast-client
- cpp-oatpp-client
- cpp-qt-client
- cpp-qt-qhttpengine-server
- cpp-oatpp-server
- cpp-pistache-server
- cpp-restbed-server
- cpp-restbed-server-deprecated
- cpp-restsdk
- cpp-tiny
- cpp-tizen
- cpp-ue4
- csharp
- csharp-functions
- dart
- dart-dio
- eiffel
- elixir
- elm
- erlang-client
- erlang-proper
- erlang-server
- erlang-server-deprecated
- fsharp-functions
- fsharp-giraffe-server
- gdscript
- go
- go-echo-server
- go-server
- go-gin-server
- graphql-schema
- graphql-nodejs-express-server
- groovy
- haskell-http-client
- haskell
- haskell-yesod
- java
- java-dubbo
- jaxrs-cxf-client
- java-helidon-client
- java-helidon-server
- java-inflector
- java-micronaut-client
- java-micronaut-server
- java-msf4j
- java-pkmst
- java-play-framework
- java-undertow-server
- java-vertx
- java-vertx-web
- java-camel
- jaxrs-cxf
- jaxrs-cxf-extended
- jaxrs-cxf-cdi
- jaxrs-jersey
- java-microprofile
- jaxrs-resteasy
- jaxrs-resteasy-eap
- jaxrs-spec
- javascript
- javascript-apollo-deprecated
- javascript-flowtyped
- javascript-closure-angular
- java-wiremock
- jetbrains-http-client
- jmeter
- julia-client
- julia-server
- k6
- kotlin
- kotlin-misk
- kotlin-server
- kotlin-spring
- kotlin-vertx
- kotlin-wiremock
- ktorm-schema
- lua
- markdown
- mysql-schema
- n4js
- nim
- nodejs-express-server
- objc
- ocaml
- openapi
- openapi-yaml
- plantuml
- perl
- php
- php-flight
- php-nextgen
- php-lumen
- php-slim4
- php-symfony
- php-mezzio-ph
- php-dt
- php-laravel
- postgresql-schema
- postman-collection
- powershell
- protobuf-schema
- python
- python-pydantic-v1
- python-fastapi
- python-flask
- python-aiohttp
- python-blueplanet
- r
- ruby
- ruby-nextgen
- ruby-on-rails
- ruby-sinatra
- rust-axum
- rust
- rust-salvo
- rust-server
- rust-server-deprecated
- scalatra
- scala-akka
- scala-cask
- scala-pekko
- scala-akka-http-server
- scala-finch-deprecated
- scala-gatling
- scala-http4s
- scala-http4s-server
- scala-lagom-server-deprecated
- scala-play-server
- scala-sttp
- scala-sttp4
- scala-sttp4-jsoniter
- scalaz
- spring
- dynamic-html
- html
- html2
- swift5
- swift6
- swift-combine
- terraform-provider
- typescript
- typescript-angular
- typescript-aurelia
- typescript-axios
- typescript-fetch
- typescript-inversify
- typescript-jquery
- typescript-nestjs
- typescript-nestjs-server
- typescript-node
- typescript-redux-query
- typescript-rxjs
- wsdl-schema
- xojo-client
- zapier
I was wondering what “markdown” could mean so I tried that:
$ docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate -i https://bskyposter.steeped.icu/openapi.json -g markdown -o /local/out/markdown
Unable to find image 'openapitools/openapi-generator-cli:latest' locally
latest: Pulling from openapitools/openapi-generator-cli
0926a8eb0e60: Pull complete
2ea1b5f47032: Pull complete
0976d588e0c1: Pull complete
92228cd89f0b: Pull complete
0036e81299df: Pull complete
2e1d7ad8563a: Pull complete
f19fa2625fe2: Pull complete
43e70e10ff2b: Pull complete
Digest: sha256:8fe573ec1e28b2da818f7fc796346259ba911f62a688ccc5e2e6c1ee7ef9088f
Status: Downloaded newer image for openapitools/openapi-generator-cli:latest
[main] WARN o.o.codegen.DefaultCodegen - OpenAPI 3.1 support is still in beta. To report an issue related to 3.1 spec, please kindly open an issue in the Github repo: https://github.com/openAPITools/openapi-generator.
[main] INFO o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/local/out/markdown) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO o.o.codegen.DefaultGenerator - OpenAPI Generator: markdown (documentation)
[main] INFO o.o.codegen.DefaultGenerator - Generator 'markdown' is considered beta.
[main] INFO o.o.codegen.InlineModelResolver - Inline schema created as Location_inner. To have complete control of the model name, set the `title` field or use the modelNameMapping option (e.g. --model-name-mappings Location_inner=NewModel,ModelA=NewModelA in CLI) or inlineSchemaNameMapping option (--inline-schema-name-mappings Location_inner=NewModel,ModelA=NewModelA in CLI).
[main] INFO o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Models/HTTPValidationError.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Models/Location_inner.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Models/SocialPost.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Models/ThreadsPost.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Models/ValidationError.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/Apis/DefaultApi.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/README.md
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/.openapi-generator-ignore
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/.openapi-generator/VERSION
[main] INFO o.o.codegen.TemplateManager - writing file /local/out/markdown/.openapi-generator/FILES
############################################################################################
# Thanks for using OpenAPI Generator. #
# We appreciate your support! Please consider donating to help us maintain this project. #
# https://opencollective.com/openapi_generator/donate #
############################################################################################
It produced pretty solid documentation:
Here is a sample:
SocialPost
Properties
| Name | Type | Description | Notes |
|---|---|---|---|
| USERNAME | String | [default to null] | |
| PASSWORD | String | [default to null] | |
| TEXT | String | [default to null] | |
| LINK | String | [optional] [default to null] | |
| BASEURL | String | [optional] [default to null] |
[Back to Model list] [Back to API list] [Back to README]
BASH is pretty interesting
CICD
Let’s try adding OpenAPI generation to a CICD workflow in Github.
I have a public Gotify App based on FastAPI that might be a good starting place.
I added this CICD workflow which should build the container, but then follow it with client bindings:
name: CI & OpenAPI Client Generator
on:
push:
branches: [ "main", "master" ]
pull_request:
branches: [ "main", "master" ]
workflow_dispatch:
jobs:
build-and-generate:
name: Build Docker and Generate OpenAPI Clients
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker Image
run: |
docker build -t notify-app .
- name: Run Container and Fetch OpenAPI JSON
run: |
docker run -d --name notify-app-container -p 8080:80 notify-app
echo "Waiting for container to start..."
for i in {1..15}; do
if curl -s -f http://localhost:8080/swagger -o openapi.json; then
echo "Successfully downloaded OpenAPI JSON from /swagger endpoint."
break
fi
sleep 1
done
docker stop notify-app-container
docker rm notify-app-container
if [ ! -s openapi.json ]; then
echo "Error: openapi.json is empty or missing."
exit 1
fi
- name: Generate Python Client Bindings
run: |
mkdir -p generated/python
docker run --rm -v "${{ github.workspace }}:/local" \
openapitools/openapi-generator-cli generate \
-i /local/openapi.json \
-g python \
-o /local/generated/python
- name: Generate Markdown Client Bindings
run: |
mkdir -p generated/markdown
docker run --rm -v "${{ github.workspace }}:/local" \
openapitools/openapi-generator-cli generate \
-i /local/openapi.json \
-g markdown \
-o /local/generated/markdown
- name: Upload Python Client Artifact
uses: actions/upload-artifact@v4
with:
name: python-client-bindings
path: generated/python/
- name: Upload Markdown Client Artifact
uses: actions/upload-artifact@v4
with:
name: markdown-client-bindings
path: generated/markdown/
The job completed
Once logged in to Github, we can see the generated artifacts on the build details page (which has Python and Markdown bindings)
The markdown, as expected, gives us good API documentation
And the Python has setup and tests
But let us just say our client is Python, rather some device running Linux leveraging QT with C++. How would we handle that?
We could just swap up “Python” for “cpp-qt-client”:
- name: Generate cpp-qt-client Client Bindings
run: |
mkdir -p generated/cpp-qt-client
docker run --rm -v "${{ github.workspace }}:/local" \
openapitools/openapi-generator-cli generate \
-i /local/openapi.json \
-g cpp-qt-client \
-o /local/generated/cpp-qt-client
- name: Generate Markdown Client Bindings
run: |
mkdir -p generated/markdown
docker run --rm -v "${{ github.workspace }}:/local" \
openapitools/openapi-generator-cli generate \
-i /local/openapi.json \
-g markdown \
-o /local/generated/markdown
- name: Upload cpp-qt-client Client Artifact
uses: actions/upload-artifact@v4
with:
name: cpp-qt-client-bindings
path: generated/cpp-qt-client/
- name: Upload Markdown Client Artifact
uses: actions/upload-artifact@v4
with:
name: markdown-client-bindings
path: generated/markdown/
Once the build completes
We can see the new C++ QT bindings artifacts
which when expanded
has everything you need to add RESTful connectivity with C++ code in QT
Summary
We showed a few examples of how easy it is to generate client bindings and documentation using OpenAPI Generator. The fact that we can now use docker greatly improves ease of use.
Besides using it to pull from know OpenAPI JSON and YAML endpoints, we also showed how to tie it into a Github actions workflow to generate Python, Markdown and QT C++ bindings.
The question one always wrestles with is whether to use a binding library (tight correlation) or just RESTful endpoint (loose correlation). I think for simple services that change rarely, the tight correlation is fine and it enables teams to use whatever language they desire. Loose correlation is generally the best practice, but that does mean more code to maintain.
If anything, I’ll likely use this for handy HTML and MD documentation creation for my apps.