tuutti.iki.fi

Generating and updating API client libraries automatically from an OpenAPI specification

#automation #github-actions

This post focuses mainly on PHP, but you can use the same method with little tweaks to generate client libraries for any language supported by OpenAPI generator.

Configuration

First we need to create a config.yaml file to provide some metadata. At minimum it should contain at least:

invokerPackage: "PetStore"
packagePath: "php-petstore-client"
packageName: "php-petstore-client"
srcBasePath: "src"
  • invokerPackage is the base namespace of your package.
  • packagePath and packageName are used in various places (like README.md) and should be same as your package’s repository name.
  • srcBasePath is the library’s base path. This is completely optional, but I prefer src/ over the default lib/ folder, so I included it as well.

Create .env:

OPENAPI_URL=https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml
GIT_HOST=github.com
GIT_REPO_ID=php-petstore-client
GIT_USER_ID=username
# You can give any additional arguments here, such as --clean to remove
# previously generated files, or global properties like apiTests=false
# to not to generate test classes.
# See: https://openapi-generator.tech/docs/usage/
OPENAPI_GENERATE_ARGS=--global-property apiTests=false,modelTests=false
# Uncomment this to override openapi-generator version.
# See https://hub.docker.com/r/openapitools/openapi-generator-cli/tags for
# available versions.
# OPENAPI_VERSION=v5.3.0

Create Makefile:

include .env
export
OPENAPI_VERSION ?= latest

default: build-client
openapi-spec:
        curl $(OPENAPI_URL) > openapi-spec

build-client: openapi-spec
        docker container run --rm -v ${PWD}:/app openapitools/openapi-generator-cli:$(OPENAPI_VERSION) \
                generate \
                $(OPENAPI_GENERATE_ARGS) \
                --config /app/config.yaml \
                --input-spec /app/openapi-spec \
                --generator-name php \
                --output /app \
                --git-host="$(GIT_HOST)" \
                --git-repo-id="$(GIT_REPO_ID)" \
                --git-user-id="$(GIT_USER_ID)"

.PHONY: build-client

Building the client

Calling make will download the OpenAPI spec file as openapi-spec. Pass -B flag to make command if you wish to force download the spec file every time client is built.

The current working directory is mounted as a volume into /app and the openapitools/openapi-generator-cli Docker image is used as a standalone executable to generate the actual client into /app folder.

See https://openapi-generator.tech/docs/customization for more information on how to further customize your client.

Automatic updates using pull request workflow

Create .github/workflows/build.yml file:

name: Build
on:
  workflow_dispatch:
  schedule:
    - cron:  '0 2 * * *'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Build the client
        run: make

      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v3
        with:
          committer: GitHub <noreply@github.com>
          author: actions-bot <actions-bot@users.noreply.github.com>
          title: "[automation] Update"
          branch: update

The action above should re-build your client automatically once a week and create a pull request of any changes done in the process.

Adding a workflow_dispatch trigger allows client to be rebuilt manually on Actions -> Build -> Run workflow as well:

Image of workflow

Further automation

One way to automate this even further is to enable Allow auto-merge option, allowing client changes to be automatically updated when the merge requirements (status checks, review count) are met.