Feat/diff command - #2940
Draft
vadyvas wants to merge 19 commits into
Draft
Conversation
🦋 Changeset detectedLatest commit: 7d66075 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| }; | ||
|
|
||
| function escapeCell(value: string): string { | ||
| return value.replace(/\|/g, '\\|').replace(/\n/g, ' '); |
Contributor
Author
|
@RomanHotsiy flowchart LR
A["base + revision"] --> C["collect ×2<br/>(walkDocument → flat maps)"] --> D["compare<br/>(set diff)"] --> E["classify<br/>(polarity + rules)"] --> F["report<br/>(stylish/json/md/html)"]
C -. "$ref edges" .-> U[UsageIndex] -. polarity .-> E
Inputs for now are files or urls - resolved through the existing
redocly diff base.yaml revision.yaml
redocly diff base.yaml revision.yaml --fail-on=breaking --format=json |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compare two API descriptions and report added, removed, and changed parts. Structural diff works for every supported spec type via the existing openapi-core type trees; breaking-change classification (breaking / warning / non-breaking) applies to OpenAPI 3.x. The diff engine lives entirely in the CLI package and consumes only the public @redocly/openapi-core API (walkDocument, type trees, bundle) — packages/core is untouched. Pipeline: collect each side into a flat stable-pointer map, two-pass compare into a change list, then classify with a polarity-aware lint-style rule registry (worst verdict wins). Supports stylish, json, markdown, and html output and a --fail-on CI gate. Marked [experimental]; 14 starter rules documented. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… verdicts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ons, and path-param matching Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e case Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adapt to the new collectSpecData signature (it now takes the document, not its parsed value) and regenerate the e2e snapshots, which still held the original flat output: they predate the two-level compat model, the per-operation grouping, the location and verdict lines, and the fail-on summary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The lint formatters in core already cover the formats CI tools expect, so map breaking changes onto lint problems and hand them to formatProblems instead of writing six more serializers. This adds codeframe, checkstyle, codeclimate, summary, github-actions, and junit to the diff command; with github-actions, every breaking change becomes an inline pull request annotation. A lint problem always carries a severity, so these formats describe breaking changes only — the full change list stays in the json format. They print to stdout, and --output now reports that clearly instead of writing nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One test per rule, each with its own minimal base/revision pair, asserting the rule id the command should attribute the change to. Thirteen of them fail today and describe the intended contract: request body required and removed, string and numeric constraint tightening, additionalProperties, oneOf narrowing, format, the three security cases, response headers, and parameter serialization. Two of the failures are false positives rather than gaps: widening a request type is reported as breaking, and 3.0 `nullable: true` compared against 3.1 `type: [.., 'null']` reports a change although both describe the same schema. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Polarity was inferred from the pointer text, which mistook a schema property named `responses` for the context of the same name and had to give up entirely under `callbacks` and `webhooks`. It now walks the ancestors the walker recorded and reads their node types, so the direction below a callback or a webhook is flipped rather than skipped, and a property can no longer pose as a context. That also uncovered a real defect: a usage edge named the `$ref` path, which is not a node and so could never be looked up; it now names the node holding the reference. The new rules cover request bodies becoming required or disappearing, numeric and string constraints, `format`, `additionalProperties`, `oneOf`/`allOf` membership, response headers, parameter serialization, and security schemes and requirements. They share one vocabulary: a constraint moves `tighter` or `looser`, and the engine's polarity decides which of the two breaks. Two false positives are gone with them. A type is now compared as the set of values it accepts, so widening a request type is no longer breaking, and 3.0's `nullable: true` folds into 3.1's `type: [..., 'null']` so the two spellings compare as equal. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The per-rule fixtures now sit beside breaking-changes and follow the same shape — base.yaml, revision.yaml and a stylish snapshot — so each rule's report is reviewable as the output a reader actually sees. Every test still names the rule id it exercises, so a regenerated snapshot cannot quietly stop covering it. Reviewing the snapshots turned up a stray label: a change on the document root rendered with an empty name before the property. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
vadyvas
force-pushed
the
feat/diff-command
branch
from
August 7, 2026 16:47
fe59519 to
7d66075
Compare
Contributor
Performance Benchmark (Lower is Faster)
|
Contributor
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.
What/Why/How?
Adds a new experimental
redocly diff <base> <revision>command that compares two API descriptions and reports what was added, removed, and changed.openapi-coretype trees — no per-type hand-written traversal.breaking/warning/non-breaking) for OpenAPI 3.x via a polarity-aware, lint-style rule registry (worst verdict wins).walkDocument) into a flat stable-pointer map → two-pass compare into a change list → classify. List items with a natural identity (e.g. parameters byin+name) are matched by identity, so reordering is not reported as a change. Shared components are diffed once; whether a component change is breaking is derived from where it's used (request/response), via a usage index.stylish(default),json(versioned schema),markdown(PR comments),html(self-contained report).--fail-on breaking|warning|none(defaultbreaking) sets the exit code.Usage:
Reference
Testing
Screenshots (optional)
Check yourself
Security