From 5a1a09b87e99f0ca98ebbc8924f9a61cd23542f6 Mon Sep 17 00:00:00 2001 From: djamn Date: Thu, 8 Jan 2026 17:47:56 +0100 Subject: [PATCH 1/9] Reworked autoguard script Added helper function to remove duplicated code, added flag to continue ci with warnings if there are differences and provide markdown openapi diff in artifacts --- AutoGuard.gitlab-ci.yml | 99 +++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index c20299b..3d459ca 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -7,31 +7,38 @@ spec: head_ref: type: string default: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME + fail_on_breaking: + type: boolean + 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 + - apk add --no-cache git script: - - git fetch + - git fetch --all - git checkout $[[inputs.base_ref]] - - docker run -v $[[ inputs.source_dir ]]:/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.base_ref]]/oas + - docker run -v "$(pwd)/$[[ inputs.source_dir ]]":/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.base_ref]]/oas - git checkout $[[inputs.head_ref]] - - docker run -v $[[ inputs.source_dir ]]:/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.head_ref]]/oas + - docker run -v "$(pwd)/$[[ inputs.source_dir ]]":/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.head_ref]]/oas - | OLD_DIR=autooas-$[[inputs.base_ref]] NEW_DIR=autooas-$[[inputs.head_ref]] - set +e + # set +e EMPTY_OAS='{ "openapi" : "3.0.1", "info" : { "title" : "", "description" : "Spring Profile: ???", "version" : "" }, "paths" : { }, "components" : { "schemas" : { } }}' echo $EMPTY_OAS > empty.json @@ -46,50 +53,64 @@ spec: OTHER_FILES=$(comm -3 old_files new_files) STATUS=0 + + mkdir -p oas_diff + + run_diff() { + local name=$1 + local old_path=$2 + local new_path=$3 + + echo "Diffing $name..." + + set +e + + docker run --rm \ + -v "$(pwd):/specs" \ + openapitools/openapi-diff:latest \ + --fail-on-incompatible \ + --html "/specs/oas_diff/$name.html" \ + --markdown "/specs/oas_diff/$name.md" \ + "/specs/$old_path" "/specs/$new_path" + + EXIT_CODE=$? + + set -e + + if [ $EXIT_CODE -ne 0 ]; then + echo -e "\e[31mBreaking change detected in $name\e[0m" + return 1 + fi + return 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 - 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" $NEW_DIR/$p + STATUS=$((STATUS + $?)) 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" 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" fi + STATUS=$((STATUS + $?)) done - - set -e - if [ $STATUS -gt 0 ]; then - echo -e "\e[31mBreaking changes detected" - exit 1 + if [ $STATUS -gt 0 ]; then + echo -e "\e[31mTotal breaking changes: $STATUS\e[0m" + 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: From fbca01b3930404493dc406b329ba9d8ead3bb3ff Mon Sep 17 00:00:00 2001 From: djamn Date: Thu, 8 Jan 2026 17:48:33 +0100 Subject: [PATCH 2/9] small cleanup --- AutoGuard.gitlab-ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index 3d459ca..cbefc1b 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -38,9 +38,7 @@ spec: OLD_DIR=autooas-$[[inputs.base_ref]] NEW_DIR=autooas-$[[inputs.head_ref]] - # set +e EMPTY_OAS='{ "openapi" : "3.0.1", "info" : { "title" : "", "description" : "Spring Profile: ???", "version" : "" }, "paths" : { }, "components" : { "schemas" : { } }}' - echo $EMPTY_OAS > empty.json OLD_FILES=$(find "$OLD_DIR" -type f | sed "s|$OLD_DIR/||" | sort) From 8e95fea3ce1da7131c0e1b26b14518b83687c04c Mon Sep 17 00:00:00 2001 From: djamn Date: Thu, 8 Jan 2026 18:37:25 +0100 Subject: [PATCH 3/9] use string instead of boolean --- AutoGuard.gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index cbefc1b..cb12734 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -8,8 +8,8 @@ spec: type: string default: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME fail_on_breaking: - type: boolean - default: true + type: string + default: "true" description: "If true, pipeline fails on breaking changes. If false, breaking changes are reported and then passed" --- From 6624544bafa29c33787fd25948cf03c71dc21189 Mon Sep 17 00:00:00 2001 From: djamn Date: Fri, 9 Jan 2026 12:34:48 +0100 Subject: [PATCH 4/9] use static folder names --- AutoGuard.gitlab-ci.yml | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index cb12734..8247abc 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -27,18 +27,24 @@ spec: script: - 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 "$(pwd)/$[[ 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 "$(pwd)/$[[ inputs.source_dir ]]":/project alexx882/auto-oas:1.2 /project /project/autooas-$[[inputs.head_ref]]/oas + - docker run -v "$(pwd):/project" alexx882/auto-oas:1.2 "/project/$[[ inputs.source_dir ]]" /project/autooas-base/openapi + - 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 - 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) @@ -82,7 +88,11 @@ spec: 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 + $?)) @@ -99,7 +109,7 @@ spec: if [ $STATUS -gt 0 ]; then echo -e "\e[31mTotal breaking changes: $STATUS\e[0m" - if [[ "$[[ inputs.fail_on_breaking ]]" == "true" ]]; then + if [ "$[[ inputs.fail_on_breaking ]]" = "true" ]; then echo "Fail on breaking is ENABLED. Failing job." exit 1 else @@ -115,6 +125,6 @@ spec: 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/*" \ No newline at end of file From 7d3578099ba59ad3a657f97a71e107b55590b616 Mon Sep 17 00:00:00 2001 From: djamn Date: Fri, 9 Jan 2026 12:35:33 +0100 Subject: [PATCH 5/9] extract state from openapi analysis --- AutoGuard.gitlab-ci.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index 8247abc..89b3c5c 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -69,16 +69,25 @@ spec: set +e - docker run --rm \ + 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" + "/specs/$old_path" "/specs/$new_path" 2>/dev/null) EXIT_CODE=$? + 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 ]; then From 39df8398cafc5e2f1292489e31714498a15f5900 Mon Sep 17 00:00:00 2001 From: djamn Date: Fri, 9 Jan 2026 12:48:59 +0100 Subject: [PATCH 6/9] added state checking and handle return of statuscode 1 without crashing --- AutoGuard.gitlab-ci.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index 89b3c5c..fe6de4c 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -90,10 +90,16 @@ spec: set -e - if [ $EXIT_CODE -ne 0 ]; then + 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 + return 0 } @@ -103,17 +109,15 @@ spec: fi for p in $COMMON_FILES; do - run_diff "$p" "$OLD_DIR/$p" $NEW_DIR/$p - STATUS=$((STATUS + $?)) + 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 - run_diff "$p" "$OLD_DIR/$p" "empty.json" + run_diff "$p" "$OLD_DIR/$p" "empty.json" || STATUS=$((STATUS + 1)) else - run_diff "$p" "empty.json" "$NEW_DIR/$p" + run_diff "$p" "empty.json" "$NEW_DIR/$p" || STATUS=$((STATUS + 1)) fi - STATUS=$((STATUS + $?)) done if [ $STATUS -gt 0 ]; then From 3c14c00e9b653d61bec9d275dc18987a836a599a Mon Sep 17 00:00:00 2001 From: djamn Date: Fri, 9 Jan 2026 12:50:59 +0100 Subject: [PATCH 7/9] removed total breaking changes --- AutoGuard.gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index fe6de4c..c1fdcb5 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -121,7 +121,6 @@ spec: done if [ $STATUS -gt 0 ]; then - echo -e "\e[31mTotal breaking changes: $STATUS\e[0m" if [ "$[[ inputs.fail_on_breaking ]]" = "true" ]; then echo "Fail on breaking is ENABLED. Failing job." exit 1 From fbed8c78050ff73dd827b2c1ad76ef7e0c04edad Mon Sep 17 00:00:00 2001 From: djamn Date: Wed, 21 Jan 2026 13:03:16 +0100 Subject: [PATCH 8/9] added check if project did not exist in base commit --- AutoGuard.gitlab-ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index c1fdcb5..8009248 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -34,7 +34,12 @@ spec: - git checkout $[[inputs.base_ref]] - echo "Running Base Analysis..." - - docker run -v "$(pwd):/project" alexx882/auto-oas:1.2 "/project/$[[ inputs.source_dir ]]" /project/autooas-base/openapi + - | + 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..." From 006c0323f775bc2db78e43438eedc8509352ec94 Mon Sep 17 00:00:00 2001 From: djamn Date: Wed, 28 Jan 2026 11:22:37 +0100 Subject: [PATCH 9/9] use own openapi diff image to fix some issues --- AutoGuard.gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoGuard.gitlab-ci.yml b/AutoGuard.gitlab-ci.yml index 8009248..708b550 100644 --- a/AutoGuard.gitlab-ci.yml +++ b/AutoGuard.gitlab-ci.yml @@ -22,7 +22,7 @@ spec: 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 --all