Skip to content

How to automatically generate API client libraries from OpenAPI specifications

Our services are often split into a backend API and one or more clients of that API. Historically we have spent developer effort in manually keeping API clients in sync with backend APIs. The OpenAPI specification describes a YAML and JSON schema for describing APIs in a machine readable form. OpenAPI specifications are convenient to work with; many of our existing backend libraries generate OpenAPI specifications automatically. Teams may also elect to engage in "specification-first" development where one starts with a description of the API in an OpenAPI file and, from that specification, one generates the backend API implementation.

This how-to guide describes how to generate API clients automatically using features in the common pipeline.

Prerequisites

In order to configure OpenAPI-based client generation you will need the following:

  • A backend API GitLab project configured to use the common pipeline.
  • One of:
    • a static OpenAPI specification in a file named openapi.yaml in the root of your repository, or
    • the ability to dynamically generate OpenAPI specifications in CI jobs.

Deliverables

By enabling OpenAPI-based client generation you will get:

  • API client libraries built for several languages. Currently this is Python and TypeScript but that list may grow over time.
  • Distribution packages for the libraries. For example, wheels are built for the Python client libraries.
  • Documentation for the API client packages available in a CI job artefact and, optionally, via GitLab pages.
  • Interactive documentation for the API itself available in a CI job artefact and, optionally, via GitLab pages.
  • For commits on the default branch, API client libraries published in the GitLab package registry.

Basic usage

Add a file named openapi.yaml to the root of your repository with the OpenAPI schema in it. This will trigger a run of the OpenAPI client generator. No additional CI configuration is needed.

Warning

OpenAPI clients will only ever be re-generated when openapi.yaml changes. The version number of the clients is taken from the OpenAPI specification. Note that neither NPM nor PyPI allow re-uploading packages with the same version and so you should make sure to change the version number in openapi.yaml each time it changes.

Generating the schema in CI

If you generate your OpenAPI schema dynamically, you need to explicitly enable OpenAPI client generation by setting the OPENAPI_GENERATOR_ENABLED variable. Additionally you'll need to override the openapi:schema job to generate your schema and write it to the path stored in the OPENAPI_GENERATOR_SCHEMA_ARTIFACT_PATH variable.

For example:

# .gitlab-ci.yml

variables:
  # We need to explicitly enable the OpenAPI generation since we don't have an openapi.yaml file in
  # the root of our repository.
  OPENAPI_GENERATOR_ENABLED: "1"

# We do not ship the OpenAPI schema in the repository and so the openapi:schema job needs to be
# overridden to use our schema generation command.
openapi:schema:
  script:
    - my-schema-generator --output=$OPENAPI_GENERATOR_SCHEMA_ARTIFACT_PATH

Not that the existing openapi:schema job's before_script ensures that the directory containing that path exists and so you do not need a mkdir or equivalent.

Warning

The version number of the clients is taken from the OpenAPI specification. Note that neither NPM nor PyPI allow re-uploading packages with the same version and so you should make sure that commits on the default branch always result in an OpenAPI specifications with a unique version number.

Publishing documentation to GitLab pages

Documentation artefacts are placed in the directory pointed to by the OPENAPI_GENERATOR_DOCS_ARTIFACT_DIR variable. To publish these to GitLab pages, add a pages job to your CI configuration. You will need to set needs and stage appropriately to guarantee that the job runs after documentation artefacts have been created:

.gitlab-ci.yaml
pages:
  stage: production
  needs: null
  pages: true
  script:
    # Create the directory holding the GitLab pages content.
    - mkdir -p public/
    # Copy generated documentation into the GitLab pages directory.
    - cp -r "$OPENAPI_GENERATOR_DOCS_ARTIFACT_DIR/*" public/
  artifacts:
    paths:
      - public
  rules:
    # Only publish to pages for commits to the default branch.
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH

Documentation will then be available in subdirectories from your GitLab pages root. For example, generated documentation for the API itself will appear at .../redoc and TypeScript client documentation at .../typescript-axios.

"Gotchas"

The version number of your API clients is taken directly from the version number in the OpenAPI specification. Package managers such as NPM and PyPI disallow re-publishing packages with identical version numbers. As such you need to ensure that, for static OpenAPI files, the version number of the specification increases each time it changes. For OpenAPI specifications generated dynamically bu CI jobs, ensure that each commit to the default branch results in a different version number.

Summary

In this guide you learned how to generate and publish API client libraries from OpenAPI specifications either stored in your project's repository or generated dynamically by the backend implementation.

Next steps

Read the full reference guide for further customisation.