Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 95 additions & 49 deletions AutoGuard.gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,49 @@ spec:
head_ref:
type: string
default: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
fail_on_breaking:
type: string
default: "true"
description: "If true, pipeline fails on breaking changes. If false, breaking changes are reported and then passed"
---

.autoGuard:
image: "docker"
image: "docker:latest"
services:
- docker:dind

variables:
DOCKER_DRIVER: overlay2

before_script:
- docker pull alexx882/auto-oas:1.2
- docker pull openapitools/openapi-diff:latest
- docker pull djamn/openapi-diff:latest
- apk add --no-cache git
script:
- git fetch
- git fetch --all

- mkdir -p autooas-base
- mkdir -p autooas-head
- chmod -R 777 autooas-base autooas-head

- git checkout $[[inputs.base_ref]]
- docker run -v $[[ inputs.source_dir ]]:/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.base_ref]]/oas
- echo "Running Base Analysis..."

- git checkout $[[inputs.head_ref]]
- docker run -v $[[ inputs.source_dir ]]:/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.head_ref]]/oas
- |
if [ -d "$[[ inputs.source_dir ]]" ]; then
docker run -v "$(pwd):/project" alexx882/auto-oas:1.2 "/project/$[[ inputs.source_dir ]]" /project/autooas-base/openapi
else
echo "Directory '$[[ inputs.source_dir ]]' not found in base ref, treating as new project."
fi

- git checkout $[[inputs.head_ref]]
- echo "Running Head Analysis..."
- docker run -v "$(pwd):/project" alexx882/auto-oas:1.2 "/project/$[[ inputs.source_dir ]]" /project/autooas-head/openapi

- |
OLD_DIR=autooas-$[[inputs.base_ref]]
NEW_DIR=autooas-$[[inputs.head_ref]]
OLD_DIR=autooas-base
NEW_DIR=autooas-head

set +e
EMPTY_OAS='{ "openapi" : "3.0.1", "info" : { "title" : "", "description" : "Spring Profile: ???", "version" : "" }, "paths" : { }, "components" : { "schemas" : { } }}'

EMPTY_OAS='{ "openapi": "3.0.1", "info": { "title": "", "version": "" }, "paths": {}, "components": { "schemas": {} } }'
echo $EMPTY_OAS > empty.json

OLD_FILES=$(find "$OLD_DIR" -type f | sed "s|$OLD_DIR/||" | sort)
Expand All @@ -46,56 +62,86 @@ spec:
OTHER_FILES=$(comm -3 old_files new_files)

STATUS=0

mkdir oas_diff

for p in $COMMON_FILES; do
printf "\x20\n\x20\nAnalyzing existing configuration $p\n"
docker run --rm -t \
-v $(pwd):/specs \
openapitools/openapi-diff:latest --fail-on-incompatible --html "/specs/oas_diff/$p.html" /specs/$OLD_DIR/$p /specs/$NEW_DIR/$p

mkdir -p oas_diff

run_diff() {
local name=$1
local old_path=$2
local new_path=$3

echo "Diffing $name..."

set +e

STATE=$(docker run --rm \
-v "$(pwd):/specs" \
openapitools/openapi-diff:latest \
--state \
--fail-on-incompatible \
--html "/specs/oas_diff/$name.html" \
--markdown "/specs/oas_diff/$name.md" \
"/specs/$old_path" "/specs/$new_path" 2>/dev/null)

EXIT_CODE=$?
if [ $EXIT_CODE -eq 1 ]; then
echo -e "\e[31mBreaking changes detected in profile $p\033[37m"

STATE=$(echo "$STATE" | tr -d '\r')

if [ "$STATE" == "no_changes" ]; then
echo "No changes detected. Removing report files."
rm -f "oas_diff/$name.html"
rm -f "oas_diff/$name.md"
fi

set -e

if [ $EXIT_CODE -ne 0 ] || [ "$STATE" == "incompatible" ]; then
echo -e "\e[31mBreaking change detected in $name\e[0m"
return 1
fi

if [ "$STATE" == "compatible" ]; then
echo -e "\e[33mCompatible changes detected in $name\e[0m"
return 0
fi
STATUS=$((STATUS + EXIT_CODE))

return 0
}

if [ -z "$COMMON_FILES" ] && [ -z "$OTHER_FILES" ]; then
echo "ERROR: No OpenAPI files were generated. Analysis failed."
exit 1
fi

for p in $COMMON_FILES; do
run_diff "$p" "$OLD_DIR/$p" $NEW_DIR/$p || STATUS=$((STATUS + 1))
done

for p in $OTHER_FILES; do
if [ -f "$OLD_DIR/$p" ]; then
printf "\x20\n\x20\nAnalyzing deleted configuration $p\n"
docker run --rm -t \
-v $(pwd):/specs \
openapitools/openapi-diff:latest --fail-on-incompatible --html "/specs/oas_diff/$p.html" /specs/$OLD_DIR/$p /specs/empty.json
EXIT_CODE=$?
if [ $EXIT_CODE -eq 1 ]; then
echo -e "\e[31mBreaking changes detected in profile $p\033[37m"
fi
STATUS=$((STATUS + EXIT_CODE))
run_diff "$p" "$OLD_DIR/$p" "empty.json" || STATUS=$((STATUS + 1))
else
printf "\x20\n\x20\nAnalyzing added configuration $p\n"
docker run --rm -t \
-v $(pwd):/specs \
openapitools/openapi-diff:latest --fail-on-incompatible --html "/specs/oas_diff/$p.html" /specs/empty.json /specs/$NEW_DIR/$p
EXIT_CODE=$?
if [ $EXIT_CODE -eq 1 ]; then
echo -e "\e[31mBreaking changes detected in profile $p\033[37m"
fi
STATUS=$((STATUS + EXIT_CODE))
run_diff "$p" "empty.json" "$NEW_DIR/$p" || STATUS=$((STATUS + 1))
fi
done

set -e

if [ $STATUS -gt 0 ]; then
echo -e "\e[31mBreaking changes detected"
exit 1
if [ $STATUS -gt 0 ]; then
if [ "$[[ inputs.fail_on_breaking ]]" = "true" ]; then
echo "Fail on breaking is ENABLED. Failing job."
exit 1
else
echo "Fail on breaking is DISABLED. Job passes with warnings."
exit 0
fi
else
echo -e "\e[32mNo breaking changes found.\e[0m"
exit 0
fi

artifacts:
when: always
name: "OpenAPI specifications"
paths:
- "autooas-$[[inputs.base_ref]]/oas*"
- "autooas-$[[inputs.head_ref]]/oas*"
- "oas_diff/*"
- "autooas-base/*.json"
- "autooas-head/*.json"
- "oas_diff/*"
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ AutoGuard is a tool that automatically detects breaking changes of REST APIs in

We provide an example project with AutoGuard set up [on GitHub](https://github.com/MSA-API-Management/AutoGuard-example-project) and a demonstration video [on YouTube](https://www.youtube.com/watch?v=3qeWIVfMvWE).

## AutoGuard v1.2 now supports JAX-RS
Use `MSA-API-Management/AutoGuard@v1.2` to detect breaking changes of REST APIs developed with JAX-RS.
## AutoGuard v2
Version 2 introduces updates to the underlying analysis logic, enhanced markdown reporting, and brings the `fail_on_breaking` toggle to GitLab CI/CD templates.
*(Note: As a minor breaking change, generated OpenAPI specifications are now stored in static `autooas-base` and `autooas-head` artifact directories rather than dynamically named branch folders).*

## AutoGuard v1.2
AutoGuard now supports JAX-RS. Use `MSA-API-Management/AutoGuard@v1.2` to detect breaking changes of REST APIs developed with JAX-RS.

## GitHub action
The action uses AutoGuard-gen (currently implemented with [AutoOAS](https://github.com/MSA-API-Management/AutoOAS-action)) and [AutoGuard-diff](https://github.com/MSA-API-Management/AutoGuard-diff-action) to find breaking REST API changes in Java Spring Boot web services.

### Usage
~~~yml
- uses: MSA-API-Management/AutoGuard@v1
- uses: MSA-API-Management/AutoGuard@v2
with:
# Path to the Maven source directory
# default: '${{github.workspace}}'
Expand All @@ -22,6 +26,10 @@ The action uses AutoGuard-gen (currently implemented with [AutoOAS](https://gith
# The branch, tag or commit SHA of the old API version
# default: '${{github.head_ref}}' (Head branch reference of a pull request)
head_ref:
# If true, the workflow fails when breaking changes are detected.
# If false, breaking changes are reported but the workflow succeeds.
# default: 'true'
fail_on_breaking:
~~~

## GitLab template
Expand All @@ -30,7 +38,7 @@ The template implements the AutoGuard-spec (again implemented with [AutoOAS](htt
### Usage
~~~yml
include:
- remote: 'https://raw.githubusercontent.com/MSA-API-Management/AutoGuard/refs/tags/v1/AutoGuard.gitlab-ci.yml'
- remote: 'https://raw.githubusercontent.com/MSA-API-Management/AutoGuard/refs/tags/v2/AutoGuard.gitlab-ci.yml'
inputs:
source_dir: "."

Expand Down