openapi-codegen-orchestratorSkill openapi-codegen-orchestrator

openapi-codegen-orchestrator是一个专门用于协调多语言SDK生成的OpenAPI规范的专业技能,能够实现跨不同编程生态系统的一致、高质量的SDK生产。

DevOps 0 次安装 0 次浏览 更新于 2/26/2026

您是 openapi-codegen-orchestrator - 一个专门用于协调多语言SDK生成的OpenAPI规范的专业技能,能够实现跨不同编程生态系统的一致、高质量的SDK生产。

概述

这个技能使AI驱动的SDK代码生成成为可能,包括:

  • 为多个目标语言配置OpenAPI生成器
  • 应用自定义模板和后处理转换
  • 处理边缘情况和OpenAPI扩展
  • 验证生成的代码编译
  • 管理生成器版本和兼容性
  • 根据语言习惯定制代码风格
  • 协调并行多语言构建

先决条件

  • Node.js 18+ 或 Java 11+
  • OpenAPI生成器CLI(npm或jar)
  • OpenAPI 3.x规范文件
  • 目标语言工具链(npm,pip,maven等)
  • Docker(可选,用于容器化生成)

能力

1. OpenAPI生成器配置

为多种语言配置OpenAPI生成器:

# openapi-generator-config.yaml
generatorConfigs:
  typescript-axios:
    generatorName: typescript-axios
    output: ./sdks/typescript
    additionalProperties:
      npmName: "@company/api-client"
      npmVersion: "1.0.0"
      supportsES6: true
      withInterfaces: true
      withSeparateModelsAndApi: true
      modelPropertyNaming: camelCase
      enumPropertyNaming: UPPERCASE
    templateDir: ./templates/typescript
    globalProperties:
      skipFormModel: false

  python:
    generatorName: python
    output: ./sdks/python
    additionalProperties:
      packageName: company_api_client
      packageVersion: "1.0.0"
      projectName: company-api-client
      generateSourceCodeOnly: false
    templateDir: ./templates/python

  java:
    generatorName: java
    output: ./sdks/java
    additionalProperties:
      groupId: com.company.api
      artifactId: api-client
      artifactVersion: "1.0.0"
      library: native
      useJakartaEe: true
      dateLibrary: java8
      serializationLibrary: jackson
    templateDir: ./templates/java

  go:
    generatorName: go
    output: ./sdks/go
    additionalProperties:
      packageName: apiclient
      packageVersion: "1.0.0"
      isGoSubmodule: true
      generateInterfaces: true

2. 多语言生成脚本

跨语言协调SDK生成:

// generate-sdks.js
import { execSync } from 'child_process';
import { readFileSync, writeFileSync } from 'fs';
import yaml from 'yaml';

const config = yaml.parse(readFileSync('openapi-generator-config.yaml', 'utf8'));
const specPath = process.env.OPENAPI_SPEC || './openapi.yaml';

async function generateSDK(language, langConfig) {
  console.log(`生成 ${language} SDK...`);

  const args = [
    'generate',
    '-i', specPath,
    '-g', langConfig.generatorName,
    '-o', langConfig.output,
    '--skip-validate-spec'
  ];

  // 添加额外属性
  if (langConfig.additionalProperties) {
    for (const [key, value] of Object.entries(langConfig.additionalProperties)) {
      args.push('--additional-properties', `${key}=${value}`);
    }
  }

  // 添加模板目录
  if (langConfig.templateDir) {
    args.push('-t', langConfig.templateDir);
  }

  // 添加全局属性
  if (langConfig.globalProperties) {
    for (const [key, value] of Object.entries(langConfig.globalProperties)) {
      args.push('--global-property', `${key}=${value}`);
    }
  }

  try {
    execSync(`npx @openapitools/openapi-generator-cli ${args.join(' ')}`, {
      stdio: 'inherit'
    });
    console.log(`成功生成 ${language} SDK`);
    return { language, status: 'success' };
  } catch (error) {
    console.error(`生成 ${language} SDK失败:`, error.message);
    return { language, status: 'failed', error: error.message };
  }
}

async function generateAllSDKs() {
  const results = [];

  for (const [language, langConfig] of Object.entries(config.generatorConfigs)) {
    const result = await generateSDK(language, langConfig);
    results.push(result);
  }

  console.log('
=== 生成摘要 ===');
  results.forEach(r => {
    console.log(`${r.language}: ${r.status}`);
  });

  return results;
}

generateAllSDKs();

3. 自定义模板管理

创建和管理自定义Mustache模板:

{{! templates/typescript/apiInner.mustache }}
{{#operations}}
{{#operation}}
/**
 * {{summary}}
 * {{notes}}
 {{#allParams}}
 * @param {{paramName}} {{description}}
 {{/allParams}}
 * @throws {ApiError} if the request fails
 */
public async {{operationId}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}{{^-last}}, {{/-last}}{{/allParams}}): Promise<{{{returnType}}}{{^returnType}}void{{/returnType}}> {
  const response = await this.{{operationId}}Raw({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}});
  {{#returnType}}
  return await response.value();
  {{/returnType}}
}
{{/operation}}
{{/operations}}

4. 生成后处理

生成后应用转换:

// post-process.js
import { glob } from 'glob';
import { readFileSync, writeFileSync } from 'fs';
import path from 'path';

const postProcessors = {
  typescript: async (outputDir) => {
    // 为生成的代码添加ESLint禁用注释
    const files = await glob(`${outputDir}/**/*.ts`);

    for (const file of files) {
      let content = readFileSync(file, 'utf8');

      // 添加头部注释
      if (!content.startsWith('/* eslint-disable */')) {
        content = `/* eslint-disable */
/**
 * 由OpenAPI生成器自动生成
 * 不要手动编辑
 */

${content}`;
      }

      // 修复常见问题
      content = content
        .replace(/any\[\]/g, 'unknown[]')  // 将any[]替换为unknown[]
        .replace(/: any;/g, ': unknown;'); // 将any替换为unknown

      writeFileSync(file, content);
    }

    // 生成桶导出
    const models = await glob(`${outputDir}/models/*.ts`);
    const exports = models
      .map(f => path.basename(f, '.ts'))
      .filter(n => n !== 'index')
      .map(n => `export * from './${n}';`)
      .join('
');

    writeFileSync(`${outputDir}/models/index.ts`, exports + '
');
  },

  python: async (outputDir) => {
    // 修复Python导入和类型提示
    const files = await glob(`${outputDir}/**/*.py`);

    for (const file of files) {
      let content = readFileSync(file, 'utf8');

      // 添加未来注释以兼容Python 3.8
      if (!content.includes('from __future__ import annotations')) {
        content = `from __future__ import annotations

${content}`;
      }

      writeFileSync(file, content);
    }
  },

  java: async (outputDir) => {
    // 添加Lombok注释
    const files = await glob(`${outputDir}/**/model/*.java`);

    for (const file of files) {
      let content = readFileSync(file, 'utf8');

      // 如果没有Lombok导入,则添加
      if (!content.includes('lombok')) {
        content = content.replace(
          'package ',
          'import lombok.Builder;
import lombok.Data;

package '
        );
      }

      writeFileSync(file, content);
    }
  }
};

async function runPostProcessing(language, outputDir) {
  if (postProcessors[language]) {
    console.log(`为 ${language} 运行后处理...`);
    await postProcessors[language](outputDir);
    console.log(`完成 ${language} 的后处理`);
  }
}

5. 生成代码验证

验证生成的SDKs编译并通过linting:

// validate-sdks.js
import { execSync } from 'child_process';

const validators = {
  'typescript-axios': {
    install: 'npm install',
    build: 'npm run build',
    lint: 'npm run lint',
    test: 'npm test'
  },
  python: {
    install: 'pip install -e .[dev]',
    build: 'python -m build',
    lint: 'ruff check .',
    test: 'pytest'
  },
  java: {
    install: 'mvn install -DskipTests',
    build: 'mvn compile',
    lint: 'mvn checkstyle:check',
    test: 'mvn test'
  },
  go: {
    install: 'go mod download',
    build: 'go build ./...',
    lint: 'golangci-lint run',
    test: 'go test ./...'
  }
};

async function validateSDK(language, outputDir) {
  const steps = validators[language];
  if (!steps) {
    console.log(`没有 ${language} 的验证器`);
    return { language, status: 'skipped' };
  }

  const results = { language, steps: {} };

  for (const [step, command] of Object.entries(steps)) {
    try {
      console.log(`[${language}] 运行 ${step}...`);
      execSync(command, { cwd: outputDir, stdio: 'inherit' });
      results.steps[step] = 'passed';
    } catch (error) {
      console.error(`[${language}] ${step} 失败:`, error.message);
      results.steps[step] = 'failed';
      results.status = 'failed';
      break;
    }
  }

  results.status = results.status || 'passed';
  return results;
}

6. OpenAPI扩展处理

处理自定义OpenAPI扩展:

// extension-handler.js
const extensionHandlers = {
  'x-sdk-operation-group': (operation, value) => {
    // 将操作分组到命名空间客户端
    operation.operationGroup = value;
  },

  'x-sdk-ignore': (operation, value) => {
    // 跳过此操作的生成
    operation.vendorExtensions['x-skip-generation'] = value;
  },

  'x-sdk-paginated': (operation, value) => {
    // 生成分页助手
    operation.vendorExtensions['x-pagination'] = {
      enabled: true,
      pageParam: value.pageParam || 'page',
      limitParam: value.limitParam || 'limit',
      resultPath: value.resultPath || 'data'
    };
  },

  'x-sdk-deprecated-date': (operation, value) => {
    // 添加带日落日期的弃用
    operation.vendorExtensions['x-deprecation'] = {
      date: value,
      message: `此操作将在 ${value} 后被移除`
    };
  }
};

function processExtensions(spec) {
  // 处理路径级扩展
  for (const [path, pathItem] of Object.entries(spec.paths)) {
    for (const [method, operation] of Object.entries(pathItem)) {
      if (typeof operation !== 'object') continue;

      for (const [ext, value] of Object.entries(operation)) {
        if (ext.startsWith('x-sdk-') && extensionHandlers[ext]) {
          extensionHandlers[ext](operation, value);
        }
      }
    }
  }

  return spec;
}

7. CI/CD集成

GitHub Actions工作流用于SDK生成:

name: Generate SDKs

on:
  push:
    paths:
      - 'openapi.yaml'
      - 'templates/**'
  workflow_dispatch:
    inputs:
      languages:
        description: '要生成的语言(逗号分隔或“all”)'
        default: 'all'

jobs:
  generate:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        language: [typescript, python, java, go]

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup language toolchain
        uses: ./.github/actions/setup-${{ matrix.language }}

      - name: Install OpenAPI Generator
        run: npm install -g @openapitools/openapi-generator-cli

      - name: Generate SDK
        run: |
          openapi-generator-cli generate \
            -i openapi.yaml \
            -g ${{ matrix.language }} \
            -o ./sdks/${{ matrix.language }} \
            -c ./config/${{ matrix.language }}.yaml

      - name: Run post-processing
        run: node scripts/post-process.js ${{ matrix.language }}

      - name: Validate SDK
        run: node scripts/validate-sdk.js ${{ matrix.language }}

      - name: Upload SDK artifact
        uses: actions/upload-artifact@v4
        with:
          name: sdk-${{ matrix.language }}
          path: ./sdks/${{ matrix.language }}

  publish:
    needs: generate
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Download all SDKs
        uses: actions/download-artifact@v4

      - name: Publish SDKs
        run: |
          for sdk in sdk-*; do
            echo "Publishing $sdk..."
            # 语言特定的发布命令
          done

8. 配置模式

验证生成器配置:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "generatorConfigs": {
      "type": "object",
      "additionalProperties": {
        "type": "object",
        "required": ["generatorName", "output"],
        "properties": {
          "generatorName": {
            "type": "string",
            "enum": ["typescript-axios", "typescript-fetch", "python", "java", "go", "csharp", "rust"]
          },
          "output": { "type": "string" },
          "additionalProperties": { "type": "object" },
          "templateDir": { "type": "string" },
          "globalProperties": { "type": "object" }
        }
      }
    }
  }
}