Skip to content

Commit 88461e7

Browse files
committed
Update README.md
1 parent 73eec51 commit 88461e7

File tree

1 file changed

+67
-124
lines changed

1 file changed

+67
-124
lines changed

README.md

Lines changed: 67 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,98 @@
11
# REST API Diff
22

3-
This tool is intended to be used to compare two OpenAPI 2.0 (Swagger) specifications to determine if there are
4-
relevant differences that affect the API contract. The primary use case is to compare a hand-written specification
5-
against the one generated from TypeSpec to determine if the TypeSpec accurately describes the same API contract.
3+
This tool compares two OpenAPI 2.0 (Swagger) specifications to identify relevant differences in the API contract.
64

75
## Install
86

9-
1. Run `npm install @azure-tools/rest-api-diff`
10-
2. If you want to make use of TypeSpec compilation features, `npm install @typespec/compiler`
7+
```bash
8+
npm install -g @azure-tools/rest-api-diff
9+
```
1110

1211
## Usage
1312

14-
1. Run `npx rest-api-diff --lhs <lhs_path> --rhs <rhs_path> [--compile-tsp] [--group-violations]` or `npx rest-api-diff` if you are using a `.env` file (Recommended)
13+
```bash
14+
npx rest-api-diff \
15+
--lhs <lhs_path_or_dir> \
16+
--rhs <rhs_path_or_dir> \
17+
[--group-violations] \
18+
[--output-folder <folder>] \
19+
[--flatten-paths] \
20+
[--preserve-definitions] \
21+
[--verbose] \
22+
[--suppressions <file>]
23+
```
24+
25+
- `--lhs`: Path or directory for the “left‑hand” Swagger files.
26+
- `--rhs`: Path or directory for the “right‑hand” Swagger files.
27+
- `--group-violations`: Group violations by rule into summary entries.
28+
- `--output-folder`: Folder for all output artifacts (default `./output`).
29+
- `--flatten-paths`: Collapse path arrays into a single slash‑delimited string.
30+
- `--preserve-definitions`: Keep definitions, parameters, responses, and securityDefinitions in output.
31+
- `--verbose`: Print detailed log messages.
32+
- `--suppressions`: Path to a YAML file listing diffs to suppress.
1533

1634
## Dev Install
1735

18-
1. Clone this repository
19-
2. Run `npm install`
20-
3. If you want to make use of TypeSpec compilation features, `npm install @typespec/compiler`
36+
```bash
37+
git clone https://github.com/azure-tools/rest-api-diff.git
38+
cd rest-api-diff
39+
npm install
40+
```
2141

2242
## Dev Usage
2343

24-
1. Run `npm run build` to build the tool. Alternatively, run `npm run watch` in a separate terminal so that changes to the TypeScript files are automatically re-compiled (RECOMMENDED).
25-
2. Run `npm run rest-api-diff -- --lhs <lhs_path> --rhs <rhs_path> [--compile-tsp] [--group-violations]` or `npm run rest-api-diff` if you are using a `.env` file (Recommended)
26-
27-
`lhs_path` and `rhs_path` are the paths to the Swagger specifications to compare, or the folders
28-
containing them. If the paths are folders, the tool will search for all Swagger files in that folder,
29-
but will not search subfolders.
30-
31-
`lhs_root` and `rhs_root` are optional parameters. If you are pointing to Swagger files, they should not be needed. However, if you are compiling
32-
TypeSpec, you should provide this so that the references get generated and resolve correctly. The value should be to set to where the Swagger
33-
files should be generated. Since that would normally result in overwriting the existing files, it's recommended that you just replace the path
34-
segment "stable" or "preview" with "generated" in the path. In this way, the Swagger will be generated into a unique folder with the same relative
35-
references as if it had been generated in the "correct" folder. This allows the tool to resolve the references correctly.
36-
37-
### Options
38-
39-
- `--compile-tsp`: The tool will attempt to compile TypeSpec files to Swagger using the
40-
`@azure-tools/autorest` emitter. If existing Swagger files are found, they will be overwritten
41-
by the compilation.
42-
- `--group-violations`: The tool will group violations by rule within `diff.json`, rather than
43-
listing them as a flat collection. It will include a count of violations and the file will
44-
be sorted in descending order by count. Assumed violations will be automatically grouped into
45-
generated groups with the '(AUTO)' suffix.
46-
- `--output-folder`: The folder to write the output files to. If not specified, the output will be
47-
written to `./output`. The output folder is cleared with each run.
48-
- `--typespec-compiler-path`: The path to the `@typespec/compiler` package. If not specified, the
49-
tool will attempt to use the globally installed package. If you get "compiler mismatch" errors,
50-
try configuring this.
51-
- `--typespec-version-selector`: This is used for multiversioned TypeSpec files to select the version
52-
you want to generate Swagger for. If omitted, the latest version will be generated.
53-
- `--preserve-definitions`: The intended purpose of the tool is to determine if two REST APIs described
54-
by Swagger are equivalent. Thus, Swagger definitions, parameters, responses, and security definitions,
55-
which exist solely for code re-use, aren't relevant to that question unless those definitions are used
56-
with a request or response. Hence, they are, by defult, pruned from the output. If you want to preserve
57-
these, for example to compare the definitions themselves between two Swaggers, provide this flag.
58-
- `--flatten-paths`: The default format of paths in the output is an array of path segments. If you prefer
59-
to flatten these into a forward-slash delimited string, provide this flag.
60-
- `--lhs-root`: The root path for the left-hand side Swagger files. This is used to resolve references
61-
when compiling TypeSpec files. If omitted, the tool will attempt to resolve the references without it.
62-
- `--rhs-root`: The root path for the right-hand side Swagger files. This is used to resolve references
63-
when compiling TypeSpec files. If omitted, the tool will attempt to resolve the references without it.
64-
- `--suppressions`: Path to a YAML file containing suppressions.
65-
66-
### .env File
67-
68-
You can also specify environment variables for all options and/or use a .env file. Example:
69-
44+
```bash
45+
npm run build
46+
npm run rest-api-diff -- --lhs <lhs_path_or_dir> --rhs <rhs_path_or_dir> [options]
7047
```
71-
LHS="KeyVaultOriginal/secrets.json"
72-
RHS="KeyVaultGenerated"
73-
RHS="<PATH_TO_SPECS_REPO>/specification"
74-
COMPILE_TSP="true"
75-
GROUP_VIOLATIONS="true"
76-
TYPESPEC_COMPILER_PATH="<PATH_TO_SPECS_REPO>/node_modules/@typespec/compiler"
77-
TYPESPEC_VERSION_SELECTOR="2021-06-01"
78-
PRESERVE_DEFINITIONS="false"
79-
```
80-
81-
## Output
82-
83-
The output artifacts are:
8448

85-
- `lhs.json` the transformed and pruned API specification for the left-hand side.
86-
- `rhs.json` the transformed and pruned API specification for the right-hand side.
87-
- `diff.json` the list of diff items between the two specifications.
49+
## .env Support
8850

89-
You can run a visual diff on `lhs.json` and `rhs.json` to visually see the differences that should appear in `diff.json`.
90-
![diff](https://github.com/tjprescott/openapi-diff/assets/5723682/ac4ec19d-88fc-4673-8fa9-cc926d63744c)
51+
You may define any of the above options via environment variables in a `.env` file:
9152

92-
`diff.json` contains each specific diff that was found between the two specifications and was not resolved by a rule.
93-
94-
The schema of the diff object:
95-
96-
- `ruleResult`: An enum which describes the result of the rule that was applied to the diff. F = Flagged, A = Assumed, or N = NoViolation.
97-
- `ruleName`: The name of the rule that was applied to the diff. For assumed violations, this will be null.
98-
- `message`: For flagged violations, this may contains a message offering more insight into the specific problem.
99-
- `diff`: The diff object, which has the following properties:
100-
- `kind`: Identifies the kind of change. E = Edit, N = New, D = Delete or A = Array.
101-
- `path`: A list of path segments from the root of the document to the problematic node.
102-
- `lhs`: The value of the node in the left-hand side document, if applicable.
103-
- `rhs`: The value of the node in the right-hand side document, if applicable.
53+
```text
54+
LHS="specs/original"
55+
RHS="specs/generated"
56+
GROUP_VIOLATIONS="true"
57+
OUTPUT_FOLDER="output"
58+
FLATTEN_PATHS="true"
59+
PRESERVE_DEFINITIONS="false"
60+
VERBOSE="true"
61+
SUPPRESSIONS="suppressions.yml"
62+
```
10463

105-
For diagnostic purposes, the tool will also output the following "inverse" files:
64+
## Output Artifacts
10665

107-
- `lhs-inv.json` the transformed API with the violations pruned for the left-hand side. Lets you see only the diffs that were considered "non-violations".
108-
- `rhs-inv.json` the transformed API with the violations pruned for the right-hand side. Lets you see only the diffs that were considered "non-violations".
109-
- `diff-inv.json` the list of diff items between the two specifications that were considered "non-violations".
66+
- **lhs.json**: Transformed, pruned LHS Swagger.
67+
- **rhs.json**: Transformed, pruned RHS Swagger.
68+
- **diff.json**: All diffs that affect the API contract.
69+
- **lhs-inv.json**, **rhs-inv.json**, **diff-inv.json**: Inverse views (non‑violations).
70+
- **lhs-raw.json**, **rhs-raw.json**: Raw transformations without pruning.
11071

111-
A visual diff of `lhs-inv.json` and `rhs-inv.json` will show you only the differences that the tool considered "non-violations" or irrelevant. `diff-inv.json` will
112-
also tell you which rule was applied that rendered the diff as a "non-violation". These can be useful to validate the rule logic and ensure it is not letting
113-
actually violations sneak through.
72+
Use a visual‑diff tool on `lhs.json`/`rhs.json` to inspect flagged differences.
11473

115-
Finally the tool will also output `lhs-raw.json` and `rhs-raw.json` which are the transformed files with no pruning or rule application. These can be useful for
116-
debugging purposes.
74+
## Suppressions
11775

118-
## Running against the REST API Specs Repo
76+
Create a YAML file to suppress known differences:
11977

120-
These steps assume that `--lhs` points to a Swagger folder and `--rhs` points to a TypeSpec folder, both within the REST API specs repo. If this is not the case, your steps will differ.
78+
```yaml
79+
- path: "paths//users//get/"
80+
reason: "Allowed pagination change"
81+
```
12182
122-
1. Ensure you have updated the dependencies in your fork by running `npm install` in the REST API specs repo root. You may need to delete `package-lock.json` first. Copy the path to the `node_modules/@typespec/compiler` package.
123-
2. Set the `TYPESPEC_COMPILER_PATH` environment variable (ideally in .env) to the path you copied in step 1.
124-
3. Ensure that LHS and RHS point to the appropriate paths in the REST API specs repo.
125-
4. By convention, if you are comparing hand-written Swagger to TypeSpec, the Swagger should be LHS and the TypeSpec should be RHS. When compiling TypeSpec, you will
126-
need to set RHS_ROOT. **If you are following the convention, the tool will automatically use the same folder as LHS for RHS_ROOT except changing the "stable" or "preview"
127-
folder to "temp", which will subsequently be deleted after the tool completes.** This is so the relative paths get generated and resolve correctly without bulldozing
128-
and existing files.
129-
5. If you are comparing to a multi-versioned TypeSpec, you should probably include the `TYPESPEC_VERSION_SELECTOR` environment variable to ensure you are generating the right version for comparison.
83+
Supply it with `--suppressions <file>` to filter those diffs out of `diff.json`.
13084

13185
## Rules
13286

133-
The way `openapi-diff` works is by expanding references (except circular references) into inline definitions, combining multiple
134-
files and applying certain special-casing logic (such as `x-ms-parameterized-host`) in order to produce a "canonical" representation
135-
of the Swagger. It then compares the two using the `deep-diff` package. The diff elements are run through a pipeline of rules. Each
136-
rule can make one of three determinations:
137-
138-
- `RuleResult.NoViolation`: this describes a diff that doesn't affect the API surface area, and thus we will ignore the diff and prune
139-
the path from both `lhs.json` and `rhs.json` so they won't appear in a visual diff.
140-
- `RuleResult.FlaggedViolation`: a pattern is identified that we confirm affects the API surface area and thus represents a violation.
141-
This will be reported by the tool and may include an amplifying message. It will appear in a visual diff.
142-
- `RuleResult.ContinueProcessing`: the logic of the rule doesn't apply to this diff and thus the tool should continue processing rules.
87+
The tool expands references, combines multiple files, and applies special logic (e.g., `x-ms-parameterized-host`) to produce a canonical Swagger representation. It then compares the two using `deep-diff` and runs each diff through a pipeline of rules:
14388

144-
When processing a diff item against the rules, if `NoViolation` is returned by a rule, it immediately suspends processing additional rules. If `FlaggedViolation` is returned, rules will continue to be processed in case another rule marks it as `NoViolation`. If all rules are run and no determination is made, then the diff is assumed to affect the API surface area and is tracked as an assumed violation. It will be reported by the tool and will appear in a visual diff. When violations are grouped, these violations will appear in the `UNGROUPED` group.
89+
- `NoViolation`: Ignore diff and prune path from both Swaggers.
90+
- `FlaggedViolation`: Report diff as a violation; appears in visual output.
91+
- `ContinueProcessing`: Diff evaluated by subsequent rules.
92+
- Unmatched diffs are treated as assumed violations.
14593

146-
## Suppressions
147-
148-
It is possible that there will be differences between Swaggers that do matter but must be accepted. For this, you can point to a suppression file using the `--suppressions` option. This file should be a YAML file with the following schema:
149-
150-
```yaml
151-
- path: "path/to/target/"
152-
reason: "This is a reason why this path is suppressed."
153-
```
94+
## Running against the REST API Specs Repo
15495

155-
You can target paths directly from the `diff.json` file assuming `--flatten-paths` is used; however, often violations originate in definitions or parameters, and the way `rest-api-diff` expands these references to create the transformation, the result is that these diffs will be multiplied. In this case, you can use the path to the element in question from the Swagger and it will automatically resolve all diffs that might be a result of reference expansion. Because `rest-api-diff` compares these as Swagger, you cannot use a TypeSpec path even if you are targeting TypeSpec. You must use the Swagger path associated with the TypeSpec-generated Swagger.
96+
1. Ensure dependencies in your fork by running `npm install` in the REST API specs repo root.
97+
2. Point `--lhs` and `--rhs` to the appropriate Swagger folders.
98+
3. By convention, compare hand‑written Swagger (LHS) against generated Swagger (RHS).

0 commit comments

Comments
 (0)