Skip to content

Commit

Permalink
feat: GH workflow to build API clients from OpenAPI spec (thus valida…
Browse files Browse the repository at this point in the history
…ting the spec)

Signed-off-by: Paul Horton <phorton@sonatype.com>
  • Loading branch information
madpah committed Nov 15, 2024
1 parent de44ad6 commit d7ca7ee
Show file tree
Hide file tree
Showing 11 changed files with 255 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* @oej
* @madpah
165 changes: 165 additions & 0 deletions .github/workflows/test-generate-api-clients.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
name: Build & Test Generated API Clients

on:
push:
branches: ['main']
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
OPEN_API_GENERATOR_VERSION: 'v7.9.0'
PYTHON_VERSION_DEFAULT: '3.12'
POETRY_VERSION: '1.8.1'

jobs:
generate-library-code:
name: Generate Library Code ${{ matrix.language }}
runs-on: ubuntu-latest
strategy:
matrix:
language: ['go', 'java-webclient', 'python', 'typescript']
steps:
- name: Checkout
# see https://github.com/actions/checkout
uses: actions/checkout@v4

- name: Create Output Directory
run: mkdir out/${{ matrix.language }}

- name: Run OpenAPI Generator
uses: addnab/docker-run-action@v3
with:
image: openapitools/openapi-generator-cli:${{ env.OPEN_API_GENERATOR_VERSION }}
options: -v ${{ github.workspace }}:/local
run: /usr/local/bin/docker-entrypoint.sh batch --clean /local/spec/generators/${{ matrix.language }}.yaml

- name: Copy our scripts across too
run: cp spec/generators/*.sh ./out/${{ matrix.language }}

- name: Save to Cache
uses: actions/cache/save@v4
with:
path: out/${{ matrix.language }}
key: '${{ matrix.language }}-${{ github.run_id }}'

validate-go:
name: Validate Go Library
runs-on: ubuntu-latest
needs: generate-library-code

steps:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22

- name: Get generated code from cache
uses: actions/cache/restore@v4
with:
path: out/go
key: 'go-${{ github.run_id }}'
fail-on-cache-miss: true

- name: Build Go API Client
run: go build -v ./
working-directory: out/go

- name: Install test dependencies & run generated tests
run: |
go get github.com/stretchr/testify/assert
go test -v ./test/
working-directory: out/go

validate-java-webclient:
name: Validate Java Webclient
runs-on: ubuntu-latest
needs: generate-library-code

steps:
- name: Set up JDK 17 for x64
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
architecture: x64

- name: Set up Maven
uses: stCarolas/setup-maven@v5
with:
maven-version: 3.9.4

- name: Get generated code from cache
uses: actions/cache/restore@v4
with:
path: out/java-webclient
key: 'java-webclient-${{ github.run_id }}'
fail-on-cache-miss: true

- name: Build & Test Java Webclient API Client
run: |
./update-pom.sh pom.xml
mvn clean test
working-directory: out/java-webclient

validate-python:
name: Validate Python Library
runs-on: ubuntu-latest
needs: generate-library-code

steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION_DEFAULT }}

- name: Install poetry
# see https://github.com/marketplace/actions/setup-poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: ${{ env.POETRY_VERSION }}

- name: Get generated code from cache
uses: actions/cache/restore@v4
with:
path: out/python
key: 'python-${{ github.run_id }}'
fail-on-cache-miss: true

- name: Install dependencies
run: poetry install --no-root
working-directory: out/python

- name: Ensure build successful
run: poetry build
working-directory: out/python

- name: Run Tests
run: |
pip install -r test-requirements.txt
poetry run pytest
working-directory: out/python

validate-typescript:
name: Validate Typescript Library
runs-on: ubuntu-latest
needs: generate-library-code

steps:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: latest

- name: Get generated code from cache
uses: actions/cache/restore@v4
with:
path: out/typescript
key: 'typescript-${{ github.run_id }}'
fail-on-cache-miss: true

- name: Build Typescript API Client
run: npm i && npm run build
working-directory: out/typescript
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.idea/
out
13 changes: 13 additions & 0 deletions spec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# TEA OpenAPI Spec

The OpenAPI 3.1 specification for the Transparency Exchange API is available in [openapi.json](./openapi.json).

- [Generating API Clients from OpenAPI Spec](#generating-api-clients-from-openapi-spec)

## Generating API Clients from OpenAPI Spec

We use the OpenAPI Generator with configuration per language/framework in the `generators` folder. An example is:

```
docker run --rm -v "$(PWD):/local" openapitools/openapi-generator-cli batch --clean /local/spec/generators/typescript.yaml
```
6 changes: 6 additions & 0 deletions spec/generators/common.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
inputSpec: /local/spec/openapi.json
gitUserId: CycloneDX
gitRepoId: transparency-exchange-api

globalProperties:
skipFormModel: false
7 changes: 7 additions & 0 deletions spec/generators/go.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'!include': 'common.yaml'
outputDir: /local/out/go
generatorName: go
gitRepoId: transparency-exchange-api-go
additionalProperties:
goImportAlias: tea_client
packageName: tea_client
27 changes: 27 additions & 0 deletions spec/generators/java-webclient.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'!include': 'common.yaml'
outputDir: /local/out/java-webclient
generatorName: java
additionalProperties:
library: webclient
artifactDescription: Transparency Exchange API Java Webclient
artifactId: tea-api-webclient
artifactUrl: https://github.com/CycloneDX/transparency-exchange-api
invokerPackage: org.cyclonedx.tea.webclient
apiPackage: org.cyclonedx.tea.webclient.api
modelPackage: org.cyclonedx.tea.webclient.model
developerEmail: community@sonatype.com
developerName: OWASP Foundation
developerOrganization: OWASP Foundation
developerOrganizationUrl: https://cyclonedx.org/
groupId: org.cyclonedx.tea
licenseName: Apache-2.0
licenseUrl: https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE
scmConnection: scm:git:git@github.com:CycloneDX/transparency-exchange-api.git
scmDeveloperConnection: scm:git:git@github.com:CycloneDX/transparency-exchange-api.git
scmUrl: https://github.com/CycloneDX/transparency-exchange-api
useJakartaEe: true
asyncNative: true
generateBuilders: true
parentGroupId: org.sonatype.buildsupport
parentArtifactId: public-parent
parentVersion: 50
8 changes: 8 additions & 0 deletions spec/generators/python.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'!include': 'common.yaml'
outputDir: /local/out/python
generatorName: python
additionalProperties:
library: urllib3
licenseInfo: "Apache-2.0"
packageName: "tea-api-client"
projectName: "Transparency Exchange API (TEA)"
7 changes: 7 additions & 0 deletions spec/generators/typescript.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'!include': 'common.yaml'
outputDir: /local/out/typescript
generatorName: typescript-fetch
additionalProperties:
npmName: "@cyclonedx/tea-api-client"
supportsES6: true
withInterfaces: true
15 changes: 15 additions & 0 deletions spec/generators/update-pom.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

# Check if the file path is provided
if [ -z "$1" ]; then
echo "Usage: $0 <path-to-xml-file>"
exit 1
fi

# File path
FILE=$1

# Use sed to remove the <build> tag and its content
sed -i.bak '/<build>/,/<\/build>/d' "$FILE"

echo "The <build> tag has been removed from $FILE. A backup has been saved as $FILE.bak."
9 changes: 4 additions & 5 deletions spec/openapi.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://spec.openapis.org/oas/3.1/dialect/base",
"jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base",
"openapi": "3.1.1",
"info": {
"title": "Transparency Exchange API",
Expand All @@ -11,7 +11,7 @@
"url": "https://github.com/CycloneDX/transparency-exchange-api"
},
"license": {
"identifier": "Apache-2.0",
"name": "Apache 2.0",
"url": "https://github.com/CycloneDX/transparency-exchange-api/blob/main/LICENSE"
},
"version": "0.0.1"
Expand Down Expand Up @@ -459,8 +459,7 @@
},
"type-uuid": {
"type": "string",
"format": "uuid",
"required": true
"format": "uuid"
}
},
"responses": {
Expand Down Expand Up @@ -507,7 +506,7 @@
"name": "product-version",
"description": "Product Version string",
"in": "path",
"reqiured": true,
"required": true,
"schema": {
"type": "string"
}
Expand Down

0 comments on commit d7ca7ee

Please sign in to comment.