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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public class Validate extends OpenApiGeneratorCommand {
@Option(name = {"--recommend"}, title = "recommend spec improvements")
private Boolean recommend;

@Option(name = {"--skip-unused-models"}, title = "skip unused models warning",
description = "skips the recommendation warning for schemas defined in components/schemas that are not referenced by any operation")
private Boolean skipUnusedModels;

@Option(
name = {"-a", "--auth"},
title = "authorization",
Expand All @@ -71,6 +75,8 @@ public void execute() {
if (recommend != null) ruleConfiguration.setEnableRecommendations(recommend);
else ruleConfiguration.setEnableRecommendations(false);

if (Boolean.TRUE.equals(skipUnusedModels)) ruleConfiguration.setEnableUnusedSchemasRecommendation(false);

OpenApiEvaluator evaluator = new OpenApiEvaluator(ruleConfiguration);
ValidationResult validationResult = evaluator.validate(specification);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class OpenApiGeneratorPlugin : Plugin<Project> {
remoteInputSpec.set(validate.remoteInputSpec)
recommend.set(validate.recommend)
treatWarningsAsErrors.set(validate.treatWarningsAsErrors)
skipUnusedModels.set(validate.skipUnusedModels)
}

register("openApiGenerate", GenerateTask::class.java).configure {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ open class OpenApiGeneratorValidateExtension(private val project: Project) {
*/
val treatWarningsAsErrors: Property<Boolean> = project.objects.property<Boolean>().convention(false)

/**
* Whether to suppress warnings for schemas defined in components/schemas that are not referenced by any operation.
*/
val skipUnusedModels: Property<Boolean> = project.objects.property<Boolean>().convention(false)

// ========================================================================
// Backwards-compatibility bridge setter for Groovy DSL
// This allows Groovy users to use assignment syntax: inputSpec = "path"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,14 @@ abstract class ValidateTask : DefaultTask() {
@get:Input
abstract val treatWarningsAsErrors: Property<Boolean>

@get:Optional
@get:Input
abstract val skipUnusedModels: Property<Boolean>

init {
recommend.convention(true)
treatWarningsAsErrors.convention(false)
skipUnusedModels.convention(false)
}

@Suppress("unused")
Expand All @@ -98,6 +103,7 @@ abstract class ValidateTask : DefaultTask() {

val recommendations = recommend.get()
val failOnWarnings = treatWarningsAsErrors.get()
val shouldSkipUnusedModels = skipUnusedModels.get()

logger.lifecycle("Validating spec $specLocation")

Expand All @@ -110,6 +116,9 @@ abstract class ValidateTask : DefaultTask() {

val ruleConfiguration = RuleConfiguration()
ruleConfiguration.isEnableRecommendations = recommendations
if (shouldSkipUnusedModels) {
ruleConfiguration.isEnableUnusedSchemasRecommendation = false
}

val evaluator = OpenApiEvaluator(ruleConfiguration)
val validationResult = evaluator.validate(result.openAPI)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,87 @@ paths:
)
}

@Test(dataProvider = "gradle_version_provider")
fun `openApiValidate should warn about unused models by default`(gradleVersion: String?, format: String) {
val propertyFormat = PropertyFormat.valueOf(format)
// Arrange
val projectFiles = mapOf(
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-with-unused-schema.yaml")
)

withProject(
"""
| plugins {
| id 'org.openapi.generator'
| }
|
| openApiValidate {
| ${inputSpecProperty("spec.yaml", propertyFormat)}
| }
""".trimMargin(), projectFiles
)

// Act
val result = getGradleRunner(gradleVersion)
.withProjectDir(temp)
.withArguments("openApiValidate")
.withPluginClasspath()
.build()

// Assert
assertTrue(
result.output.contains("Unused model: UnusedSchema"),
"Expected unused model warning to be present by default."
)
assertEquals(
SUCCESS, result.task(":openApiValidate")?.outcome,
"Expected a successful run, but found ${result.task(":openApiValidate")?.outcome}"
)
}

@Test(dataProvider = "gradle_version_provider")
fun `openApiValidate should suppress unused model warnings when skipUnusedModels is true`(gradleVersion: String?, format: String) {
val propertyFormat = PropertyFormat.valueOf(format)
// Arrange
val projectFiles = mapOf(
"spec.yaml" to javaClass.classLoader.getResourceAsStream("specs/petstore-v3.0-with-unused-schema.yaml")
)

withProject(
"""
| plugins {
| id 'org.openapi.generator'
| }
|
| openApiValidate {
| ${inputSpecProperty("spec.yaml", propertyFormat)}
| skipUnusedModels = true
| }
""".trimMargin(), projectFiles
)

// Act
val result = getGradleRunner(gradleVersion)
.withProjectDir(temp)
.withArguments("openApiValidate")
.withPluginClasspath()
.build()

// Assert
assertTrue(
result.output.contains("Unused model: UnusedSchema").not(),
"Expected unused model warning to be suppressed when skipUnusedModels = true."
)
assertTrue(
result.output.contains("Spec is valid."),
"Expected spec to be reported as valid."
)
assertEquals(
SUCCESS, result.task(":openApiValidate")?.outcome,
"Expected a successful run, but found ${result.task(":openApiValidate")?.outcome}"
)
}

@Test(dataProvider = "gradle_version_only_provider")
fun `openApiValidate should support task-level configuration with Kotlin DSL set String syntax`(gradleVersion: String?) {
// Create a valid spec file
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
responses:
'200':
description: A list of pets
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
UnusedSchema:
description: This schema is defined but never referenced by any operation.
type: object
properties:
id:
type: integer