Skip to content

OpenAPI Generator Project — Build a Complete Code Generation System

DodaTech Updated 2026-06-28 7 min read

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

  1. What is the recommended project structure for code generation?
  2. Why should you validate specs before generating code?
  3. How do you test generated SDKs across multiple languages?
  4. What should you include in a production codegen CI/CD pipeline?

Answers:

  1. 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.
  2. Spec validation catches errors before wasting time on generation. An invalid spec produces broken code in every generated output. Validate once, generate many.
  3. 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.
  4. 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

How long does it take to set up this system?

Initial setup takes 2-4 hours for a single API with 5 generators. Subsequent APIs take 30 minutes each since the infrastructure (CI/CD, templates, scripts) is reusable.

Can I use this system for private/internal APIs?

Yes. Private APIs use the same system but publish to internal registries (private npm, Artifactory, AWS CodeArtifact) instead of public registries.

How do I add a new generator to the system?

Create a new config file in codegen/ (codegen/newgen.yaml), add the generator to generate-all.sh, add test commands to test-generated.sh, and update the CI matrix if parallel generation is needed.

What if generated code has security vulnerabilities?

Run security scanning (npm audit, pip audit, Snyk, Dependabot) on generated output. Update generator version or apply post-generation patches to fix known vulnerabilities.

How do I handle rate limiting for package registry publishing?

Use registry-specific tokens and authentication. For npm, use automation tokens. For PyPI, use API tokens. Implement retry logic in publish scripts for transient failures.

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