{"id":15091330,"url":"https://github.com/typeable/comparest","last_synced_at":"2025-04-12T06:31:45.202Z","repository":{"id":43379007,"uuid":"340356702","full_name":"typeable/compaREST","owner":"typeable","description":"Compatibility checker for OpenAPI","archived":false,"fork":false,"pushed_at":"2024-04-23T20:04:45.000Z","size":847,"stargazers_count":24,"open_issues_count":29,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-23T22:24:34.688Z","etag":null,"topics":["api","openapi","openapi-spec","openapi-specification","openapi3"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/compaREST","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typeable.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-19T12:03:06.000Z","updated_at":"2024-05-28T08:27:34.544Z","dependencies_parsed_at":"2024-04-23T21:29:24.092Z","dependency_job_id":null,"html_url":"https://github.com/typeable/compaREST","commit_stats":{"total_commits":90,"total_committers":4,"mean_commits":22.5,"dds":0.3555555555555555,"last_synced_commit":"f0f24add42fc9cd76fc8dd5d9116cee3ebae4839"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typeable%2FcompaREST","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typeable%2FcompaREST/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typeable%2FcompaREST/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typeable%2FcompaREST/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typeable","download_url":"https://codeload.github.com/typeable/compaREST/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248529664,"owners_count":21119555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","openapi","openapi-spec","openapi-specification","openapi3"],"created_at":"2024-09-25T10:40:28.156Z","updated_at":"2025-04-12T06:31:40.323Z","avatar_url":"https://github.com/typeable.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# compaREST\n\n[![Hackage](https://img.shields.io/hackage/v/compaREST.svg?logo=haskell)](https://hackage.haskell.org/package/compaREST)\n[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nCompatibility checker for OpenAPI\n\n## Using compaREST in Github Actions\n\nAdd the following step to your  Github Actions workflow:\n\n```yaml\n- uses: typeable/comparest\n    if: ${{ github.event_name == 'pull_request' }}\n    with:\n      old: old-openapi.yaml\n      new: new-openapi.yaml\n```\n\nThe `new` and `old` values should be paths to your OpenAPI specifications you want to compare.\n\nYou will get something like this in your pull requests:\n\n![](docs/img/github-action-report.png)\n\nFor more detail please see our [integration guide](docs/Integration_guide.md).\n\n## An example\n\n### Your situation\n\nYou are developing a very important server with a REST API. You have clients who use your API that you do not control. Say, you are also developing a mobile app that uses your API and you can't force someone to update to the latest version. (Or you prefer not to for UX reasons.)\n\nYou have recently released version 1.0 and things are going great: user are downloading your app, servers are processing requests.\n\nYou describe your API in a file `api-1.0.0.yaml`:\n\n```yaml\nopenapi: \"3.0.0\"\ninfo:\n  version: 1.0.0\n  title: Swagger Petstore\n  license:\n    name: MIT\nservers:\n  - url: https://example.com\npaths:\n  /pets:\n    get:\n      parameters:\n        - name: limit\n          in: query\n          required: false\n          schema:\n            type: integer\n            maximum: 20\n      responses:\n        \"200\":\n          description: \"\"\n          headers:\n            x-next:\n              schema:\n                type: string\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Pets\"\n    post:\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: \"#/components/schemas/Pet\"\n      responses:\n        \"201\":\n          description: \"\"\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      required:\n        - id\n        - name\n      properties:\n        id:\n          type: integer\n        name:\n          type: string\n          minLength: 3\n          maxLength: 10\n    Pets:\n      type: array\n      items:\n        $ref: \"#/components/schemas/Pet\"\n```\n\n### Evolving your product\n\nEnthused over your initial success you hurry to release a new and improved version of your API and mobile app.\n\nAfter a round of very intense programming you take a look at your new `api-1.1.0.yaml`:\n\n```yaml\nopenapi: \"3.0.0\"\ninfo:\n  version: 1.1.0\n  title: Swagger Petstore\n  license:\n    name: MIT\nservers:\n  - url: https://example.com\npaths:\n  /pets:\n    get:\n      parameters:\n        - name: limit\n          in: query\n          required: false\n          schema:\n            type: integer\n            maximum: 30\n      responses:\n        \"200\":\n          description: \"\"\n          headers:\n            x-next:\n              schema:\n                type: string\n          content:\n            application/json:\n              schema:\n                $ref: \"#/components/schemas/Pets\"\n    post:\n      requestBody:\n        content:\n          application/json:\n            schema:\n              $ref: \"#/components/schemas/Pet\"\n      responses:\n        \"201\":\n          description: \"\"\ncomponents:\n  schemas:\n    Pet:\n      type: object\n      required:\n        - id\n        - name\n      properties:\n        id:\n          type: integer\n        name:\n          type: string\n          minLength: 1\n          maxLength: 15\n        weight:\n          type: integer\n    Pets:\n      type: array\n      items:\n        $ref: \"#/components/schemas/Pet\"\n```\n\nLooking at the very large and complex API description, you grow more and more concerned that your old mobile app might stop working when you update the server. But the spec is too large and too complex to reasonably assess this manually.\n\n### Assessing compatibility automatically\n\nLuckily, you have access to compaREST which can programmatically analyze your APIs and determine what, if anything, breaks compatibility and what doesn't.\n\nYou can call it, passing the API your client will be aware of, and the API your server will serve like so:\n\n```bash\ndocker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report.md\n```\n\nRunning this command will output a file `report.md`, containing the compatibility report between the two APIs:\n\n\u003e # Summary\n\u003e\n\u003e | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) |\n\u003e |------------------------------------------|--------------------------------------------------|\n\u003e | 5                                        | 6                                                |\n\u003e\n\u003e # \u003cspan id=\"breaking-changes\"\u003e\u003c/span\u003e❌ Breaking changes\n\u003e\n\u003e ## **GET** /pets\n\u003e\n\u003e ### ⬅️☁️ JSON Response – 200\n\u003e\n\u003e #### `$[*].name(String)`\n\u003e\n\u003e 1.  Maximum length of the string changed from 10 to 15.\n\u003e\n\u003e 2.  Minimum length of the string changed from 3 to 1.\n\u003e\n\u003e ## **POST** /pets\n\u003e\n\u003e ### ➡️☁️ JSON Request\n\u003e\n\u003e #### `$.weight`\n\u003e\n\u003e 1.  Values are now limited to the following types:\n\u003e\n\u003e     -   Number\n\u003e\n\u003e 2.  The property was previously implicitly described by the catch-all\n\u003e     \"additional properties\" case. It is now explicitly defined.\n\u003e\n\u003e #### `$.weight(Number)`\n\u003e\n\u003e Value is now a multiple of 1.0.\n\u003e\n\u003e # \u003cspan id=\"non-breaking-changes\"\u003e\u003c/span\u003e⚠️ Non-breaking changes\n\u003e\n\u003e ## **GET** /pets\n\u003e\n\u003e ### Parameter limit\n\u003e\n\u003e #### JSON Schema\n\u003e\n\u003e ##### `$(Number)`\n\u003e\n\u003e Upper bound changed from 20.0 inclusive to 30.0 inclusive.\n\u003e\n\u003e ### ⬅️☁️ JSON Response – 200\n\u003e\n\u003e #### `$[*].weight`\n\u003e\n\u003e 1.  Values are now limited to the following types:\n\u003e\n\u003e     -   Number\n\u003e\n\u003e 2.  The property was previously implicitly described by the catch-all\n\u003e     \"additional properties\" case. It is now explicitly defined.\n\u003e\n\u003e #### `$[*].weight(Number)`\n\u003e\n\u003e Value is now a multiple of 1.0.\n\u003e\n\u003e ## **POST** /pets\n\u003e\n\u003e ### ➡️☁️ JSON Request\n\u003e\n\u003e #### `$.name(String)`\n\u003e\n\u003e 1.  Maximum length of the string changed from 10 to 15.\n\u003e\n\u003e 2.  Minimum length of the string changed from 3 to 1.\n\nYou now know exactly in what situations and in what way your 1.0 version of the app will break if you deploy your 1.1 version of the server.\n\n### Additional formats\n\nYou can also produce a self-contained HTML report that you can open in your browser by simply omitting the file extension of the output file:\n\n```bash\ndocker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report\n```\n\n## CLI docs\n\nFor more detail please see our [user guide](docs/User_guide.md).\n\n```\nUsage: comparest (-c|--client ARG) (-s|--server ARG)\n                 [--silent | --only-breaking | --all] [-o|--output ARG]\n                 [--folding-block-quotes-style | --header-style]\n                 [--signal-exit-code]\n  A tool to check compatibility between two OpenAPI specifications.\n\n  Usage examples\n\n      Compare files old.yaml with new.yaml and output the resulting report to\n      stdout:\n\n          comparest -c old.yaml -s new.yaml\n\n      Only output breaking changes and write a styled HTML report to file\n      report.html:\n\n          comparest -c old.yaml -s new.yaml --only-breaking -o report\n\n      Don't output anything, only fail if there are breaking changes:\n\n          comparest -c old.json -s new.json --silent\n\n      Write full report suitable for embedding into a GitHub comment to\n      report.html:\n\n          comparest -c old.json -s new.json --folding-block-quotes-style -o report.html\n\nAvailable options:\n  -h,--help                Show this help text\n  -c,--client ARG          A path to the file containing the specification that\n                           will be used for the client of the API. Can be either\n                           a YAML or JSON file.\n  -s,--server ARG          A path to the file containing the specification that\n                           will be used for the server of the API. Can be either\n                           a YAML or JSON file.\n  --silent                 Silence all output. Only makes sense in combination\n                           with --signal-exit-code.\n  --only-breaking          Only report breaking changes in the output.\n  --all                    Report both incompatible and compatible changes.\n                           Compatible changes will not trigger a failure exit\n                           code.\n  -o,--output ARG          The file path where the output should be written. If\n                           the option is omitted the result will be written to\n                           stdout.\n\n                           The file extension is used to determine the type of\n                           the output file.\n\n                           Supports many formats such as markdown, html, rtf,\n                           doc, txt, rst, and many more.\n\n                           Leave out the extension to produce a self-contained\n                           HTML report with styling.\n  --folding-block-quotes-style\n                           The report tree is structured using summary/detail\n                           HTML elements and indented using block quotes. This\n                           style renders well on GitHub.Intended for HTML output\n                           format. Markdown has rendering bugs on GitHub.\n  --header-style           The report tree is structured using increasing levels\n                           of headers.\n  --signal-exit-code       Signal API compatibility with the exit code.\n\n                           Exit with 0 if there are no breaking changes.\n                           Exit with 1 if there are breaking changes.\n                           Exit with 2 if could not determine compatibility.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypeable%2Fcomparest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypeable%2Fcomparest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypeable%2Fcomparest/lists"}