From 664713eb7978323f36be59599bb4db1a84774f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20C=C3=A9sar?= Date: Wed, 22 Oct 2025 10:18:41 +0200 Subject: [PATCH 01/13] [CHK-12730][CHK-12731] fix dependabot alerts (#277) * [CHK-12730] fix dependabot #25 (ch.qos.logback:logback-core from 1.5.18 to 1.5.19) * [CHK-12731] fix dependabot #24 (org.springframework:spring-core 6.2.10) --- build.gradle | 10 +++++----- examples/example-spring-boot-starter-web/build.gradle | 5 +++-- .../example-spring-boot-starter-webflux/build.gradle | 5 +++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index be00b8d2..3219328b 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { alias(libs.plugins.nexus.publish) } -ext['spring-framework.version'] = '6.2.10' +ext['spring-framework.version'] = '6.2.11' ext['tomcat.version'] = '11.0.10' ext['netty.version'] = '4.2.6.Final' // Due to security vulnerabilities in 4.125.Final and older @@ -70,11 +70,11 @@ subprojects { // Security constraints constraints { - implementation("org.springframework:spring-web:6.2.10") { - because("versions below 6.2.8 have security vulnerabilities including CVE-2024-38820 - see dependabot #12") + implementation("org.springframework:spring-web:6.2.11") { + because("versions below 6.2.11 have security vulnerabilities including CVE-2024-38820 and CVE-2025-41249 - see dependabot #12, #24") } - implementation("org.springframework:spring-webmvc:6.2.10") { - because("versions below 6.2.10 have Path Traversal Vulnerability CVE-2025-41242 - see dependabot #247") + implementation("org.springframework:spring-webmvc:6.2.11") { + because("versions below 6.2.11 have security vulnerabilities including CVE-2025-41242 and CVE-2025-41249 - see dependabot #24, #247") } implementation("org.apache.tomcat.embed:tomcat-embed-core:11.0.10") { because("versions below 10.1.42 have security vulnerabilities including CVE-2024-56337 - see dependabot #13") diff --git a/examples/example-spring-boot-starter-web/build.gradle b/examples/example-spring-boot-starter-web/build.gradle index e4e6a749..aa15ec56 100644 --- a/examples/example-spring-boot-starter-web/build.gradle +++ b/examples/example-spring-boot-starter-web/build.gradle @@ -6,13 +6,14 @@ plugins { } // Needed for security. See: +// - https://github.com/getyourguide/openapi-validation-java/security/dependabot/25 // - https://github.com/getyourguide/openapi-validation-java/security/dependabot/7 // - https://github.com/getyourguide/openapi-validation-java/security/dependabot/6 // Hopefully with spring-boot 3.4.2+ this won't be needed anymore and can be removed. dependencyManagement { dependencies { - dependency 'ch.qos.logback:logback-core:1.5.18' - dependency 'ch.qos.logback:logback-classic:1.5.18' + dependency 'ch.qos.logback:logback-core:1.5.19' + dependency 'ch.qos.logback:logback-classic:1.5.19' } } diff --git a/examples/example-spring-boot-starter-webflux/build.gradle b/examples/example-spring-boot-starter-webflux/build.gradle index 60e1117d..26ae51a4 100644 --- a/examples/example-spring-boot-starter-webflux/build.gradle +++ b/examples/example-spring-boot-starter-webflux/build.gradle @@ -6,13 +6,14 @@ plugins { } // Needed for security. See: +// - https://github.com/getyourguide/openapi-validation-java/security/dependabot/25 // - https://github.com/getyourguide/openapi-validation-java/security/dependabot/7 // - https://github.com/getyourguide/openapi-validation-java/security/dependabot/6 // Hopefully with spring-boot 3.4.2+ this won't be needed anymore and can be removed. dependencyManagement { dependencies { - dependency 'ch.qos.logback:logback-core:1.5.18' - dependency 'ch.qos.logback:logback-classic:1.5.18' + dependency 'ch.qos.logback:logback-core:1.5.19' + dependency 'ch.qos.logback:logback-classic:1.5.19' } } From be9c7cf700aca7f022ab2024009652d1b4669f7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:47:02 +0100 Subject: [PATCH 02/13] build(deps): bump mockito from 5.19.0 to 5.20.0 (#264) Bumps `mockito` from 5.19.0 to 5.20.0. Updates `org.mockito:mockito-core` from 5.19.0 to 5.20.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.19.0...v5.20.0) Updates `org.mockito:mockito-junit-jupiter` from 5.19.0 to 5.20.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.19.0...v5.20.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-version: 5.20.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.mockito:mockito-junit-jupiter dependency-version: 5.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 22294ec7..be45ec27 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ checkstyle = "8.44" pmd = "7.14.0" jacoco = "0.8.13" # Testing -mockito = "5.19.0" +mockito = "5.20.0" junit-jupiter = "5.13.4" junit-platform = "1.13.4" From c0d79588c2bbbe67d52e9efc9265a0658c5c59fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:47:24 +0100 Subject: [PATCH 03/13] build(deps): bump org.springframework.boot from 3.5.5 to 3.5.6 (#265) Bumps [org.springframework.boot](https://github.com/spring-projects/spring-boot) from 3.5.5 to 3.5.6. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.5...v3.5.6) --- updated-dependencies: - dependency-name: org.springframework.boot dependency-version: 3.5.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index be45ec27..a0652506 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] java = "21" -spring-boot = "3.5.5" +spring-boot = "3.5.6" spring-dependency-management = "1.1.7" openapi-generator = "7.15.0" openapi-tools = "0.2.7" From 64199edef607a052b8e8c9433381f9be620ed22d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:47:56 +0100 Subject: [PATCH 04/13] build(deps): bump org.projectlombok:lombok from 1.18.40 to 1.18.42 (#266) Bumps [org.projectlombok:lombok](https://github.com/projectlombok/lombok) from 1.18.40 to 1.18.42. - [Changelog](https://github.com/projectlombok/lombok/blob/master/doc/changelog.markdown) - [Commits](https://github.com/projectlombok/lombok/compare/v1.18.40...v1.18.42) --- updated-dependencies: - dependency-name: org.projectlombok:lombok dependency-version: 1.18.42 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0652506..c8b1b71b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ openapi-tools = "0.2.7" swagger = "2.2.36" swagger-request-validator = "2.45.1" jakarta-validation = "3.1.1" -lombok = "1.18.40" +lombok = "1.18.42" commons-codec = "1.19.0" find-bugs = "3.0.2" gradle-nexus-publish-plugin = "2.0.0" From f4d718053ce92b770be7094cba03c96e76cc8ed8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:48:22 +0100 Subject: [PATCH 05/13] build(deps): bump org.openapi.generator from 7.15.0 to 7.16.0 (#270) Bumps org.openapi.generator from 7.15.0 to 7.16.0. --- updated-dependencies: - dependency-name: org.openapi.generator dependency-version: 7.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c8b1b71b..2f22f683 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ java = "21" spring-boot = "3.5.6" spring-dependency-management = "1.1.7" -openapi-generator = "7.15.0" +openapi-generator = "7.16.0" openapi-tools = "0.2.7" swagger = "2.2.36" swagger-request-validator = "2.45.1" From 361ba56699479784f025f84569d3a819301ac026 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:48:53 +0100 Subject: [PATCH 06/13] build(deps): bump io.swagger.core.v3:swagger-annotations (#271) Bumps io.swagger.core.v3:swagger-annotations from 2.2.36 to 2.2.39. --- updated-dependencies: - dependency-name: io.swagger.core.v3:swagger-annotations dependency-version: 2.2.39 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2f22f683..8979488f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ spring-boot = "3.5.6" spring-dependency-management = "1.1.7" openapi-generator = "7.16.0" openapi-tools = "0.2.7" -swagger = "2.2.36" +swagger = "2.2.39" swagger-request-validator = "2.45.1" jakarta-validation = "3.1.1" lombok = "1.18.42" From d4a271372d4f6de93783c16930dd813a57ce1ea1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:53:14 +0100 Subject: [PATCH 07/13] build(deps): bump org.apache.tomcat.embed:tomcat-embed-core (#272) Bumps org.apache.tomcat.embed:tomcat-embed-core from 11.0.10 to 11.0.13. --- updated-dependencies: - dependency-name: org.apache.tomcat.embed:tomcat-embed-core dependency-version: 11.0.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 3219328b..df6531f5 100644 --- a/build.gradle +++ b/build.gradle @@ -76,7 +76,7 @@ subprojects { implementation("org.springframework:spring-webmvc:6.2.11") { because("versions below 6.2.11 have security vulnerabilities including CVE-2025-41242 and CVE-2025-41249 - see dependabot #24, #247") } - implementation("org.apache.tomcat.embed:tomcat-embed-core:11.0.10") { + implementation("org.apache.tomcat.embed:tomcat-embed-core:11.0.13") { because("versions below 10.1.42 have security vulnerabilities including CVE-2024-56337 - see dependabot #13") } implementation("org.apache.commons:commons-lang3:3.18.0") { From 8b4deaa9fa79a7e0f1b32d371ff279587e43b5de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:53:21 +0100 Subject: [PATCH 08/13] build(deps): bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 (#269) Bumps org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index df6531f5..5345ff07 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ subprojects { implementation("org.apache.tomcat.embed:tomcat-embed-core:11.0.13") { because("versions below 10.1.42 have security vulnerabilities including CVE-2024-56337 - see dependabot #13") } - implementation("org.apache.commons:commons-lang3:3.18.0") { + implementation("org.apache.commons:commons-lang3:3.19.0") { because("versions below 3.18.0 have security vulnerabilities including CVE-2025-48924 - see dependabot #15") } implementation("io.projectreactor.netty:reactor-netty-http:1.2.9") { From 21be4cff867f9bb87341cd87de5a2fe106a129a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:53:59 +0100 Subject: [PATCH 09/13] build(deps): bump org.springframework:spring-web from 6.2.10 to 6.2.12 (#274) Bumps [org.springframework:spring-web](https://github.com/spring-projects/spring-framework) from 6.2.10 to 6.2.12. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.2.10...v6.2.12) --- updated-dependencies: - dependency-name: org.springframework:spring-web dependency-version: 6.2.12 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5345ff07..9051f450 100644 --- a/build.gradle +++ b/build.gradle @@ -70,10 +70,10 @@ subprojects { // Security constraints constraints { - implementation("org.springframework:spring-web:6.2.11") { + implementation("org.springframework:spring-web:6.2.12") { because("versions below 6.2.11 have security vulnerabilities including CVE-2024-38820 and CVE-2025-41249 - see dependabot #12, #24") } - implementation("org.springframework:spring-webmvc:6.2.11") { + implementation("org.springframework:spring-webmvc:6.2.12") { because("versions below 6.2.11 have security vulnerabilities including CVE-2025-41242 and CVE-2025-41249 - see dependabot #24, #247") } implementation("org.apache.tomcat.embed:tomcat-embed-core:11.0.13") { From 3adfed73db85505da7331be2a2ab2e7c30608889 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:57:46 +0100 Subject: [PATCH 10/13] build(deps): bump io.projectreactor.netty:reactor-netty-http (#273) Bumps [io.projectreactor.netty:reactor-netty-http](https://github.com/reactor/reactor-netty) from 1.2.9 to 1.2.11. - [Release notes](https://github.com/reactor/reactor-netty/releases) - [Commits](https://github.com/reactor/reactor-netty/compare/v1.2.9...v1.2.11) --- updated-dependencies: - dependency-name: io.projectreactor.netty:reactor-netty-http dependency-version: 1.2.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9051f450..602cc5e7 100644 --- a/build.gradle +++ b/build.gradle @@ -82,7 +82,7 @@ subprojects { implementation("org.apache.commons:commons-lang3:3.19.0") { because("versions below 3.18.0 have security vulnerabilities including CVE-2025-48924 - see dependabot #15") } - implementation("io.projectreactor.netty:reactor-netty-http:1.2.9") { + implementation("io.projectreactor.netty:reactor-netty-http:1.2.11") { because("versions below 1.2.8 have security vulnerabilities including CVE-2025-22227 - see dependabot #16") } implementation("io.netty:netty-codec-http2:4.2.6.Final") { From edd9c22dbbb2b567c8d54296721ad2071382de0e Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Tue, 28 Oct 2025 06:53:16 +0100 Subject: [PATCH 11/13] Fix: Do not return violations with LogLevel.IGNORE (#279) --- .../core/OpenApiRequestValidator.java | 9 +- .../core/OpenApiRequestValidatorTest.java | 183 +++++++++++++++--- .../FailOnViolationIntegrationTest.java | 4 +- .../FailOnViolationIntegrationTest.java | 4 +- 4 files changed, 169 insertions(+), 31 deletions(-) diff --git a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java index 41800da9..ac730ba8 100644 --- a/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java +++ b/openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java @@ -3,6 +3,7 @@ import com.atlassian.oai.validator.model.Request; import com.atlassian.oai.validator.model.SimpleRequest; import com.atlassian.oai.validator.model.SimpleResponse; +import com.getyourguide.openapi.validation.api.log.LogLevel; import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler; import com.getyourguide.openapi.validation.api.metrics.MetricsReporter; import com.getyourguide.openapi.validation.api.model.Direction; @@ -98,7 +99,7 @@ public List validateRequestObject( var result = validator.validateRequest(simpleRequest); var violations = mapper.map(result, request, response, Direction.REQUEST, requestBody); return violations.stream() - .filter(violation -> !violationExclusions.isExcluded(violation)) + .filter(this::isNonExcludedViolation) .toList(); } catch (Exception e) { log.error("[OpenAPI Validation] Could not validate request", e); @@ -145,11 +146,15 @@ public List validateResponseObject( ); var violations = mapper.map(result, request, response, Direction.RESPONSE, responseBody); return violations.stream() - .filter(violation -> !violationExclusions.isExcluded(violation)) + .filter(this::isNonExcludedViolation) .toList(); } catch (Exception e) { log.error("[OpenAPI Validation] Could not validate response", e); return List.of(); } } + + private boolean isNonExcludedViolation(OpenApiViolation violation) { + return !LogLevel.IGNORE.equals(violation.getLevel()) && !violationExclusions.isExcluded(violation); + } } diff --git a/openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java b/openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java index 9b2e4882..652a5c2c 100644 --- a/openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java +++ b/openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java @@ -8,8 +8,10 @@ import com.atlassian.oai.validator.model.SimpleRequest; import com.atlassian.oai.validator.report.ValidationReport; +import com.getyourguide.openapi.validation.api.log.LogLevel; import com.getyourguide.openapi.validation.api.model.OpenApiViolation; import com.getyourguide.openapi.validation.api.model.RequestMetaData; +import com.getyourguide.openapi.validation.api.model.ResponseMetaData; import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions; import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper; import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper; @@ -19,6 +21,8 @@ import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -51,49 +55,178 @@ public void setup() { } @Test + @DisplayName("When thread pool executor rejects execution then it should not throw") public void testWhenThreadPoolExecutorRejectsExecutionThenItShouldNotThrow() { Mockito.doThrow(new RejectedExecutionException()).when(executor).execute(any()); openApiRequestValidator.validateRequestObjectAsync(mock(), null, null, mock()); } - @Test - public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQueryParamDecoded() { - var uri = URI.create("https://api.example.com?ids=1%2C2%2C3&text=e%3Dmc2%20%26%20more&spaces=this+is+a+sparta"); - var request = new RequestMetaData("GET", uri, new HashMap<>()); + @Nested + @DisplayName("validateRequestObject") + public class ValidateRequestObjectTests { + + @Test + @DisplayName("When encoded query param is passed then validation should happen with query param decoded") + public void testWhenEncodedQueryParamIsPassedThenValidationShouldHappenWithQueryParamDecoded() { + var uri = URI.create("https://api.example.com?ids=1%2C2%2C3&text=e%3Dmc2%20%26%20more&spaces=this+is+a+sparta"); + var request = new RequestMetaData("GET", uri, new HashMap<>()); + + openApiRequestValidator.validateRequestObject(request, null); + + var simpleRequestArgumentCaptor = ArgumentCaptor.forClass(SimpleRequest.class); + verify(validator).validateRequest(simpleRequestArgumentCaptor.capture()); + verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "ids", "1,2,3"); + verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "text", "e=mc2 & more"); + verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "spaces", "this is a sparta"); + } + + @Test + @DisplayName("When violation is excluded then it should not be returned") + public void testWhenViolationIsExcludedThenItShouldNotBeReturned() { + var validationReport = mock(ValidationReport.class); + when(validator.validateRequest(any())).thenReturn(validationReport); + var violationExcluded = mock(OpenApiViolation.class); + var violations = List.of(violationExcluded, mock(OpenApiViolation.class)); + when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); + when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); + + var result = openApiRequestValidator.validateRequestObject(createRequest(), null); + + assertEquals(1, result.size()); + assertEquals(violations.get(1), result.getFirst()); + } + + @Test + @DisplayName("When violation has log level IGNORE then it should not be returned") + public void testWhenRequestViolationHasLogLevelIgnoreThenItShouldNotBeReturned() { + var violationIgnored = createViolation(LogLevel.IGNORE); + var violationError = createViolation(LogLevel.ERROR); + mockRequestValidation(List.of(violationIgnored, violationError)); + + var result = openApiRequestValidator.validateRequestObject(createRequest(), null); + + assertSingleViolationReturned(result, violationError); + } + + @Test + @DisplayName("When violation has log level IGNORE and another is excluded then both should not be returned") + public void testWhenRequestViolationHasLogLevelIgnoreAndIsExcludedThenItShouldNotBeReturned() { + var violationIgnored = createViolation(LogLevel.IGNORE); + var violationExcluded = createViolation(LogLevel.WARN); + when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); + var violationError = createViolation(LogLevel.ERROR); + mockRequestValidation(List.of(violationIgnored, violationExcluded, violationError)); + + var result = openApiRequestValidator.validateRequestObject(createRequest(), null); + + assertSingleViolationReturned(result, violationError); + } + + @Test + @DisplayName("When all violations are ignored then empty list is returned") + public void testWhenAllRequestViolationsAreIgnoredThenEmptyListIsReturned() { + var violation1 = createViolation(LogLevel.IGNORE); + var violation2 = createViolation(LogLevel.IGNORE); + mockRequestValidation(List.of(violation1, violation2)); + + var result = openApiRequestValidator.validateRequestObject(createRequest(), null); + + assertNoViolationsReturned(result); + } + } + + @Nested + @DisplayName("validateResponseObject") + public class ValidateResponseObjectTests { + + @Test + @DisplayName("When violation has log level IGNORE then it should not be returned") + public void testWhenResponseViolationHasLogLevelIgnoreThenItShouldNotBeReturned() { + var violationIgnored = createViolation(LogLevel.IGNORE); + var violationWarn = createViolation(LogLevel.WARN); + mockResponseValidation(List.of(violationIgnored, violationWarn)); + + var result = executeValidateResponseObject(); + + assertSingleViolationReturned(result, violationWarn); + } + + @Test + @DisplayName("When violation has log level IGNORE and another is excluded then both should not be returned") + public void testWhenResponseViolationHasLogLevelIgnoreAndIsExcludedThenItShouldNotBeReturned() { + var violationIgnored = createViolation(LogLevel.IGNORE); + var violationExcluded = createViolation(LogLevel.INFO); + when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); + var violationError = createViolation(LogLevel.ERROR); + mockResponseValidation(List.of(violationIgnored, violationExcluded, violationError)); + + var result = executeValidateResponseObject(); + + assertSingleViolationReturned(result, violationError); + } + + @Test + @DisplayName("When all violations are ignored then empty list is returned") + public void testWhenAllResponseViolationsAreIgnoredThenEmptyListIsReturned() { + var violation1 = createViolation(LogLevel.IGNORE); + var violation2 = createViolation(LogLevel.IGNORE); + mockResponseValidation(List.of(violation1, violation2)); + + var result = executeValidateResponseObject(); + + assertNoViolationsReturned(result); + } + + private List executeValidateResponseObject() { + var request = createRequest(); + var response = createResponse(); + return openApiRequestValidator.validateResponseObject(request, response, null); + } + } - openApiRequestValidator.validateRequestObject(request, null); + private void verifyQueryParamValueEquals( + ArgumentCaptor simpleRequestArgumentCaptor, + String name, + String expected + ) { + var ids = simpleRequestArgumentCaptor.getValue().getQueryParameterValues(name).iterator().next(); + assertEquals(expected, ids); + } - var simpleRequestArgumentCaptor = ArgumentCaptor.forClass(SimpleRequest.class); - verify(validator).validateRequest(simpleRequestArgumentCaptor.capture()); - verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "ids", "1,2,3"); - verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "text", "e=mc2 & more"); - verifyQueryParamValueEquals(simpleRequestArgumentCaptor, "spaces", "this is a sparta"); + private OpenApiViolation createViolation(LogLevel level) { + var violation = mock(OpenApiViolation.class); + when(violation.getLevel()).thenReturn(level); + return violation; } - @Test - public void testWhenViolationIsExcludedThenItShouldNotBeReturned() { + private RequestMetaData createRequest() { var uri = URI.create("https://api.example.com/path"); - var request = new RequestMetaData("GET", uri, new HashMap<>()); + return new RequestMetaData("GET", uri, new HashMap<>()); + } + + private ResponseMetaData createResponse() { + return new ResponseMetaData(200, "application/json", new HashMap<>()); + } + + private void mockRequestValidation(List violations) { var validationReport = mock(ValidationReport.class); when(validator.validateRequest(any())).thenReturn(validationReport); - var violationExcluded = mock(OpenApiViolation.class); - var violations = List.of(violationExcluded, mock(OpenApiViolation.class)); when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); - when(internalViolationExclusions.isExcluded(violationExcluded)).thenReturn(true); + } - var result = openApiRequestValidator.validateRequestObject(request, null); + private void mockResponseValidation(List violations) { + var validationReport = mock(ValidationReport.class); + when(validator.validateResponse(any(), any(), any())).thenReturn(validationReport); + when(mapper.map(any(), any(), any(), any(), any())).thenReturn(violations); + } + private void assertSingleViolationReturned(List result, OpenApiViolation expected) { assertEquals(1, result.size()); - assertEquals(violations.get(1), result.getFirst()); + assertEquals(expected, result.getFirst()); } - private void verifyQueryParamValueEquals( - ArgumentCaptor simpleRequestArgumentCaptor, - String name, - String expected - ) { - var ids = simpleRequestArgumentCaptor.getValue().getQueryParameterValues(name).iterator().next(); - assertEquals(expected, ids); + private void assertNoViolationsReturned(List result) { + assertEquals(0, result.size()); } } diff --git a/spring-boot-starter/spring-boot-starter-web/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java b/spring-boot-starter/spring-boot-starter-web/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java index f29c4369..05043e9f 100644 --- a/spring-boot-starter/spring-boot-starter-web/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java +++ b/spring-boot-starter/spring-boot-starter-web/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java @@ -20,8 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; @@ -39,7 +39,7 @@ public class FailOnViolationIntegrationTest { @Autowired private TestViolationLogger openApiViolationLogger; - @SpyBean + @MockitoSpyBean private DefaultRestController defaultRestController; @BeforeEach diff --git a/spring-boot-starter/spring-boot-starter-webflux/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java b/spring-boot-starter/spring-boot-starter-webflux/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java index 602236b3..f110c512 100644 --- a/spring-boot-starter/spring-boot-starter-webflux/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java +++ b/spring-boot-starter/spring-boot-starter-webflux/src/test/java/com/getyourguide/openapi/validation/integration/FailOnViolationIntegrationTest.java @@ -14,8 +14,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; @@ -33,7 +33,7 @@ public class FailOnViolationIntegrationTest { @Autowired private TestViolationLogger openApiViolationLogger; - @SpyBean + @MockitoSpyBean private DefaultRestController defaultRestController; @BeforeEach From fe8cd0d4448c4d11b9415b234b20ad7a62beb13e Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Tue, 28 Oct 2025 08:25:34 +0100 Subject: [PATCH 12/13] Use github tag for release version (#289) --- RELEASE.md | 22 +++++++++++++++------- build.gradle | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index af7792cd..d3eec587 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,9 +1,17 @@ # Release process -1. Update the `version` in `build.gradle` - - Push this to `main` (optionally with a PR) -2. Create a new release on github: [direct link](https://github.com/getyourguide/openapi-validation-java/releases/new) - - Choose a tag `v....` (the new version) - - Select "Create new tag" - - Press "Generate release notes" - - Publish release +- Create a new release on github: [direct link](https://github.com/getyourguide/openapi-validation-java/releases/new) +- Choose a tag `v....` (the new version) +- Select "Create new tag" +- Press "Generate release notes" +- Publish release + +## Release SNAPSHOT version from branch + +- Create a new release on github: [direct link](https://github.com/getyourguide/openapi-validation-java/releases/new) +- Choose a tag `v....` (the new version) +- Select "Create new tag" +- **Choose your branch as target** +- Press "Generate release notes" +- **Check "Set as a pre-release"** +- Publish release diff --git a/build.gradle b/build.gradle index 602cc5e7..22924cf0 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,8 @@ apply from: "${rootDir}/gradle/publish-root.gradle" allprojects { group = 'com.getyourguide.openapi.validation' description = 'OpenAPI Validation library' - version = '3.3.2' + // Use version from GitHub tag if provided, otherwise use default version + version = project.hasProperty('gh_tag') ? project.property('gh_tag').replaceFirst('^v', '') : '0-SNAPSHOT' java { toolchain { From e88a04cf83dc783cd9d9a20aaa174caf71fe7a66 Mon Sep 17 00:00:00 2001 From: Patrick Boos Date: Tue, 28 Oct 2025 09:25:06 +0100 Subject: [PATCH 13/13] Use github tag for release version (fix) (#290) --- .github/workflows/publish.yml | 8 ++++++++ build.gradle | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1d5da543..9b1d0036 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,6 +27,13 @@ jobs: uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 with: arguments: sourcesJar javadocJar + - name: Get tag + shell: bash + id: get_tag + run: | + TAG=${GITHUB_REF#refs/tags/} + echo "Github tag: $TAG" + echo "gh_tag=${TAG#v}" >> "$GITHUB_OUTPUT" - name: Publish to MavenCentral uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 with: @@ -38,3 +45,4 @@ jobs: SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }} SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + GH_TAG: "${{ steps.get_tag.outputs.gh_tag }}" diff --git a/build.gradle b/build.gradle index 22924cf0..b853cce8 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ allprojects { group = 'com.getyourguide.openapi.validation' description = 'OpenAPI Validation library' // Use version from GitHub tag if provided, otherwise use default version - version = project.hasProperty('gh_tag') ? project.property('gh_tag').replaceFirst('^v', '') : '0-SNAPSHOT' + version = System.getenv('GH_TAG') ? System.getenv('GH_TAG').replaceFirst('^v', '') : '0-SNAPSHOT' java { toolchain {