├── .gitattributes ├── .github └── workflows │ └── test.yaml ├── .gitignore ├── LICENSE ├── README.md ├── breaking ├── Dockerfile ├── action.yml └── entrypoint.sh ├── changelog ├── Dockerfile ├── action.yml └── entrypoint.sh ├── diff ├── Dockerfile ├── action.yml └── entrypoint.sh └── specs ├── base-deprecation.yaml ├── base-exclude-elements.yaml ├── base.yaml ├── glob ├── base │ └── base.yaml └── revision │ └── revision-breaking.yaml ├── petstore-base.yaml ├── petstore-revision.yaml ├── revision-breaking-warn.yaml ├── revision-breaking.yaml └── revision.yaml /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: 'Test oasdiff actions' 2 | on: 3 | pull_request: 4 | push: 5 | jobs: 6 | oasdiff_diff: 7 | runs-on: ubuntu-latest 8 | name: Test diff action 9 | steps: 10 | - name: checkout 11 | uses: actions/checkout@v4 12 | - name: Running diff action 13 | id: test_ete 14 | uses: ./diff 15 | with: 16 | base: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml 17 | revision: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml 18 | format: 'text' 19 | output-to-file: 'diff.txt' 20 | - name: Test diff action output to file 21 | run: | 22 | if [ ! -s diff.txt ]; then 23 | echo "Diff file doesn't exist or is empty" 24 | exit 1 25 | fi 26 | oasdiff_diff_exclude_elements: 27 | runs-on: ubuntu-latest 28 | name: Test diff action with exclude-elements option 29 | steps: 30 | - name: checkout 31 | uses: actions/checkout@v4 32 | - name: Running diff action with exclude-elements option 33 | id: test_exclude_elements 34 | uses: ./diff 35 | with: 36 | base: 'specs/base.yaml' 37 | revision: 'specs/base-exclude-elements.yaml' 38 | format: 'text' 39 | exclude-elements: 'description,title,summary' 40 | - name: Test diff action output 41 | run: | 42 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 43 | output=$(cat <<-$delimiter 44 | ${{ steps.test_exclude_elements.outputs.diff }} 45 | $delimiter 46 | ) 47 | if [ "$output" != "No changes" ]; then 48 | echo "Expected output 'No changes' but got '$output'" >&2 49 | exit 1 50 | fi 51 | oasdiff_diff_composed: 52 | runs-on: ubuntu-latest 53 | name: Test diff action with composed option 54 | steps: 55 | - name: checkout 56 | uses: actions/checkout@v4 57 | - name: Running diff action with composed option 58 | id: test_composed 59 | uses: ./diff 60 | with: 61 | base: 'specs/glob/base/*.yaml' 62 | revision: 'specs/glob/revision/*.yaml' 63 | format: 'text' 64 | composed: true 65 | - name: Test diff action output 66 | run: | 67 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 68 | output=$(cat <<-$delimiter 69 | ${{ steps.test_composed.outputs.diff }} 70 | $delimiter 71 | ) 72 | if [[ ! "$output" =~ "Deleted Endpoints: 1" ]]; then 73 | echo "Expected 'Deleted Endpoints: 1' to be modified in diff, instead got '$output'" >&2 74 | exit 1 75 | fi 76 | oasdiff_breaking: 77 | runs-on: ubuntu-latest 78 | name: Test breaking changes 79 | env: 80 | OASDIFF_ACTION_TEST_EXPECTED_OUTPUT: "1 changes: 1 error, 0 warning, 0 info" 81 | steps: 82 | - name: checkout 83 | uses: actions/checkout@v4 84 | - name: Running breaking action 85 | id: test_breaking_changes 86 | uses: ./breaking 87 | with: 88 | base: 'specs/base.yaml' 89 | revision: 'specs/revision-breaking.yaml' 90 | output-to-file: 'breaking.txt' 91 | - name: Test breaking changes action output 92 | run: | 93 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 94 | output=$(cat <<-$delimiter 95 | ${{ steps.test_breaking_changes.outputs.breaking }} 96 | $delimiter 97 | ) 98 | if [ "$output" != "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]; then 99 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '$output'" >&2 100 | exit 1 101 | fi 102 | - name: Test breaking changes action output to file 103 | run: | 104 | if [ ! -s breaking.txt ]; then 105 | echo "Breaking changes file doesn't exist or is empty" 106 | exit 1 107 | fi 108 | output=$(cat breaking.txt | head -n 1) 109 | if [[ "${output}" != "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]]; then 110 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '${output}'" >&2 111 | exit 1 112 | fi 113 | oasdiff_breaking_fail_on: 114 | runs-on: ubuntu-latest 115 | name: Test fail on breaking changes 116 | env: 117 | OASDIFF_ACTION_TEST_EXPECTED_OUTPUT: "2 changes: 0 error, 2 warning, 0 info" 118 | steps: 119 | - name: checkout 120 | uses: actions/checkout@v4 121 | - name: Running breaking action 122 | id: test_breaking_changes 123 | uses: ./breaking 124 | with: 125 | base: 'specs/base.yaml' 126 | revision: 'specs/revision-breaking-warn.yaml' 127 | output-to-file: 'breaking.txt' 128 | fail-on: 'ERR' 129 | - name: Test breaking changes action output 130 | run: | 131 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 132 | output=$(cat <<-$delimiter 133 | ${{ steps.test_breaking_changes.outputs.breaking }} 134 | $delimiter 135 | ) 136 | if [ "$output" != "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]; then 137 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '$output'" >&2 138 | exit 1 139 | fi 140 | - name: Test breaking changes action output to file 141 | run: | 142 | if [ ! -s breaking.txt ]; then 143 | echo "Breaking changes file doesn't exist or is empty" 144 | exit 1 145 | fi 146 | output=$(cat breaking.txt | head -n 1) 147 | if [[ "${output}" != "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]]; then 148 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '${output}'" >&2 149 | exit 1 150 | fi 151 | oasdiff_breaking_matching_delimiter_not_found: 152 | runs-on: ubuntu-latest 153 | name: Test breaking action with petsotre to validate no error of unable to process file command 'output' successfully and invalid value and matching delimiter not found 154 | env: 155 | OASDIFF_ACTION_TEST_EXPECTED_OUTPUT: "9 changes: 6 error, 3 warning, 0 info" 156 | steps: 157 | - name: checkout 158 | uses: actions/checkout@v4 159 | - name: Running breaking action with petsotre to validate no error of unable to process file command 'output' successfully and invalid value and matching delimiter not found 160 | id: test_breaking_changes_matching_delimiter_not_found 161 | uses: ./breaking 162 | with: 163 | base: 'specs/petstore-base.yaml' 164 | revision: 'specs/petstore-revision.yaml' 165 | - name: Test breaking changes action output 166 | run: | 167 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 168 | output=$(cat <<-$delimiter 169 | ${{ steps.test_breaking_changes_matching_delimiter_not_found.outputs.breaking }} 170 | $delimiter 171 | ) 172 | if [ "$output" != "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]; then 173 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '$output'" >&2 174 | exit 1 175 | fi 176 | oasdiff_breaking_composed: 177 | runs-on: ubuntu-latest 178 | name: Test breaking action with composed option 179 | env: 180 | OASDIFF_ACTION_TEST_EXPECTED_OUTPUT: "1 changes: 1 error, 0 warning, 0 info" 181 | steps: 182 | - name: checkout 183 | uses: actions/checkout@v4 184 | - name: Running breaking action with composed option 185 | id: test_breaking_composed 186 | uses: ./breaking 187 | with: 188 | base: 'specs/glob/base/*.yaml' 189 | revision: 'specs/glob/revision/*.yaml' 190 | composed: true 191 | - name: Test breaking action output 192 | run: | 193 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 194 | output=$(cat <<-$delimiter 195 | ${{ steps.test_breaking_composed.outputs.breaking }} 196 | $delimiter 197 | ) 198 | if [[ ! "$output" =~ "$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT" ]]; then 199 | echo "Expected '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT', instead got '$output'" >&2 200 | exit 1 201 | fi 202 | oasdiff_breaking_deprecation: 203 | runs-on: ubuntu-latest 204 | name: Test breaking changes with deprecation 205 | steps: 206 | - name: checkout 207 | uses: actions/checkout@v4 208 | - name: Set date for deprecated specs 209 | run: | 210 | # Deprecate Beta in 14 days 211 | sed -ie "s/{{SUNSET_DATE_BETA}}/$(date --date="14 day" "+%Y-%m-%d")/" specs/base-deprecation.yaml 212 | # Deprecate Stable in 21 days 213 | sed -ie "s/{{SUNSET_DATE_STABLE}}/$(date --date="21 day" "+%Y-%m-%d")/" specs/base-deprecation.yaml 214 | - name: Running OpenAPI Spec check breaking action 215 | id: test_breaking_deprecations 216 | uses: ./breaking 217 | with: 218 | base: specs/base.yaml 219 | revision: specs/base-deprecation.yaml 220 | deprecation-days-beta: 14 221 | deprecation-days-stable: 21 222 | oasdiff_changelog: 223 | runs-on: ubuntu-latest 224 | name: Test generation of changelog 225 | env: 226 | OASDIFF_ACTION_TEST_EXPECTED_OUTPUT: "21 changes: 2 error, 4 warning, 15 info" 227 | steps: 228 | - name: checkout 229 | uses: actions/checkout@v4 230 | - name: Running changelog action 231 | id: test_changelog 232 | uses: ./changelog 233 | with: 234 | base: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml 235 | revision: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml 236 | output-to-file: "changelog.txt" 237 | - name: Test changelog action output 238 | run: | 239 | output=$(echo "${{steps.test_changelog.outputs.changelog}}" | head -n 1) 240 | if [[ "${output}" != "${OASDIFF_ACTION_TEST_EXPECTED_OUTPUT}" ]]; then 241 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '${output}'" >&2 242 | exit 1 243 | fi 244 | - name: Test changelog action output to file 245 | run: | 246 | if [ ! -s changelog.txt ]; then 247 | echo "Changelog file doesn't exist or is empty" 248 | exit 1 249 | fi 250 | output=$(cat changelog.txt | head -n 1) 251 | if [[ "${output}" != "${OASDIFF_ACTION_TEST_EXPECTED_OUTPUT}" ]]; then 252 | echo "Expected output '$OASDIFF_ACTION_TEST_EXPECTED_OUTPUT' but got '${output}'" >&2 253 | exit 1 254 | fi 255 | oasdiff_changelog_composed: 256 | runs-on: ubuntu-latest 257 | name: Test changelog action with composed option 258 | steps: 259 | - name: checkout 260 | uses: actions/checkout@v4 261 | - name: Running changelog action with composed option 262 | id: test_changelog_composed 263 | uses: ./changelog 264 | with: 265 | base: 'specs/glob/base/*.yaml' 266 | revision: 'specs/glob/revision/*.yaml' 267 | composed: true 268 | - name: Test changelog action output 269 | run: | 270 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 271 | output=$(cat <<-$delimiter 272 | ${{ steps.test_changelog_composed.outputs.changelog }} 273 | $delimiter 274 | ) 275 | if [[ ! "$output" =~ "1 changes: 1 error, 0 warning, 0 info" ]]; then 276 | echo "Expected '1 changes: 1 error, 0 warning, 0 info', instead got '$output'" >&2 277 | exit 1 278 | fi 279 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oasdiff-action 2 | [![CI](https://github.com/oasdiff/oasdiff-action/actions/workflows/test.yaml/badge.svg)](https://github.com/oasdiff/oasdiff-action/actions) 3 | 4 | GitHub actions for comparing OpenAPI specs and detect breaking changes, based on [oasdiff](https://github.com/oasdiff/oasdiff) tool 5 | 6 | ## How to use? 7 | Depending on your use case, refer below for instructions on generating reports for differences, breaking changes and changelog. 8 | 9 | ### Generate a diff report 10 | Copy and paste the following snippet into your build .yml file: 11 | ``` 12 | - name: Running OpenAPI Spec diff action 13 | uses: oasdiff/oasdiff-action/diff@main 14 | with: 15 | base: 'specs/base.yaml' 16 | revision: 'specs/revision.yaml' 17 | ``` 18 | 19 | This action supports additional arguments. Most are converted to parameters for the `oasdiff` CLI. 20 | 21 | | CLI | Action input | Default | 22 | | --------------------- | ------------------- | ------- | 23 | | --fail-on-diff | fail-on-diff | false | 24 | | --format | format | yaml | 25 | | --include-path-params | include-path-params | false | 26 | | --exclude-elements | exclude-elements | '' | 27 | | --composed | composed | false | 28 | | N/A | output-to-file | '' | 29 | 30 | ### Check for breaking API changes, and fail if any are found 31 | Copy and paste the following snippet into your build .yml file: 32 | ``` 33 | - name: Running OpenAPI Spec diff action 34 | uses: oasdiff/oasdiff-action/breaking@main 35 | with: 36 | base: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml 37 | revision: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml 38 | ``` 39 | 40 | Additional arguments: 41 | 42 | | CLI | Action input | Default | 43 | | ------------------------- | ----------------------- | ------- | 44 | | --fail-on | fail-on | empty | 45 | | --include-checks | include-checks | csv | 46 | | --include-path-params | include-path-params | false | 47 | | --deprecation-days-beta | deprecation-days-beta | 31 | 48 | | --deprecation-days-stable | deprecation-days-stable | 180 | 49 | | --exclude-elements | exclude-elements | '' | 50 | | --composed | composed | false | 51 | | N/A | output-to-file | '' | 52 | 53 | This action delivers a summary of breaking changes, accessible as a GitHub step output named `breaking`. 54 | 55 | ### Generate a changelog 56 | Copy and paste the following snippet into your build .yml file: 57 | ``` 58 | - name: Running OpenAPI Spec diff action 59 | uses: oasdiff/oasdiff-action/changelog@main 60 | with: 61 | base: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml 62 | revision: https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml 63 | ``` 64 | 65 | Additional arguments: 66 | 67 | | CLI | Action input | Default | 68 | | --------------------- | ------------------- | ------- | 69 | | --include-path-params | include-path-params | false | 70 | | --exclude-elements | exclude-elements | '' | 71 | | --composed | composed | false | 72 | | N/A | output-to-file | '' | 73 | -------------------------------------------------------------------------------- /breaking/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tufin/oasdiff:stable 2 | ENV PLATFORM github-action 3 | COPY entrypoint.sh /entrypoint.sh 4 | ENTRYPOINT ["/entrypoint.sh"] 5 | -------------------------------------------------------------------------------- /breaking/action.yml: -------------------------------------------------------------------------------- 1 | name: 'Check for API breaking changes' 2 | description: 'Detect breaking changes' 3 | inputs: 4 | base: 5 | description: 'Path of original OpenAPI spec in YAML or JSON format' 6 | required: true 7 | revision: 8 | description: 'Path of revised OpenAPI spec in YAML or JSON format' 9 | required: true 10 | fail-on: 11 | description: 'Fail with exit code 1 if any breaking changes are found at severity level, such as ERR or WARN' 12 | required: false 13 | default: '' 14 | include-checks: 15 | description: 'Include any of the defined optional breaking changes checks' 16 | required: false 17 | include-path-params: 18 | description: 'Include path parameter names in endpoint matching' 19 | required: false 20 | default: 'false' 21 | deprecation-days-beta: 22 | description: 'Consider minimum sunset period for deprecation of beta API endpoints' 23 | required: false 24 | deprecation-days-stable: 25 | description: 'Consider minimum sunset period for deprecation of stable API endpoints' 26 | required: false 27 | exclude-elements: 28 | description: 'Exclude certain kinds of changes' 29 | required: false 30 | default: '' 31 | composed: 32 | description: 'Run in composed mode' 33 | required: false 34 | default: 'false' 35 | output-to-file: 36 | description: 'Output to a file at the given path' 37 | required: false 38 | default: '' 39 | outputs: 40 | breaking: 41 | description: 'Output summary of API breaking changes, encompassing both warnings and errors' 42 | runs: 43 | using: 'docker' 44 | image: 'Dockerfile' 45 | args: 46 | - ${{ inputs.base }} 47 | - ${{ inputs.revision }} 48 | - ${{ inputs.fail-on }} 49 | - ${{ inputs.include-checks }} 50 | - ${{ inputs.include-path-params }} 51 | - ${{ inputs.deprecation-days-beta }} 52 | - ${{ inputs.deprecation-days-stable }} 53 | - ${{ inputs.exclude-elements }} 54 | - ${{ inputs.composed }} 55 | - ${{ inputs.output-to-file }} -------------------------------------------------------------------------------- /breaking/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | readonly base="$1" 5 | readonly revision="$2" 6 | readonly fail_on="$3" 7 | readonly include_checks="$4" 8 | readonly include_path_params="$5" 9 | readonly deprecation_days_beta="$6" 10 | readonly deprecation_days_stable="$7" 11 | readonly exclude_elements="$8" 12 | readonly composed="$9" 13 | readonly output_to_file="${10}" 14 | 15 | write_output () { 16 | _write_output_output="$1" 17 | if [ -n "$output_to_file" ]; then 18 | _write_output_file_output="$2" 19 | if [ -z "$_write_output_file_output" ]; then 20 | _write_output_file_output=$_write_output_output 21 | 22 | fi 23 | echo "$_write_output_file_output" >> "$output_to_file" 24 | fi 25 | # github-action limits output to 1MB 26 | # we count bytes because unicode has multibyte characters 27 | size=$(echo "$_write_output_output" | wc -c) 28 | if [ "$size" -ge "1000000" ]; then 29 | echo "WARN: diff exceeds the 1MB limit, truncating output..." >&2 30 | _write_output_output=$(echo "$_write_output_output" | head -c 1000000) 31 | fi 32 | echo "$_write_output_output" >>"$GITHUB_OUTPUT" 33 | } 34 | 35 | echo "running oasdiff breaking... base: $base, revision: $revision, fail_on: $fail_on, include_checks: $include_checks, include_path_params: $include_path_params, deprecation_days_beta: $deprecation_days_beta, deprecation_days_stable: $deprecation_days_stable, exclude_elements: $exclude_elements, composed: $composed, output_to_file: $output_to_file" 36 | 37 | # Build flags to pass in command 38 | flags="" 39 | if [ "$include_path_params" = "true" ]; then 40 | flags="$flags --include-path-params" 41 | fi 42 | if [ -n "$include_checks" ]; then 43 | flags="$flags --include-checks $include_checks" 44 | fi 45 | if [ -n "$deprecation_days_beta" ]; then 46 | flags="$flags --deprecation-days-beta $deprecation_days_beta" 47 | fi 48 | if [ -n "$deprecation_days_stable" ]; then 49 | flags="$flags --deprecation-days-stable $deprecation_days_stable" 50 | fi 51 | if [ -n "$exclude_elements" ]; then 52 | flags="$flags --exclude-elements $exclude_elements" 53 | fi 54 | if [ "$composed" = "true" ]; then 55 | flags="$flags -c" 56 | fi 57 | echo "flags: $flags" 58 | 59 | # Check for breaking changes 60 | if [ -n "$flags" ]; then 61 | breaking_changes=$(oasdiff breaking "$base" "$revision" $flags) 62 | else 63 | breaking_changes=$(oasdiff breaking "$base" "$revision") 64 | fi 65 | 66 | # Updating GitHub Action summary with formatted output 67 | flags_with_githubactions="$flags --format githubactions" 68 | # Writes the summary to log and updates GitHub Action summary 69 | oasdiff breaking "$base" "$revision" $flags_with_githubactions 70 | 71 | # *** GitHub Action step output *** 72 | 73 | # Output name should be in the syntax of multiple lines: 74 | # {name}<<{delimiter} 75 | # {value} 76 | # {delimiter} 77 | # see: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings 78 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 79 | echo "breaking<<$delimiter" >>"$GITHUB_OUTPUT" 80 | 81 | if [ -n "$breaking_changes" ]; then 82 | write_output "$(echo "$breaking_changes" | head -n 1)" "$breaking_changes" 83 | else 84 | write_output "No breaking changes" 85 | fi 86 | 87 | echo "$delimiter" >>"$GITHUB_OUTPUT" 88 | 89 | # First output the changes (above) and then run oasdiff to check --fail-on 90 | if [ -n "$fail_on" ]; then 91 | flags="$flags --fail-on $fail_on" 92 | oasdiff breaking "$base" "$revision" $flags > /dev/null 93 | fi 94 | -------------------------------------------------------------------------------- /changelog/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tufin/oasdiff:stable 2 | ENV PLATFORM github-action 3 | COPY entrypoint.sh /entrypoint.sh 4 | ENTRYPOINT ["/entrypoint.sh"] 5 | -------------------------------------------------------------------------------- /changelog/action.yml: -------------------------------------------------------------------------------- 1 | name: 'OpenAPI Spec: changelog' 2 | description: 'Generate a changelog for OpenAPI Specification 3' 3 | inputs: 4 | base: 5 | description: 'Path of original OpenAPI spec in YAML or JSON format' 6 | required: true 7 | revision: 8 | description: 'Path of revised OpenAPI spec in YAML or JSON format' 9 | required: true 10 | include-path-params: 11 | description: 'Include path parameter names in endpoint matching' 12 | required: false 13 | default: 'false' 14 | exclude-elements: 15 | description: 'Exclude certain kinds of changes' 16 | required: false 17 | default: '' 18 | composed: 19 | description: 'Run in composed mode' 20 | required: false 21 | default: 'false' 22 | output-to-file: 23 | description: 'Output to a file at the given path' 24 | required: false 25 | default: '' 26 | outputs: 27 | changelog: 28 | description: 'Output summary of API changelog' 29 | runs: 30 | using: 'docker' 31 | image: 'Dockerfile' 32 | args: 33 | - ${{ inputs.base }} 34 | - ${{ inputs.revision }} 35 | - ${{ inputs.include-path-params }} 36 | - ${{ inputs.exclude-elements }} 37 | - ${{ inputs.composed }} 38 | - ${{ inputs.output-to-file }} 39 | -------------------------------------------------------------------------------- /changelog/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | write_output () { 5 | local output="$1" 6 | if [ -n "$output_to_file" ]; then 7 | local file_output="$2" 8 | if [ -z "$file_output" ]; then 9 | file_output=$output 10 | fi 11 | echo "$file_output" >> "$output_to_file" 12 | fi 13 | # github-action limits output to 1MB 14 | # we count bytes because unicode has multibyte characters 15 | size=$(echo "$output" | wc -c) 16 | if [ "$size" -ge "1000000" ]; then 17 | echo "WARN: diff exceeds the 1MB limit, truncating output..." >&2 18 | output=$(echo "$output" | head -c 1000000) 19 | fi 20 | echo "$output" >>"$GITHUB_OUTPUT" 21 | } 22 | 23 | readonly base="$1" 24 | readonly revision="$2" 25 | readonly include_path_params="$3" 26 | readonly exclude_elements="$4" 27 | readonly composed="$5" 28 | readonly output_to_file="$6" 29 | 30 | echo "running oasdiff changelog base: $base, revision: $revision, include_path_params: $include_path_params, exclude_elements: $exclude_elements, composed: $composed, output_to_file: $output_to_file" 31 | 32 | # Build flags to pass in command 33 | flags="" 34 | if [ "$include_path_params" = "true" ]; then 35 | flags="$flags --include-path-params" 36 | fi 37 | if [ -n "$exclude_elements" ]; then 38 | flags="$flags --exclude-elements $exclude_elements" 39 | fi 40 | if [ "$composed" = "true" ]; then 41 | flags="$flags -c" 42 | fi 43 | echo "flags: $flags" 44 | 45 | set -o pipefail 46 | 47 | # *** github action step output *** 48 | 49 | # output name should be in the syntax of multiple lines: 50 | # {name}<<{delimiter} 51 | # {value} 52 | # {delimiter} 53 | # see: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings 54 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 55 | echo "changelog<<$delimiter" >>"$GITHUB_OUTPUT" 56 | 57 | if [ -n "$flags" ]; then 58 | output=$(oasdiff changelog "$base" "$revision" $flags) 59 | else 60 | output=$(oasdiff changelog "$base" "$revision") 61 | fi 62 | 63 | if [ -n "$output" ]; then 64 | write_output "$output" 65 | else 66 | write_output "No changelog changes" 67 | fi 68 | 69 | echo "$delimiter" >>"$GITHUB_OUTPUT" 70 | 71 | # *** github action step output *** 72 | 73 | -------------------------------------------------------------------------------- /diff/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tufin/oasdiff:stable 2 | ENV PLATFORM github-action 3 | COPY entrypoint.sh /entrypoint.sh 4 | ENTRYPOINT ["/entrypoint.sh"] 5 | -------------------------------------------------------------------------------- /diff/action.yml: -------------------------------------------------------------------------------- 1 | name: 'OpenAPI Spec: diff' 2 | description: 'Generate a diff report for OpenAPI Specification 3' 3 | inputs: 4 | base: 5 | description: 'Path of original OpenAPI spec in YAML or JSON format' 6 | required: true 7 | revision: 8 | description: 'Path of revised OpenAPI spec in YAML or JSON format' 9 | required: true 10 | format: 11 | description: 'Output format' 12 | required: false 13 | default: 'yaml' 14 | fail-on-diff: 15 | description: 'Fail with exit code 1 if a difference is found' 16 | required: false 17 | default: 'false' 18 | include-path-params: 19 | description: 'Include path parameter names in endpoint matching' 20 | required: false 21 | default: 'false' 22 | exclude-elements: 23 | description: 'Exclude certain kinds of changes' 24 | required: false 25 | default: '' 26 | composed: 27 | description: 'Run in composed mode' 28 | required: false 29 | default: 'false' 30 | output-to-file: 31 | description: 'Output to a file at the given path' 32 | required: false 33 | default: '' 34 | outputs: 35 | diff: 36 | description: 'Output summary of API diff' 37 | runs: 38 | using: 'docker' 39 | image: 'Dockerfile' 40 | args: 41 | - ${{ inputs.base }} 42 | - ${{ inputs.revision }} 43 | - ${{ inputs.format }} 44 | - ${{ inputs.fail-on-diff }} 45 | - ${{ inputs.include-path-params }} 46 | - ${{ inputs.exclude-elements }} 47 | - ${{ inputs.composed }} 48 | - ${{ inputs.output-to-file }} 49 | -------------------------------------------------------------------------------- /diff/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | write_output () { 5 | local output="$1" 6 | if [ -n "$output_to_file" ]; then 7 | local file_output="$2" 8 | if [ -z "$file_output" ]; then 9 | file_output=$output 10 | fi 11 | echo "$file_output" >> "$output_to_file" 12 | fi 13 | # github-action limits output to 1MB 14 | # we count bytes because unicode has multibyte characters 15 | size=$(echo "$output" | wc -c) 16 | if [ "$size" -ge "1000000" ]; then 17 | echo "WARN: diff exceeds the 1MB limit, truncating output..." >&2 18 | output=$(echo "$output" | head -c 1000000) 19 | fi 20 | echo "$output" >>"$GITHUB_OUTPUT" 21 | } 22 | 23 | readonly base="$1" 24 | readonly revision="$2" 25 | readonly format="$3" 26 | readonly fail_on_diff="$4" 27 | readonly include_path_params="$5" 28 | readonly exclude_elements="$6" 29 | readonly composed="$7" 30 | readonly output_to_file="$8" 31 | 32 | echo "running oasdiff diff base: $base, revision: $revision, format: $format, fail_on_diff: $fail_on_diff, include_path_params: $include_path_params, exclude_elements: $exclude_elements, composed: $composed, output_to_file: $output_to_file" 33 | 34 | # Build flags to pass in command 35 | flags="" 36 | if [ "$format" != "yaml" ]; then 37 | flags="$flags --format $format" 38 | fi 39 | if [ "$fail_on_diff" = "true" ]; then 40 | flags="$flags --fail-on-diff" 41 | fi 42 | if [ "$include_path_params" = "true" ]; then 43 | flags="$flags --include-path-params" 44 | fi 45 | if [ -n "$exclude_elements" ]; then 46 | flags="$flags --exclude-elements $exclude_elements" 47 | fi 48 | if [ "$composed" = "true" ]; then 49 | flags="$flags -c" 50 | fi 51 | echo "flags: $flags" 52 | 53 | # *** github action step output *** 54 | 55 | # output name should be in the syntax of multiple lines: 56 | # {name}<<{delimiter} 57 | # {value} 58 | # {delimiter} 59 | # see: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings 60 | delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-') 61 | echo "diff<<$delimiter" >>"$GITHUB_OUTPUT" 62 | 63 | set -o pipefail 64 | 65 | if [ -n "$flags" ]; then 66 | output=$(oasdiff diff "$base" "$revision" $flags) 67 | else 68 | output=$(oasdiff diff "$base" "$revision") 69 | fi 70 | 71 | if [ -n "$output" ]; then 72 | write_output "$output" 73 | else 74 | write_output "No changes" 75 | fi 76 | 77 | echo "$delimiter" >>"$GITHUB_OUTPUT" -------------------------------------------------------------------------------- /specs/base-deprecation.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | deprecated: true 15 | x-stability-level: beta 16 | x-sunset: {{SUNSET_DATE_BETA}} 17 | tags: 18 | - pets 19 | parameters: 20 | - name: limit 21 | in: query 22 | description: How many items to return at one time (max 100) 23 | required: false 24 | schema: 25 | type: integer 26 | format: int32 27 | responses: 28 | '200': 29 | description: A paged array of pets 30 | headers: 31 | x-next: 32 | description: A link to the next page of responses 33 | schema: 34 | type: string 35 | content: 36 | application/json: 37 | schema: 38 | $ref: "#/components/schemas/Pets" 39 | default: 40 | description: unexpected error 41 | content: 42 | application/json: 43 | schema: 44 | $ref: "#/components/schemas/Error" 45 | post: 46 | summary: Create a pet 47 | operationId: createPets 48 | deprecated: true 49 | x-sunset: {{SUNSET_DATE_STABLE}} 50 | tags: 51 | - pets 52 | responses: 53 | '201': 54 | description: Null response 55 | default: 56 | description: unexpected error 57 | content: 58 | application/json: 59 | schema: 60 | $ref: "#/components/schemas/Error" 61 | /pets/{petId}: 62 | get: 63 | summary: Info for a specific pet 64 | operationId: showPetById 65 | tags: 66 | - pets 67 | parameters: 68 | - name: petId 69 | in: path 70 | required: true 71 | description: The id of the pet to retrieve 72 | schema: 73 | type: string 74 | responses: 75 | '200': 76 | description: Expected response to a valid request 77 | content: 78 | application/json: 79 | schema: 80 | $ref: "#/components/schemas/Pet" 81 | default: 82 | description: unexpected error 83 | content: 84 | application/json: 85 | schema: 86 | $ref: "#/components/schemas/Error" 87 | components: 88 | schemas: 89 | Pet: 90 | type: object 91 | required: 92 | - id 93 | - name 94 | properties: 95 | id: 96 | type: integer 97 | format: int64 98 | name: 99 | type: string 100 | tag: 101 | type: string 102 | Pets: 103 | type: array 104 | items: 105 | $ref: "#/components/schemas/Pet" 106 | Error: 107 | type: object 108 | required: 109 | - code 110 | - message 111 | properties: 112 | code: 113 | type: integer 114 | format: int32 115 | message: 116 | type: string -------------------------------------------------------------------------------- /specs/base-exclude-elements.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore API 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets data 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 1000) 20 | required: false 21 | schema: 22 | type: integer 23 | format: int32 24 | responses: 25 | '200': 26 | description: A paged array of pets 27 | headers: 28 | x-next: 29 | description: A link to the next page of responses 30 | schema: 31 | type: string 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pets" 36 | default: 37 | description: unexpected error 38 | content: 39 | application/json: 40 | schema: 41 | $ref: "#/components/schemas/Error" 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | '201': 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | content: 53 | application/json: 54 | schema: 55 | $ref: "#/components/schemas/Error" 56 | /pets/{petId}: 57 | get: 58 | summary: Info for a specific pet 59 | operationId: showPetById 60 | tags: 61 | - pets 62 | parameters: 63 | - name: petId 64 | in: path 65 | required: true 66 | description: The id of the pet to retrieve 67 | schema: 68 | type: string 69 | responses: 70 | '200': 71 | description: Expected response to a valid request 72 | content: 73 | application/json: 74 | schema: 75 | $ref: "#/components/schemas/Pet" 76 | default: 77 | description: unexpected error 78 | content: 79 | application/json: 80 | schema: 81 | $ref: "#/components/schemas/Error" 82 | components: 83 | schemas: 84 | Pet: 85 | type: object 86 | required: 87 | - id 88 | - name 89 | properties: 90 | id: 91 | type: integer 92 | format: int64 93 | name: 94 | type: string 95 | tag: 96 | type: string 97 | Pets: 98 | type: array 99 | items: 100 | $ref: "#/components/schemas/Pet" 101 | Error: 102 | type: object 103 | required: 104 | - code 105 | - message 106 | properties: 107 | code: 108 | type: integer 109 | format: int32 110 | message: 111 | type: string -------------------------------------------------------------------------------- /specs/base.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | format: int32 24 | responses: 25 | '200': 26 | description: A paged array of pets 27 | headers: 28 | x-next: 29 | description: A link to the next page of responses 30 | schema: 31 | type: string 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pets" 36 | default: 37 | description: unexpected error 38 | content: 39 | application/json: 40 | schema: 41 | $ref: "#/components/schemas/Error" 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | '201': 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | content: 53 | application/json: 54 | schema: 55 | $ref: "#/components/schemas/Error" 56 | /pets/{petId}: 57 | get: 58 | summary: Info for a specific pet 59 | operationId: showPetById 60 | tags: 61 | - pets 62 | parameters: 63 | - name: petId 64 | in: path 65 | required: true 66 | description: The id of the pet to retrieve 67 | schema: 68 | type: string 69 | responses: 70 | '200': 71 | description: Expected response to a valid request 72 | content: 73 | application/json: 74 | schema: 75 | $ref: "#/components/schemas/Pet" 76 | default: 77 | description: unexpected error 78 | content: 79 | application/json: 80 | schema: 81 | $ref: "#/components/schemas/Error" 82 | components: 83 | schemas: 84 | Pet: 85 | type: object 86 | required: 87 | - id 88 | - name 89 | properties: 90 | id: 91 | type: integer 92 | format: int64 93 | name: 94 | type: string 95 | tag: 96 | type: string 97 | Pets: 98 | type: array 99 | items: 100 | $ref: "#/components/schemas/Pet" 101 | Error: 102 | type: object 103 | required: 104 | - code 105 | - message 106 | properties: 107 | code: 108 | type: integer 109 | format: int32 110 | message: 111 | type: string -------------------------------------------------------------------------------- /specs/glob/base/base.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | format: int32 24 | responses: 25 | '200': 26 | description: A paged array of pets 27 | headers: 28 | x-next: 29 | description: A link to the next page of responses 30 | schema: 31 | type: string 32 | content: 33 | application/json: 34 | schema: 35 | $ref: "#/components/schemas/Pets" 36 | default: 37 | description: unexpected error 38 | content: 39 | application/json: 40 | schema: 41 | $ref: "#/components/schemas/Error" 42 | post: 43 | summary: Create a pet 44 | operationId: createPets 45 | tags: 46 | - pets 47 | responses: 48 | '201': 49 | description: Null response 50 | default: 51 | description: unexpected error 52 | content: 53 | application/json: 54 | schema: 55 | $ref: "#/components/schemas/Error" 56 | /pets/{petId}: 57 | get: 58 | summary: Info for a specific pet 59 | operationId: showPetById 60 | tags: 61 | - pets 62 | parameters: 63 | - name: petId 64 | in: path 65 | required: true 66 | description: The id of the pet to retrieve 67 | schema: 68 | type: string 69 | responses: 70 | '200': 71 | description: Expected response to a valid request 72 | content: 73 | application/json: 74 | schema: 75 | $ref: "#/components/schemas/Pet" 76 | default: 77 | description: unexpected error 78 | content: 79 | application/json: 80 | schema: 81 | $ref: "#/components/schemas/Error" 82 | components: 83 | schemas: 84 | Pet: 85 | type: object 86 | required: 87 | - id 88 | - name 89 | properties: 90 | id: 91 | type: integer 92 | format: int64 93 | name: 94 | type: string 95 | tag: 96 | type: string 97 | Pets: 98 | type: array 99 | items: 100 | $ref: "#/components/schemas/Pet" 101 | Error: 102 | type: object 103 | required: 104 | - code 105 | - message 106 | properties: 107 | code: 108 | type: integer 109 | format: int32 110 | message: 111 | type: string -------------------------------------------------------------------------------- /specs/glob/revision/revision-breaking.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | post: 12 | summary: Create a pet 13 | operationId: createPets 14 | tags: 15 | - pets 16 | responses: 17 | '201': 18 | description: Null response 19 | default: 20 | description: unexpected error 21 | content: 22 | application/json: 23 | schema: 24 | $ref: "#/components/schemas/Error" 25 | /pets/{petId}: 26 | get: 27 | summary: Info for a specific pet 28 | operationId: showPetById 29 | tags: 30 | - pets 31 | parameters: 32 | - name: petId 33 | in: path 34 | required: true 35 | description: The id of the pet to retrieve 36 | schema: 37 | type: string 38 | responses: 39 | '200': 40 | description: Expected response to a valid request 41 | content: 42 | application/json: 43 | schema: 44 | $ref: "#/components/schemas/Pet" 45 | default: 46 | description: unexpected error 47 | content: 48 | application/json: 49 | schema: 50 | $ref: "#/components/schemas/Error" 51 | components: 52 | schemas: 53 | Pet: 54 | type: object 55 | required: 56 | - id 57 | - name 58 | properties: 59 | id: 60 | type: integer 61 | format: int64 62 | name: 63 | type: string 64 | tag: 65 | type: string 66 | Pets: 67 | type: array 68 | items: 69 | $ref: "#/components/schemas/Pet" 70 | Error: 71 | type: object 72 | required: 73 | - code 74 | - message 75 | properties: 76 | code: 77 | type: integer 78 | format: int32 79 | message: 80 | type: string -------------------------------------------------------------------------------- /specs/petstore-base.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | maximum: 100 24 | format: int32 25 | responses: 26 | '200': 27 | description: A paged array of pets 28 | headers: 29 | x-next: 30 | description: A link to the next page of responses 31 | schema: 32 | type: string 33 | content: 34 | application/json: 35 | schema: 36 | $ref: "#/components/schemas/Pets" 37 | default: 38 | description: unexpected error 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Error" 43 | post: 44 | summary: Create a pet 45 | operationId: createPets 46 | tags: 47 | - pets 48 | requestBody: 49 | content: 50 | application/json: 51 | schema: 52 | $ref: '#/components/schemas/Pet' 53 | required: true 54 | responses: 55 | '201': 56 | description: Null response 57 | default: 58 | description: unexpected error 59 | content: 60 | application/json: 61 | schema: 62 | $ref: "#/components/schemas/Error" 63 | /pets/{petId}: 64 | get: 65 | summary: Info for a specific pet 66 | operationId: showPetById 67 | tags: 68 | - pets 69 | parameters: 70 | - name: petId 71 | in: path 72 | required: true 73 | description: The id of the pet to retrieve 74 | schema: 75 | type: string 76 | responses: 77 | '200': 78 | description: Expected response to a valid request 79 | content: 80 | application/json: 81 | schema: 82 | $ref: "#/components/schemas/Pet" 83 | default: 84 | description: unexpected error 85 | content: 86 | application/json: 87 | schema: 88 | $ref: "#/components/schemas/Error" 89 | components: 90 | schemas: 91 | Pet: 92 | type: object 93 | required: 94 | - id 95 | - name 96 | properties: 97 | id: 98 | type: integer 99 | format: int64 100 | name: 101 | type: string 102 | tag: 103 | type: string 104 | Pets: 105 | type: array 106 | maxItems: 100 107 | items: 108 | $ref: "#/components/schemas/Pet" 109 | Error: 110 | type: object 111 | required: 112 | - code 113 | - message 114 | properties: 115 | code: 116 | type: integer 117 | format: int32 118 | message: 119 | type: string 120 | -------------------------------------------------------------------------------- /specs/petstore-revision.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | get: 12 | summary: List all pets 13 | operationId: listPets 14 | tags: 15 | - pets 16 | parameters: 17 | - name: limit 18 | in: query 19 | description: How many items to return at one time (max 100) 20 | required: false 21 | schema: 22 | type: integer 23 | maximum: 100 24 | format: int32 25 | responses: 26 | '200': 27 | description: A paged array of pets 28 | headers: 29 | x-next: 30 | description: A link to the next page of responses 31 | schema: 32 | type: string 33 | content: 34 | application/json: 35 | schema: 36 | $ref: "#/components/schemas/Pets" 37 | default: 38 | description: unexpected error 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/components/schemas/Error" 43 | post: 44 | summary: Create a pet 45 | operationId: createPets 46 | tags: 47 | - pets 48 | requestBody: 49 | content: 50 | application/json: 51 | schema: 52 | $ref: '#/components/schemas/Pet' 53 | required: true 54 | responses: 55 | '201': 56 | description: Null response 57 | default: 58 | description: unexpected error 59 | content: 60 | application/json: 61 | schema: 62 | $ref: "#/components/schemas/Error" 63 | /pets/{petId}: 64 | get: 65 | summary: Info for a specific pet 66 | operationId: showPetById 67 | tags: 68 | - pets 69 | parameters: 70 | - name: petId 71 | in: path 72 | required: true 73 | description: The id of the pet to retrieve 74 | schema: 75 | type: string 76 | responses: 77 | '200': 78 | description: Expected response to a valid request 79 | content: 80 | application/json: 81 | schema: 82 | $ref: "#/components/schemas/Pet" 83 | default: 84 | description: unexpected error 85 | content: 86 | application/json: 87 | schema: 88 | $ref: "#/components/schemas/Error" 89 | components: 90 | schemas: 91 | Pet: 92 | type: object 93 | required: 94 | - id 95 | - tag2 96 | properties: 97 | id: 98 | type: integer 99 | format: int64 100 | name: 101 | type: string 102 | tag2: 103 | type: string 104 | Pets: 105 | type: array 106 | maxItems: 100 107 | items: 108 | $ref: "#/components/schemas/Pet" 109 | Error: 110 | type: object 111 | required: 112 | - code 113 | properties: 114 | code: 115 | type: integer 116 | format: int32 117 | message: 118 | type: string 119 | -------------------------------------------------------------------------------- /specs/revision-breaking-warn.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /healthcheck: 11 | get: 12 | summary: Health Check 13 | description: >- 14 | The healthcheck endpoint provides detailed information about the health 15 | of a web service. If each of the components required by the service are 16 | healthy, then the service is considered healthy and will return a 200 OK 17 | response. If any of the components needed by the service are unhealthy, 18 | then a 503 Service Unavailable response will be provided. 19 | responses: 20 | '200': 21 | description: Health Check report 22 | /pets: 23 | get: 24 | summary: List all pets 25 | operationId: listPets 26 | tags: 27 | - pets 28 | parameters: 29 | - name: limit 30 | in: query 31 | description: How many items to return at one time (max 100) 32 | required: false 33 | schema: 34 | type: integer 35 | format: int32 36 | responses: 37 | '200': 38 | description: A paged array of pets 39 | headers: 40 | x-next: 41 | description: A link to the next page of responses 42 | schema: 43 | type: string 44 | content: 45 | application/json: 46 | schema: 47 | $ref: "#/components/schemas/Pets" 48 | default: 49 | description: unexpected error 50 | content: 51 | application/json: 52 | schema: 53 | $ref: "#/components/schemas/Error" 54 | post: 55 | summary: Create a pet 56 | operationId: createPets 57 | tags: 58 | - pets 59 | responses: 60 | '201': 61 | description: Null response 62 | default: 63 | description: unexpected error 64 | content: 65 | application/json: 66 | schema: 67 | $ref: "#/components/schemas/Error" 68 | /pets/{petId}: 69 | get: 70 | summary: Info for a specific pet 71 | operationId: showPetById 72 | tags: 73 | - pets 74 | parameters: 75 | - name: petId 76 | in: path 77 | required: true 78 | description: The id of the pet to retrieve 79 | schema: 80 | type: string 81 | responses: 82 | '200': 83 | description: Expected response to a valid request 84 | content: 85 | application/json: 86 | schema: 87 | $ref: "#/components/schemas/Pet" 88 | default: 89 | description: unexpected error 90 | content: 91 | application/json: 92 | schema: 93 | $ref: "#/components/schemas/Error" 94 | components: 95 | schemas: 96 | Pet: 97 | type: object 98 | required: 99 | - id 100 | - name 101 | properties: 102 | id: 103 | type: integer 104 | format: int64 105 | name: 106 | type: string 107 | Pets: 108 | type: array 109 | items: 110 | $ref: "#/components/schemas/Pet" 111 | Error: 112 | type: object 113 | required: 114 | - code 115 | - message 116 | properties: 117 | code: 118 | type: integer 119 | format: int32 120 | message: 121 | type: string -------------------------------------------------------------------------------- /specs/revision-breaking.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /pets: 11 | post: 12 | summary: Create a pet 13 | operationId: createPets 14 | tags: 15 | - pets 16 | responses: 17 | '201': 18 | description: Null response 19 | default: 20 | description: unexpected error 21 | content: 22 | application/json: 23 | schema: 24 | $ref: "#/components/schemas/Error" 25 | /pets/{petId}: 26 | get: 27 | summary: Info for a specific pet 28 | operationId: showPetById 29 | tags: 30 | - pets 31 | parameters: 32 | - name: petId 33 | in: path 34 | required: true 35 | description: The id of the pet to retrieve 36 | schema: 37 | type: string 38 | responses: 39 | '200': 40 | description: Expected response to a valid request 41 | content: 42 | application/json: 43 | schema: 44 | $ref: "#/components/schemas/Pet" 45 | default: 46 | description: unexpected error 47 | content: 48 | application/json: 49 | schema: 50 | $ref: "#/components/schemas/Error" 51 | components: 52 | schemas: 53 | Pet: 54 | type: object 55 | required: 56 | - id 57 | - name 58 | properties: 59 | id: 60 | type: integer 61 | format: int64 62 | name: 63 | type: string 64 | tag: 65 | type: string 66 | Pets: 67 | type: array 68 | items: 69 | $ref: "#/components/schemas/Pet" 70 | Error: 71 | type: object 72 | required: 73 | - code 74 | - message 75 | properties: 76 | code: 77 | type: integer 78 | format: int32 79 | message: 80 | type: string -------------------------------------------------------------------------------- /specs/revision.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.0" 2 | info: 3 | version: 1.0.0 4 | title: Swagger Petstore 5 | license: 6 | name: MIT 7 | servers: 8 | - url: http://petstore.swagger.io/v1 9 | paths: 10 | /healthcheck: 11 | get: 12 | summary: Health Check 13 | description: >- 14 | The healthcheck endpoint provides detailed information about the health 15 | of a web service. If each of the components required by the service are 16 | healthy, then the service is considered healthy and will return a 200 OK 17 | response. If any of the components needed by the service are unhealthy, 18 | then a 503 Service Unavailable response will be provided. 19 | responses: 20 | '200': 21 | description: Health Check report 22 | /pets: 23 | get: 24 | summary: List all pets 25 | operationId: listPets 26 | tags: 27 | - pets 28 | parameters: 29 | - name: limit 30 | in: query 31 | description: How many items to return at one time (max 100) 32 | required: false 33 | schema: 34 | type: integer 35 | format: int32 36 | responses: 37 | '200': 38 | description: A paged array of pets 39 | headers: 40 | x-next: 41 | description: A link to the next page of responses 42 | schema: 43 | type: string 44 | content: 45 | application/json: 46 | schema: 47 | $ref: "#/components/schemas/Pets" 48 | default: 49 | description: unexpected error 50 | content: 51 | application/json: 52 | schema: 53 | $ref: "#/components/schemas/Error" 54 | post: 55 | summary: Create a pet 56 | operationId: createPets 57 | tags: 58 | - pets 59 | responses: 60 | '201': 61 | description: Null response 62 | default: 63 | description: unexpected error 64 | content: 65 | application/json: 66 | schema: 67 | $ref: "#/components/schemas/Error" 68 | /pets/{petId}: 69 | get: 70 | summary: Info for a specific pet 71 | operationId: showPetById 72 | tags: 73 | - pets 74 | parameters: 75 | - name: petId 76 | in: path 77 | required: true 78 | description: The id of the pet to retrieve 79 | schema: 80 | type: string 81 | responses: 82 | '200': 83 | description: Expected response to a valid request 84 | content: 85 | application/json: 86 | schema: 87 | $ref: "#/components/schemas/Pet" 88 | default: 89 | description: unexpected error 90 | content: 91 | application/json: 92 | schema: 93 | $ref: "#/components/schemas/Error" 94 | components: 95 | schemas: 96 | Pet: 97 | type: object 98 | required: 99 | - id 100 | - name 101 | properties: 102 | id: 103 | type: integer 104 | format: int64 105 | name: 106 | type: string 107 | tag: 108 | type: string 109 | Pets: 110 | type: array 111 | items: 112 | $ref: "#/components/schemas/Pet" 113 | Error: 114 | type: object 115 | required: 116 | - code 117 | - message 118 | properties: 119 | code: 120 | type: integer 121 | format: int32 122 | message: 123 | type: string --------------------------------------------------------------------------------