Skip to content

Instantly share code, notes, and snippets.

@tsimbalar
Last active March 4, 2024 01:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsimbalar/000f1e9ed04357e3d626a436ea9e1a58 to your computer and use it in GitHub Desktop.
Save tsimbalar/000f1e9ed04357e3d626a436ea9e1a58 to your computer and use it in GitHub Desktop.
Open API Diff breaking changes - GitHub Actions

I couldn't get https://github.com/evereepay/openapi-diff-action to work for me, so ended up doing it a bit more manually, by invoking directly https://github.com/quen2404/openapi-diff and generating a comment for the PR with https://github.com/actions/github-script

To do that you need :

  • the script check-openapi-diff.sh ... in my case it is in the .ci folder at the root of our repo
  • the GitHub Actions workflow openapi.yaml. It needs to be under the folder .github/workflows of the repo
  • possibly adapt some paths here and there in the openapi.yaml file

If everything goes well, you'll get comments on you PRs such as :


API Diff Report

BREAKING CHANGES ‼️

ℹ️ This is not preventing you from merging, you are an adult.

What's Changed


POST /v1/enrollments
Request:

Changed content type : application/json

New required properties:

  • thisIsANewRequiredProp
  • Added property thisIsANewRequiredProp (boolean)

comparing /home/runner/work/xxxx/xxxx/base/docs/swagger.yaml with /home/runner/work/xxxx/xxxxx/head/docs/swagger.yaml.


or


API Diff Report

CHANGES - non breaking 👌

ℹ️ This is not preventing you from merging, you are an adult.

What's Changed


POST /v2/enrollments
Request:

Changed content type : application/json

  • Added property newOptionalProp (string)

comparing /home/runner/work/xxxx/xxx/base/docs/swagger.yaml with /home/runner/work/xxxx/xxxx/head/docs/swagger.yaml.


or


API Diff Report

NO API changes 👻

ℹ️ This is not preventing you from merging, you are an adult.


comparing /home/runner/work/xxxx/xxxx/base/docs/swagger.yaml with /home/runner/work/xxxx/xxxx/head/docs/swagger.yaml.

#!/bin/sh
set -e
#
# Runs the openapi-diff tool from https://github.com/quen2404/openapi-diff to detect changes against the base branch of the PR
#
# Used in CI pipelines to report possible breaking changes
#
if [ -z "$1" ]; then
echo "🛑You need to provide the original spec file path"
exit 1
fi
if [ -z "$2" ]; then
echo "🛑You need to provide the new spec file path"
exit 1
fi
BASE_SPEC_PATH="$1"
HEAD_SPEC_PATH="$2"
OUTPUT_DIR="$(mktemp -d -t openapi-diff-result-XXXXXXXXXX)"
# Run diff
RESULT=$(docker run --rm -v "$BASE_SPEC_PATH:/base.yaml:ro" -v "$HEAD_SPEC_PATH:/head.yaml:ro" -v "$OUTPUT_DIR:/output" quen2404/openapi-diff /base.yaml /head.yaml --markdown /output/out.md --state)
# result is `no_changes` or `incompatible` or `compatible`
echo "## _API Diff Report_"
echo
if [ "$RESULT" = "incompatible" ]; then
echo "### :x: **BREAKING CHANGES** :bangbang:"
elif [ "$RESULT" = "compatible" ]; then
echo "### :white_check_mark: **CHANGES - non breaking** :ok_hand:"
elif [ "$RESULT" = "no_changes" ]; then
echo "### :white_circle: **NO API changes** :ghost:"
else
echo "### :warning: Unexpected result from diff \`$RESULT\`"
fi
echo
echo ":information_source: This is not preventing you from merging, you are an adult."
echo
cat "$OUTPUT_DIR/out.md"
echo "---"
echo "comparing \`$BASE_SPEC_PATH\` with \`$HEAD_SPEC_PATH\`."
name: openapi
on:
pull_request:
paths:
- 'docs/*.yaml'
jobs:
openapi-diff:
runs-on: ubuntu-20.04
steps:
- name : Print GitHub context (for debug)
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Check out HEAD revision
uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
path: head
- name: Check out BASE revision
uses: actions/checkout@v2
with:
ref: ${{ github.base_ref }}
path: base
- name: Check for OpenAPI changes
id: openapi_diff
run: |
OPEN_API_DIFF_REPORT=$(head/.ci/check-openapi-diff.sh "$(pwd)/base/docs/swagger.yaml" "$(pwd)/head/docs/swagger.yaml")
echo 'DIFF_REPORT_MARKDOWN<<EOF' >> $GITHUB_ENV
echo "$OPEN_API_DIFF_REPORT" >> $GITHUB_ENV # Double quotes are needed to preserve new lines.
echo 'EOF' >> $GITHUB_ENV
- name: Add Diff as PR Comment
uses: actions/github-script@v2.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.DIFF_REPORT_MARKDOWN
})
@HerrNiklasRaab
Copy link

Thanks a lot for the script. Getting a:
/home/runner/work/_temp/4704e061-c75c-432b-8c99-ffb5426ad0c6.sh: line 1: head/brokkoli_backend/scripts/check-openapi-diff.sh: Permission denied

@HerrNiklasRaab
Copy link

Solved it with putting sudo before executing the bash file. Now getting:

Error: Unable to process command '::set-env name=DIFF_REPORT_MARKDOWN::## _API Diff Report_%0A%0A### :x: **BREAKING CHANGES** :bangbang:%0A%0A:information_source: This is not preventing you from merging, you are an adult.%0A%0A#### What's New%0A---%0A%0A##### `POST` /orderLines/add-or-update-orderLine%0A%0A%0A#### What's Changed%0A---%0A%0A##### `GET` /shipments%0A%0A%0A###### Return Type:%0A%0AChanged response : **200 OK**%0A> ok%0A%0A* Changed content type : `application/json`%0A%0A    Changed items (object):%0A%0A    * Added property `orderLines` (array)%0A%0A        Items (object):%0A%0A        * Property `id` (string)%0A%0A        * Property `productId` (string)%0A%0A        * Property `ingredientId` (string)%0A%0A        * Property `ingredientUnitConstraintId` (string)%0A%0A        * Property `quantity` (integer)%0A%0A        * Property `amount` (number)%0A%0A        * Property `productName` (string)%0A%0A        * Property `unit` (string)%0A%0A            Enum values:%0A%0A            * `weight`%0A            * `volume`%0A            * `tablespoon`%0A            * `teaspoon`%0A            * `pieces`%0A            * `basedOnTaste`%0A        * Property `totalAmount` (number)%0A%0A        * Property `isPacked` (boolean)%0A%0A    * Changed property `recipeOrderLines` (array)%0A%0A        Changed items (object):%0A%0A        * Changed property `orderLines` (array)%0A%0A            Changed items (object):%0A%0A            New optional properties:%0A            - `amount`%0A            - `ingredientUnitConstraintId`%0A            - `totalAmount`%0A%0A            * Added property `ingredientId` (string)%0A%0A##### `PUT` /shipment/{shipmentId}/add-or-update-orderLine%0A%0A%0A###### Request:%0A%0AChanged content type : `application/json`%0A%0A* Changed property `orderLines` (array)%0A%0A    Changed items (object):%0A%0A    New optional properties:%0A    - `amount`%0A    - `ingredientUnitConstraintId`%0A    - `totalAmount`%0A%0A    * Added property `ingredientId` (string)%0A%0A##### `GET` /shipments/by-date-range%0A%0A%0A###### Return Type:%0A%0AChanged response : **200 OK**%0A%0A* Changed content type : `application/json`%0A%0A    Changed items (object):%0A%0A    * Added property `orderLines` (array)%0A%0A        Items (object):%0A%0A        * Property `id` (string)%0A%0A        * Property `productId` (string)%0A%0A        * Property `ingredientId` (string)%0A%0A        * Property `ingredientUnitConstraintId` (string)%0A%0A        * Property `quantity` (integer)%0A%0A        * Property `amount` (number)%0A%0A        * Property `productName` (string)%0A%0A        * Property `unit` (string)%0A%0A            Enum values:%0A%0A            * `weight`%0A            * `volume`%0A            * `tablespoon`%0A            * `teaspoon`%0A            * `pieces`%0A            * `basedOnTaste`%0A        * Property `totalAmount` (number)%0A%0A        * Property `isPacked` (boolean)%0A%0A    * Changed property `recipeOrderLines` (array)%0A%0A        Changed items (object):%0A%0A        * Changed property `orderLines` (array)%0A%0A            Changed items (object):%0A%0A            New optional properties:%0A            - `amount`%0A            - `ingredientUnitConstraintId`%0A            - `totalAmount`%0A%0A            * Added property `ingredientId` (string)%0A%0A##### `GET` /recipes/{shipmentId}%0A%0A%0A###### Return Type:%0A%0AChanged response : **200 OK**%0A> ok%0A%0A* Changed content type : `application/json`%0A%0A    Changed items (object):%0A%0A    * Changed property `ingredients` (array)%0A%0A        Changed items (object):%0A%0A        * Added property `ingredientId` (string)%0A%0A##### `GET` /recipes/forSignup%0A%0A%0A###### Return Type:%0A%0AChanged response : **200 OK**%0A> ok%0A%0A* Changed content type : `application/json`%0A%0A    Changed items (object):%0A%0A    * Changed property `ingredients` (array)%0A%0A        Changed items (object):%0A%0A        * Added property `ingredientId` (string)%0A%0A---%0Acomparing `/home/runner/work/brokkoli/brokkoli/base/brokkoli_backend/api.yml` with `/home/runner/work/brokkoli/brokkoli/head/brokkoli_backend/api.yml`.' successfully.
Error: The `set-env` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/

@tsimbalar
Copy link
Author

Oh, I think we had the issue a while ago, and fixed it. I had forgotten about this gist .... I'll update it with our changes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment