feat: add OpenAPI doc generation script and improve envd spec#1952
feat: add OpenAPI doc generation script and improve envd spec#1952
Conversation
Add scripts/generate_openapi.py that merges multiple OpenAPI sources (proto-generated Connect RPC specs, envd REST spec, platform API spec) into a single e2b-openapi.yml for Mintlify documentation. Includes post-processing for empty responses, 502 sandbox-not-found errors, streaming endpoint placeholders, and orphaned schema cleanup. Update packages/envd/spec/envd.yaml with accurate response types, operationIds, improved parameter descriptions, example error responses, and a 406 NotAcceptable response for unsupported encodings.
- Fix temp file leak: use try/finally for Dockerfile cleanup on build failure - Pin protoc-gen-connect-openapi to v0.25.3 (was @latest) - Deduplicate global security entries during spec merge - Fix substring collision in orphan schema detection (Foo vs FooBar) - Keep /volumes endpoints in generated docs (remove from excluded prefixes)
The operationId additions in envd.yaml changed the generated Go type and method names. Update all references across envd, orchestrator, and integration tests: - GetFilesParams → DownloadFileParams - PostFilesParams → UploadFileParams - PostInitJSONBody → InitSandboxJSONBody - GetFiles → DownloadFile, PostFiles → UploadFile - GetEnvs → GetEnvVars, PostInit → InitSandbox - Path field is now non-pointer (required in spec) - PostFilesWithBodyWithResponse → UploadFileWithBodyWithResponse - GetFilesWithResponse → DownloadFileWithResponse
- Remove unnecessary string()/FilePath() conversions flagged by linter (FilePath is a type alias, not a distinct type) - Rename PostInitJSONRequestBody → InitSandboxJSONRequestBody in auth_test.go - Rename PostInitWithResponse → InitSandboxWithResponse in auth_test.go - Rename GetFiles → DownloadFile in signatures_test.go
Revert all Go code and generated code changes to avoid breaking the build. The envd.yaml spec now only contains documentation-safe changes (descriptions, examples, 406 response, mem MiB fields) that don't affect oapi-codegen output. OperationIds and the AccessTokenAuth → SandboxAccessTokenAuth rename are now applied in generate_openapi.py during post-processing, so they appear in the public docs without changing generated Go type names.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0533d1b93
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for sec_req in op["security"]: | ||
| if old_name in sec_req: | ||
| sec_req[new_name] = sec_req.pop(old_name) |
There was a problem hiding this comment.
Scope auth-scheme rename to sandbox paths only
rename_envd_auth_scheme rewrites every operation’s security entry from AccessTokenAuth to SandboxAccessTokenAuth, not just envd endpoints. Because merge_specs merges envd first and platform second, components.securitySchemes.AccessTokenAuth is the platform bearer-token definition from spec/openapi.yml, so sandbox operations are documented with the wrong auth type instead of envd’s header-based token from packages/envd/spec/envd.yaml; this will mislead SDK/doc consumers about how to authenticate against sandbox APIs.
Useful? React with 👍 / 👎.
| for path, methods in doc.get("paths", {}).items(): | ||
| merged["paths"][path] = methods |
There was a problem hiding this comment.
Preserve both APIs when paths collide
merge_specs overwrites path items on key collisions, so shared paths between envd and platform (e.g. /health, present in both packages/envd/spec/envd.yaml and spec/openapi.yml) lose one side entirely. Later, envd_paths still marks /health as sandbox, so the surviving operation can be assigned to the wrong server and response shape, producing an incorrect merged contract.
Useful? React with 👍 / 👎.
| add_operation_ids(merged) | ||
|
|
||
| # Remove internal/unwanted paths | ||
| filter_paths(merged) |
There was a problem hiding this comment.
schema_text = yaml.dump(schemas, default_flow_style=False) is computed but never used. The cross-reference check below (lines 741–746) re-serializes each individual schema instead. This variable can be removed.
| fill_empty_responses(merged) | ||
|
|
||
| # Clean up unreferenced schemas left over from filtered paths | ||
| remove_orphaned_schemas(merged) |
There was a problem hiding this comment.
The pattern f"schemas/{name}'" (trailing single quote) relies on PyYAML always quoting $ref values with single quotes. PyYAML does this because # requires quoting, but it's an undocumented implementation detail. If PyYAML ever uses double quotes (e.g. for a schema name with certain characters), the schema won't be detected as referenced and will be incorrectly removed from the output. A more robust approach would be to check for both quote styles, or to walk the spec tree structurally rather than matching serialized YAML strings.
| envd_paths.update(doc["paths"].keys()) | ||
|
|
||
| # --- Platform API --- | ||
| api_doc = load_yaml_file(API_SPEC) |
There was a problem hiding this comment.
Log message says "Removed N paths (volumes + admin)" but the excluded prefixes are /access-tokens and /api-keys, and the excluded exact paths include /init. The /volumes prefix is not excluded (it was intentionally removed in a previous commit). The message is misleading.
|
|
||
| Mintlify requires a content block on every response to render correctly. | ||
| """ | ||
| filled = 0 |
There was a problem hiding this comment.
If an operation's security list contains only Supabase entries, filtering them all out produces security: [], which in OpenAPI 3.x means the endpoint requires no authentication. Any API-key-only or user-only endpoints would be incorrectly documented as public in the generated spec. Consider logging a warning or asserting that the result is non-empty for non-excluded paths.
The platform API's /health (200 with auth) was overwriting envd's /health (204, no auth) because both specs define the same path and the platform API is merged second. Add protected_paths parameter to merge_specs() so envd paths are preserved.
1. MemoryMB minimum 128 → 0 (API returns 0 for some templates) 2. CPUCount minimum 1 → 0 (API returns 0 for some templates) 3. TemplateBuildStatus enum: add uploaded, failed, "" values 4. TemplateLegacy: add buildStatus and names properties 5. volumeMounts: remove from required in SandboxDetail and ListedSandbox 6. LogLevel enum: add "" (Go zero-value)
Summary
scripts/generate_openapi.pythat merges multiple OpenAPI sources (proto-generated Connect RPC specs, envd REST spec, platform API spec) into a singlee2b-openapi.ymlfor Mintlify documentationpackages/envd/spec/envd.yamlwith documentation-only improvements: better parameter/response descriptions, example error values for Mintlify rendering, 406 NotAcceptable response,mem_total_mib/mem_used_mibMetrics fields, VolumeMount descriptionsNo Go code or generated code is modified — operationIds and the auth scheme rename are applied at generation time only.
Test plan
python scripts/generate_openapi.pyand verify the generatede2b-openapi.yml/initis excluded and/volumesis included in generated output