Inngest REST API v2 的 OpenAPI 文档自动化生成工作流:从 Protobuf 注解到 OpenAPI v3 规格 Inngest REST API v2 的 OpenAPI 文档自动化生成工作流从 Protobuf 注解到 OpenAPI v3 规格【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngest在 Inngest 开源仓库中REST API v2 的 OpenAPI 文档并非手写维护而是由make docs驱动的两段式流水线自动产出先由 protoc-gen-openapiv2 从带 gRPC-gateway HTTP 注解的 protobuf 文件生成 OpenAPI 2.0Swagger规格再由自研转换工具tools/convert-openapi将其升级为带多服务器配置、统一错误模型和示例数据的 OpenAPI 3.0 规格。读完本文你将掌握该流水线的完整命令与参数、protobuf 侧的服务级/端点级注解写法、转换工具每一步的源码级行为以及如何为新端点补齐文档而不破坏既有生成约定。一、工作流总览整个流程分为四个环节见 docs/OPENAPI_WORKFLOW.mdOpenAPI v2 生成由protoc-gen-openapiv2解析proto/api/v2/service.proto中的 HTTP 注解gRPC-gateway 风格直接产出 Swagger 2.0 JSONOpenAPI v3 转换自定义转换器tools/convert-openapi基于 kin-openapi 库完成 v2 → v3 转换并施加多项增强高级特性自定义错误响应、Bearer 认证声明、多服务器生产 本地开发配置构建集成文档生成内嵌在 Makefile 中随build/dev自动执行。产出物目录结构为docs/ ├── openapi/ │ ├── v2/ # OpenAPI 2.0 specsprotoc 直接从 protobuf 生成 │ │ └── api/v2/service.swagger.json │ └── v3/ # OpenAPI 3.0 specs转换 增强后的产物 │ └── api/v2/service.swagger.json注意这两个 v2/v3 下的api/v2产物均为生成文件不纳入 git 跟踪通过.gitignore排除仓库中只跟踪 protobuf 源文件和转换工具本身。当前仓库里可见的docs/openapi/v3/api/v1/spec.yaml是旧版 v1 API 的跟踪规格与 v2 自动产物不在同一体系内。二、构建命令主命令make docsmake docs该目标同时生成 OpenAPI v2 与增强后的 v3 文档。查看 Makefile 第 80–93 行可以看到其实际分四步执行校验示例文件结构先运行cd tools/convert-openapi go test -run TestExamplesJSONStructure -v确保docs/api_v2_examples.json的三层结构path → method → statusCode → example合法生成 OpenAPI v2由于 buf 配置问题Makefile 中注释原话为 Generate OpenAPI v2 directly using protoc due to buf configuration issues这里绕过 buf直接调用 protoccd proto protoc --proto_path. --proto_paththird_party \ --openapiv2_out../docs/openapi/v2 \ --openapiv2_optallow_delete_bodytrue \ --openapiv2_optjson_names_for_fieldstrue \ api/v2/service.proto参数说明--proto_path. --proto_paththird_party分别指向proto/和proto/third_party/后者提供google/api/annotations.proto、protoc-gen-openapiv2/options/annotations.proto等第三方 proto 依赖--openapiv2_out../docs/openapi/v2输出目录按 proto 包路径落盘为api/v2/service.swagger.jsonallow_delete_bodytrue允许带请求体的 DELETE 方法OpenAPI 规范上 DELETE 通常无 bodyjson_names_for_fieldstrue字段名按 JSON 命名小驼峰生成 schema 属性与服务端实际序列化字段名保持一致。转换到 v3go run ./tools/convert-openapi docs/openapi/v2 docs/openapi/v3整个过程还会回写示例文件见第五节。自动触发文档生成还随以下构建自动执行Makefile 依赖关系make build—— 生产构建build: docsmake dev—— 开发构建dev: docs。因此每次构建都会刷新文档保证与 protobuf 定义严格同步。清理生成文件make clean对应rm -rf docs/openapi/v2/*与rm -rf docs/openapi/v3/*Makefile 第 114–118 行。三、protobuf 侧的注解配置文档生成完全依赖proto/api/v2/service.proto中的三层注解这是整条流水线的“单一事实来源”。1. 服务级配置openapiv2_swaggerproto/api/v2/service.proto 顶部声明了openapiv2_swagger选项等价于文档中的示例option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) { info: { title: Inngest REST API v2 version: 2.0.0 description: The v2 API delivers a significantly improved developer experience with consistent design patterns and enhanced functionality. } host: api.inngest.com base_path: /v2 schemes: HTTPS security_definitions: { security: { key: BearerAuth value: { type: TYPE_API_KEY in: IN_HEADER name: Authorization description: Bearer token authentication. Format: Bearer {key} } } } tags: { name: Account description: Manage your account } tags: { name: Environments description: Create and manage environments } // ... Keys / Webhooks / Apps / Events / Functions / Runs / Insights / Sandboxes / Sessions / Partner API };各部分职责info产出文档的元数据标题 Inngest REST API v2、版本 2.0.0hostbase_pathschemes在 v2 中表现为host/basePath字段后续由转换工具映射为 v3 的servers数组security_definitions声明全局唯一的BearerAuthAPI Key 认证位于Authorization头描述中注明Bearer {key}格式tags为所有端点分组Account、Environments、Keys、Webhooks、Runs 等 12 个业务标签使 Swagger UI 中端点可分类浏览。2. 端点级配置google.api.http openapiv2_operation每个 RPC 需要两类 optiongoogle.api.http定义路由openapiv2_operation定义文档细节。以 CreatePartnerAccount 为例rpc CreatePartnerAccount(CreateAccountRequest) returns (CreateAccountResponse) { option (google.api.http) { post: /partner/accounts, body : * }; option (authz) { require_authz: true }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) { summary: Create partner account description: Creates a sub-account (if you have partner access) tags: Partner API security: { security_requirement: { key: BearerAuth value: {} } } responses: { key: 201 value: { description: Account successfully created schema: { json_schema: { ref: #/definitions/v2CreateAccountResponse } } } } // 以及 400 / 401 / 403 / 409 / 500 等schema 均引用 #/definitions/v2ErrorResponse }; };要点body: *表示整个请求消息映射为 JSON 请求体GET 类端点则无需该字段认证分层声明security_definitions放在服务级“定义”认证方式security_requirement放在 operation 级“启用”认证——这正是文档 Troubleshooting 一节强调的“Authentication Not Showing”检查顺序显式状态码每个错误码都显式声明201/400/401/403/404/409/422/500 等并引用统一的v2ErrorResponse定义不依赖default响应。这也是后文转换工具“只保留显式声明的状态码”策略的前提自定义 header 参数如FetchAccountEventKeys端点用openapiv2_operation.parameters.headers声明了X-Inngest-Env头环境过滤这类参数不会从请求消息中自动推导必须在 operation 里手写authz扩展来自 proto/api/v2/options.proto 定义的MethodOptions.authz扩展require_authz字段它不影响 OpenAPI 生成而是供服务端路由装配鉴权中间件是同一份 proto 既服务文档又服务实现的典型设计。当前 proto/api/v2/service.proto 共定义了 51 个 RPC含 1 个仅用于 schema 的内部方法覆盖 Health、Partner Accounts、Environments、Keys、Webhooks、Runs 等分组——文档中“Current API Endpoints”一节列举的/v2/health与POST /v2/partner/accounts只是最早的基线实际端点面已按 proto 为准扩展。3._SchemaOnly强制生成错误 schema 的技巧protoc-gen-openapiv2 只会为“被某个 RPC 引用”的 message 输出 definition。为了让ErrorResponse即使没有真实端点直接返回它也能出现在#/definitions中service.proto 增加了一个内部方法service.proto 第 91–98 行// Internal method to ensure ErrorResponse schema generation (not exposed via HTTP). // The HTTP annotation is required for protoc-gen-openapiv2 to include ErrorResponse // in the swagger definitions. This path is stripped by the convert-openapi tool. rpc _SchemaOnly(HealthRequest) returns (ErrorResponse) { option (google.api.http) { get: /_internal/schema-only }; }配套的错误消息定义service.proto 第 2166–2173 行message Error { string code 1; string message 2; } message ErrorResponse { repeated Error errors 1; // Always an array }/_internal/前缀路径会在转换阶段被剥离见下节因此公共文档里不会出现这条假端点但 schema 引用#/definitions/v2ErrorResponse全部有效。四、自定义转换工具 tools/convert-openapigo run ./tools/convert-openapi docs/openapi/v2 docs/openapi/v3是流水线的第二阶段。主逻辑在 tools/convert-openapi/main.go它遍历输入目录下所有.json文件非合法 v2 文件会被打印警告后跳过逐个执行以下处理链1. 移除 default 响应与冗余 200removeDefaultResponsesmain.go 第 119–154 行对所有 7 种 HTTP 方法执行删除default响应protoc-gen-openapiv2 会自动补一个泛化的 default若该操作已存在自定义 2xx 成功码201/204 等由hasCustomStatusCodes判断则同时删除自动生成的200避免“一个端点两个成功响应”。最终产物因此只包含显式声明的状态码与 Inngest API 规范中“无 default response”的约束一致。2. 剥离内部路径与内部操作removeInternalPaths删除所有/_internal/前缀路径即_SchemaOnly的落点removeInternalOperations删除带Internal标签的操作如Health端点的tags: Internal若某 path 的所有方法都被剥离则整个 path 一并移除。3. 多服务器配置basePath → servershandleBasePathmain.go 第 240–253 行无视 v2 的 host/basePath直接把 v3servers写死为两个环境servers : []*openapi3.Server{ {URL: https://api.inngest.com/v2, Description: Production server}, {URL: http://localhost:8288/api/v2, Description: Development server}, }即文档所述“Production Development 双服务器”。本地开发地址8288端口与 Inngest dev server 的 REST API 端口约定一致使生成的文档可直接被本地联调的 Swagger UI 使用。4. 公共枚举名缩短shortenPublicEnumNames解决 protobuf 枚举在 JSON 中的命名问题。转换链会先从components.schemas推导枚举前缀如 schemaFunctionRunStatus对应前缀FUNCTION_RUN_STATUS_再遍历所有 path 参数、请求体、响应体中的 enum/default 值把FUNCTION_RUN_STATUS_QUEUED这类 wire 名截短为QUEUED与 v2 HTTP gateway 对外暴露的枚举值保持一致见 main.go 第 278–453 行 的derivePublicEnumPrefixes/shortenPublicEnumString。5. 参数约束注入addParameterConstraints为特定参数补上 proto 中无法表达的校验约束例如给GET /partner/accounts的limit查询参数写入minimum: 1, maximum: 1000main.go 第 256–276 行。6. 响应示例注入applyExamplesapplyExamples读取外部示例文件 docs/api_v2_examples.json结构为path - method - statusCode - example三层映射将每个状态码的示例以Examples[default]形式挂到对应响应的每种 content-type 上。该机制还有两个值得注意的行为自动补骨架generateMissingExamples会扫描 v3 文档为尚不存在的 path/method/statusCode 组合写入占位条目含// TODO: Add example data for ...并把排序后的完整结构回写api_v2_examples.json——即示例文件是“生成 人工补数据”的半自动产物跳过 TODO 占位isTodoExample会把纯 TODO/注释字段的条目排除出最终文档避免占位符泄漏到公开规格中。转换完成后最终 JSON 以 2 空格缩进写回docs/openapi/v3/下与输入相同的相对路径。五、统一错误模型v2 API 的响应错误遵循统一的数组格式文档给出的规范示例{ errors: [ { code: function_name_required, message: Function name is required } ] }其 schema 溯源链是Error/ErrorResponse两个 messageservice.proto 第 2166–2173 行→ 由_SchemaOnly方法确保进入#/definitions→ 所有端点的错误状态码 schema 引用#/definitions/v2ErrorResponse。errors字段为repeated即无论单个还是多个错误响应体始终是数组客户端解析逻辑无需分支处理。六、外部示例文件的结构校验make docs的第一步会运行结构校验测试 tools/convert-openapi/main_test.goTestExamplesJSONStructure逐条断言三层键格式——path 必须以/开头、method 属于 7 种合法动词、status code 为三位且首位 1–5、example 必须是非空对象或非空字符串TestExamplesMatchOpenAPISpec校验基线端点/health、/account、/partner/accounts、/envs存在且GET /health具备 200/401/500 三个状态码示例。这两项测试把示例数据质量纳入了make docs的前置门禁坏示例会在生成阶段即被拦截。七、依赖清单依赖用途protoc-gen-openapiv2grpc-gateway从 protobuf 生成 OpenAPI 2.0github.com/getkin/kin-openapi/openapi2解析 v2 规格当前 go.mod 锁定 v0.132.0github.com/getkin/kin-openapi/openapi2convv2 → v3 转换核心github.com/getkin/kin-openapi/openapi3v3 数据模型与写出另外proto/api/v2/buf.gen.yaml 中其实也声明了openapiv2插件输出至docs/openapi/v2选项allow_delete_bodytrue、json_names_for_fieldstrue说明 buf 路线曾被尝试但 Makefile 明确注释了因 buf 配置问题改用 protoc 直调二者选项保持一致阅读仓库时以make docs的实际命令为准。八、新增端点的文档化步骤按 docs/OPENAPI_WORKFLOW.md 的 “Adding New Endpoints” 流程并结合仓库现状定义带 HTTP 注解的 RPCrpc MyMethod(MyRequest) returns (MyResponse) { option (google.api.http) { post: /my-endpoint }; }POST/PUT/PATCH 等带体请求记得加body: *如需鉴权仿照现有端点补security_requirement。补充显式响应推荐为成功码与常见错误码逐一声明openapiv2_operation.responses错误码统一引用#/definitions/v2ErrorResponse。不要依赖 default 响应——它会在转换阶段被删除等于丢失文档。重新生成make docs。若新端点引入了需要示例的状态码applyExamples会向docs/api_v2_examples.json自动追加 TODO 条目随后人工填入示例数据下次make docs的结构校验测试会强制要求数据非空且格式正确。九、Git 集成策略生成的docs/openapi/v2、docs/openapi/v3下产物被.gitignore排除只有 protobuf 源文件proto/api/v2/与转换工具tools/convert-openapi/受版本跟踪文档随每次构建重新生成从机制上消除了“文档与 proto 漂移”。十、故障排查文档给出的两类常见问题的排查路径均可对照源码验证Missing Schemas错误 schema 缺失确认Error/ErrorResponse消息定义存在于 proto当前位于 service.proto确认存在内部_SchemaOnly方法引用ErrorResponse且路径带/_internal/前缀否则它本身也会漏进公开文档确认 schema 引用使用#/definitions/v2ErrorResponse格式——前缀v2来自 proto 包名api.v2的消息命名规则写错前缀会导致悬空引用。Authentication Not Showing认证不显示确认security_definitions在服务级openapiv2_swagger确认security_requirement在操作级openapiv2_operation仅定义不引用时 Swagger UI 不会显示锁形图标确认 Bearer token 格式写在 security definition 的description中当前 proto 为Bearer token authentication. Format: Bearer {key}文档渲染器依赖这段描述向使用者展示令牌格式。小结Inngest 的 OpenAPI 文档工作流本质上是“protobuf 注解为单一事实来源 两段式生成 转换期修正”的管线protoc 负责从注解机械产出 v2 规格tools/convert-openapi负责剥离内部端点、统一双服务器、对齐枚举命名并注入示例数据而make docs用示例结构测试做前置门禁、make build/make dev做自动触发.gitignore保证产物不入库。对维护者而言新增一个端点的文档成本被压缩到“写注解 补示例 JSON”两步其余一致性由流水线兜底。【免费下载链接】inngestThe leading workflow orchestration platform. Run stateful step functions and AI workflows on serverless, servers, or the edge.项目地址: https://gitcode.com/GitHub_Trending/in/inngest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考