OpenAPI Generator Project — Build a Complete Code Generation System
In this tutorial, you will learn about OpenAPI Generator Project. We cover key concepts, practical examples, and best practices to help you master this topic.
This complete project guides you through building a production-ready OpenAPI code generation system that validates specs, generates multi-platform SDKs, runs automated tests, deploys documentation, and manages API versions.
What You'll Learn
How to design a complete code generation system: project structure, spec authoring best practices, multi-language SDK generation, CI/CD automation, version management, package publishing, and monitoring generation health.
Why It Matters
A well-designed code generation system scales API development across teams and platforms. DodaTech's system generates SDKs for 15 languages, serves 200+ integration partners, and reduces API integration time from days to minutes.
Real-World Use
A startup needs to publish a public API with web, mobile, and backend SDKs. Using this project, they design a single OpenAPI spec, generate 6 SDKs, set up CI/CD with GitHub Actions, manage versions with automated changelogs, and publish to npm, PyPI, and Maven Central.
flowchart LR
A["Design\nAPI Spec"] --> B["Validate\nSpec"]
B --> C["Generate\nSDKs"]
C --> D["Test\nGenerated Code"]
D --> E{"All Tests\nPass?"}
E -->|"No"| B
E -->|"Yes"| F["Update\nChangelog"]
F --> G["Publish\nPackages"]
G --> H["Deploy\nAPI Docs"]
H --> I["Monitor &\nIterate"]
style B fill:#fef3c7,stroke:#d97706
style G fill:#bbf7d0,stroke:#16a34a
style H fill:#6cb4ee,color:#fff
Project Structure
# Complete project directory structure:
# api-codegen-system/
# specs/
# v1/
# openapi.yaml
# changelog.md
# v2/
# openapi.yaml
# changelog.md
# latest -> v2
# codegen/
# python-fastapi.yaml
# typescript-fetch.yaml
# swift5.yaml
# kotlin.yaml
# html-docs.yaml
# templates/
# custom/
# controller.mustache
# model.mustache
# scripts/
# validate.sh
# generate-all.sh
# test-generated.sh
# publish-sdks.sh
# generate-changelog.py
# bump-version.py
# .github/
# workflows/
# codegen.yml
# output/
# .gitkeep
echo "Project structure created"
# Expected output:
# Project structure created
Spec Design
# specs/v2/openapi.yaml
openapi: 3.0.3
info:
title: Orders API
description: |
Orders API for managing customer orders.
Used by DodaTech's e-commerce platform.
version: 2.0.0
contact:
name: API Team
email: api@dodatech.com
servers:
- url: https://api.dodatech.com/v2
description: Production
paths:
/orders:
get:
operationId: listOrders
summary: List customer orders
parameters:
- name: limit
in: query
schema:
type: integer
maximum: 100
default: 20
- name: status
in: query
schema:
type: string
enum: [pending, confirmed, shipped, delivered]
responses:
'200':
description: Order list
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Order'
post:
operationId: createOrder
summary: Create a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOrderRequest'
responses:
'201':
description: Order created
headers:
Location:
schema:
type: string
components:
schemas:
Order:
type: object
required: [id, customer_id, items, total]
properties:
id:
type: string
format: uuid
customer_id:
type: string
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
total:
type: number
status:
type: string
enum: [pending, confirmed, shipped, delivered]
OrderItem:
type: object
properties:
product_id:
type: string
quantity:
type: integer
CreateOrderRequest:
type: object
required: [customer_id, items]
properties:
customer_id:
type: string
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
Generation Script
# scripts/generate-all.sh
# !/bin/bash
set -euo pipefail
SPEC_VERSION="${1:-v2}"
SPEC_FILE="specs/$SPEC_VERSION/openapi.yaml"
OUTPUT_DIR="output/$SPEC_VERSION"
echo "=== Generating all SDKs for $SPEC_VERSION ==="
# Validate spec first
echo "Validating spec..."
openapi-generator validate -i "$SPEC_FILE"
if [ $? -ne 0 ]; then
echo "Spec validation failed!"
exit 1
fi
# Define generators and configs
declare -A GENERATORS
GENERATORS["python-fastapi"]="codegen/python-fastapi.yaml"
GENERATORS["typescript-fetch"]="codegen/typescript-fetch.yaml"
GENERATORS["swift5"]="codegen/swift5.yaml"
GENERATORS["kotlin"]="codegen/kotlin.yaml"
GENERATORS["html"]="codegen/html-docs.yaml"
# Generate each SDK
for gen in "${!GENERATORS[@]}"; do
config="${GENERATORS[$gen]}"
echo "Generating $gen..."
mkdir -p "$OUTPUT_DIR/$gen"
openapi-generator generate \
-i "$SPEC_FILE" \
-g "$gen" \
-o "$OUTPUT_DIR/$gen" \
-c "$config"
if [ $? -eq 0 ]; then
echo " $gen generated successfully"
else
echo " $gen generation failed!"
exit 1
fi
done
echo "=== Generation complete ==="
CI/CD Pipeline
# .github/workflows/codegen.yml
name: API Code Generation System
on:
push:
branches: [main]
paths:
- 'specs/**'
pull_request:
paths:
- 'specs/**'
jobs:
validate-and-generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Validate spec
run: |
SPEC=$(readlink -f specs/latest)
openapi-generator validate -i $SPEC/openapi.yaml
- name: Generate all SDKs
run: |
bash scripts/generate-all.sh $(basename $(readlink -f specs/latest))
- name: Test generated code
run: |
bash scripts/test-generated.sh
- name: Generate changelog
if: github.ref == 'refs/heads/main'
run: |
# Compare with previous version
PREV=$(ls -d specs/v* | sort -V | tail -2 | head -1)
CURR=$(readlink -f specs/latest)
python scripts/generate-changelog.py $PREV $CURR
- name: Publish SDKs
if: github.ref == 'refs/heads/main'
run: |
bash scripts/publish-sdks.sh
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
- name: Deploy docs
if: github.ref == 'refs/heads/main'
run: |
npx netlify-cli deploy --dir=output/latest/html --prod
Testing Generated Code
# scripts/test-generated.sh
# !/bin/bash
set -euo pipefail
SPEC_VERSION="${1:-v2}"
BASE_DIR="output/$SPEC_VERSION"
echo "=== Testing generated code ==="
# Test Python server
if [ -d "$BASE_DIR/python-fastapi" ]; then
echo "Testing Python FastAPI..."
cd "$BASE_DIR/python-fastapi"
pip install -r requirements.txt -q
python -m pytest tests/ -v
cd ../..
echo "Python tests passed"
fi
# Test TypeScript client
if [ -d "$BASE_DIR/typescript-fetch" ]; then
echo "Testing TypeScript Fetch..."
cd "$BASE_DIR/typescript-fetch"
npm install --silent
npm test
cd ../..
echo "TypeScript tests passed"
fi
# Test Swift client
if [ -d "$BASE_DIR/swift5" ]; then
echo "Building Swift..."
cd "$BASE_DIR/swift5"
swift build 2>/dev/null
cd ../..
echo "Swift build passed"
fi
echo "=== All tests passed ==="
Common Mistakes
1. Skipping Spec Review Before Generation
Always review spec changes before generating SDKs. A spec error propagates to all generated outputs. Use Pull Request reviews with automated spec validation.
2. Not Testing Generated Code in CI
Generating code is not enough. Compiled languages may fail to build. Test suites may fail because of broken generated stubs. Always compile and test generated code in CI.
3. Publishing Without Version Bump
Every spec change should update the spec version. Breaking changes require a major version bump. CI should enforce version increment and fail if the version has not changed.
4. Ignoring Deprecation Notices
When removing endpoints, add deprecation notices first. The OpenAPI spec supports the deprecated: true field on operations and schemas. Use it before removal.
5. Not Monitoring Generation Health
Track generation success rate, test pass rate, and time per generation. A spike in failures may indicate spec issues, generator bugs, or CI environment changes. Set up alerts for declines.
Practice Questions
- What is the recommended project structure for code generation?
- Why should you validate specs before generating code?
- How do you test generated SDKs across multiple languages?
- What should you include in a production codegen CI/CD pipeline?
Answers:
- Separate specs by version (specs/v1/, specs/v2/), generator configs in codegen/, scripts in scripts/, and output in output/. Use a latest symlink for the current stable version.
- Spec validation catches errors before wasting time on generation. An invalid spec produces broken code in every generated output. Validate once, generate many.
- Run language-specific tests for each generated SDK. Python uses pytest, TypeScript uses jest/karma, Swift uses swift test, Kotlin uses gradle test. A CI matrix job runs all test suites in parallel.
- A production pipeline includes: spec validation, multi-platform generation, generated code compilation/testing, breaking change detection, changelog generation, version bump enforcement, package publishing, and documentation deployment.
Challenge: Build the complete code generation system described in this project with your own API spec. Include CI/CD pipeline, multi-platform SDK generation, automated testing, changelog generation, version management, and package publishing to at least one registry (npm, PyPI, or Maven).
FAQ
Mini Project
Build the complete code generation system: create a spec with 5 endpoints and 3 models, set up generator configs for 3 languages (Python, TypeScript, Swift), create CI/CD pipeline with GitHub Actions, implement version management with changelogs, and publish the TypeScript client to a test npm registry.
What's Next
API Documentation — generate interactive API documentation from your spec.
CI/CD Codegen — deeper dive into CI/CD integration patterns.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro