Migrate to oas3 (OpenAPI 3.1 support) + header param Option fix#1
Open
chris13524 wants to merge 11 commits intomainfrom
Open
Migrate to oas3 (OpenAPI 3.1 support) + header param Option fix#1chris13524 wants to merge 11 commits intomainfrom
chris13524 wants to merge 11 commits intomainfrom
Conversation
…nalProperties Adds sample_openapi/coverage-gaps.json, a new test_output::test_coverage_gaps golden test, and a test_specific::test_coverage_gaps_compiles include!() test that ensures the generated output actually compiles. The fixture exercises schema features that were thinly covered elsewhere: - anyOf (StringOrInt) - oneOf with discriminator (Animal / Dog / Cat) - additionalProperties with a typed schema (StringMap) - additionalProperties: true / free-form (FreeformMap) Establishing this baseline so that regressions in the upcoming openapiv3 -> oas3 migration surface as concrete test failures rather than silent drift. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- openapi version bumped from 3.0.x to 3.1.0
- nullable: true combined with a scalar type rewritten as type: ["X", "null"]
- nullable: true alongside composed schemas (allOf/oneOf) wrapped in
anyOf: [<original>, {type: "null"}]
- exclusiveMinimum/exclusiveMaximum boolean form already absent
This commit on its own leaves the build broken because the Rust code still
targets openapiv3; the crate swap follows immediately.
Crate-level dep changes only; code still references openapiv3 and will not build until the subsequent migration commits. openapiv3 remains as a transitive dep of dropshot (dev-only).
- ReferenceOrExt::item now delegates to ObjectOrReference::resolve and takes &Spec (oas3 resolves from the top-level spec, not just Components) - Returns owned T (oas3 clones on resolve) instead of &T - ComponentLookup trait is obsolete; oas3 ships FromRef for the concrete component types - parameter_map now collects into BTreeMap<String, Parameter>; oas3's Parameter is a flat struct so param.name is a direct field
Key transforms: - openapiv3::Parameter enum-with-per-variant-style-types → oas3 flat Parameter struct. Location/style now read via the `location` and `style` fields; missing `style` falls back to the per-location default (Path/Header: Simple, Query/Cookie: Form) - parameter.schema is now a direct Option field; content lives alongside it. Unsupported `content`-only parameters produce an UnexpectedFormat error - operation.responses is a single Option<BTreeMap<String, _>> keyed by the raw status string; a new parse_response_status helper maps "default", "2XX"-style ranges, and numeric codes to OperationResponseStatus - Response.description is now Option<String>; description handling adjusted - BTreeMap has no .first(); swapped to iter().next()/is_empty() - oas3 strips the "x-" prefix from extension keys, so x-dropshot-pagination and x-dropshot-websocket are now looked up without the prefix - ParameterDataExt is obsolete (Parameter.schema is a direct field) and has been replaced by a small is_simple_string_schema helper that validates octet-stream and plain-text body schemas against a flat ObjectSchema to_schema.rs still references openapiv3 types, so progenitor-impl does not build after this commit; the remaining schema rewrite lands in the next commit.
oas3 0.21 represents schemas as a flat ObjectSchema rather than the tagged SchemaKind enum. This rewrites the schemars conversion around that shape: - Split `Option<SchemaTypeSet>` into `(non_null_type, nullable)` so the 3.1 `type: ["X", "null"]` array is normalized to a 3.0-style `nullable` flag for downstream schemars consumption. - Mirror the old per-variant branches via primary-type matching, plus catch-all composition (one_of / all_of / any_of) branches. - Convert BooleanSchema(bool) to schemars::schema::Schema::Bool. - Walk exclusiveMinimum / exclusiveMaximum as serde_json::Number. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace every remaining `openapiv3::OpenAPI` reference with `oas3::Spec`, and rewrite the path/operation walk around oas3's flat `PathItem` shape: - `progenitor-impl/src/lib.rs`: generate_tokens + validate_openapi + tag-separate builder now take `&Spec`; path walk uses `PathItem::methods()` (returning `http::Method`), converted to the lowercase string that HttpMethod::from_str expects. The version validator accepts both 3.0.x and 3.1.x: progenitor targets 3.1, but we keep 3.0 support because Dropshot emits 3.0.3 in `test_specific`. `nullable: true` from 3.0 is silently dropped by oas3. - `progenitor-impl/src/cli.rs` and `src/httpmock.rs`: identical path walk + signature changes. - `progenitor-macro/src/lib.rs` and `cargo-progenitor/src/main.rs`: parse into `Spec` instead of `OpenAPI`. - `progenitor-impl/tests/test_output.rs` and `tests/test_specific.rs`: parse into `Spec`. The inner generation changes (Parameter / ObjectSchema shape) landed in earlier commits; this commit wires up the call sites so the workspace compiles end-to-end. Goldens are regenerated in the next commit. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Goldens under progenitor-impl/tests/output/src/ regenerated via `EXPECTORATE=overwrite cargo test -p progenitor-impl`. Diffs fall into a few categories: - oas3's Components use BTreeMap rather than IndexMap, so components reorder alphabetically. Most churn is reordered impl blocks / type definitions in generated code. - Operation reordering within a path: oas3's `PathItem::methods()` returns operations in a fixed GET/PUT/POST/DELETE/OPTIONS/HEAD/PATCH /TRACE order rather than spec-file order. This shifts method order inside `impl Client` blocks. - 3.1 schema shapes: `type: ["string", "null"]` instead of `type: string` + `nullable: true` preserves identical Option<T> generation where fixtures were converted; a few dropshot-produced specs (test_stream_pagination, test_default_params) still carry 3.0 `nullable: true` which oas3 drops, so those Option wrappers disappear. Also drops the scratch MIGRATION_NOTES.md and the conversion script used to migrate fixtures. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Header parameters with nullable schemas (`type: ["string", "null"]`) were generating field types like `Result<Option<Option<String>>, String>` because the `required = false` wrapping in builder generation was being applied on top of an already-optional type. Query parameters had logic to detect this and unwrap the inner type; ports the same fix to the Header branch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Downstream consumers (e.g., yttrium) are still on reqwest 0.12; pin the workspace to match to avoid pulling two reqwest versions into the same dependency graph. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5 tasks
# Conflicts: # Cargo.lock # Cargo.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
openapiv3tooas3 0.21.0to support OpenAPI 3.1 specs end-to-end (entry points, validator,to_schema.rs,method.rs,util.rs).sample_openapifixtures from 3.0 to 3.1 and adds a coverage-gaps fixture (anyOf, oneOf+discriminator, additionalProperties).type: ["string", "null"]) were generating field types likeResult<Option<Option<String>>, String>. The Query parameter branch had logic to unwrap an already-optional inner type before the non-required wrapping in builder generation; this PR ports the same logic to the Header branch.reqwestto0.12for compatibility with downstream consumers (e.g. yttrium) that are still on 0.12; this avoids two reqwest versions appearing in the same dep graph. Drop this commit if the fork prefers to stay on 0.13.Test plan
cargo check -p progenitor -p progenitor-client -p progenitor-impl -p progenitor-macro -p cargo-progenitor(verified locally)cargo testacross the workspacecargo-progenitoragainst an OpenAPI 3.1 spec with nullable header params and confirm the generated builder field isResult<Option<T>, String>(single Option)example-build,example-macro,example-out-dirstill build (these may need their own reqwest version bumped/pinned to match)🤖 Generated with Claude Code