From 0a14e905e92ce55104745df5bbe670e5be638d32 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Tue, 21 Jul 2026 18:47:32 -0500 Subject: [PATCH 1/2] feat: new rule AAR056 avro schema format --- CHANGELOG.md | 3 +- README.md | 1 + .../sonar/asyncapi/checks/RulesLists.java | 3 +- .../schemas/AAR056AvroSchemaFormatCheck.java | 70 ++++++++++++++++ src/main/resources/messages/errors.properties | 1 + .../resources/messages/errors_es.properties | 3 +- .../rules/asyncapi/schemas/AAR056.html | 82 +++++++++++++++++++ .../rules/asyncapi/schemas/AAR056.json | 13 +++ .../rules/asyncapi/schemas/AAR056.html | 82 +++++++++++++++++++ .../rules/asyncapi/schemas/AAR056.json | 13 +++ .../AAR056AvroSchemaFormatCheckTest.java | 66 +++++++++++++++ .../AAR056/non-avro-schema-format.yaml | 15 ++++ .../checks/v2/schemas/AAR056/valid.yaml | 27 ++++++ .../v2/schemas/AAR056/wrong-version.yaml | 27 ++++++ .../AAR056/non-avro-schema-format.yaml | 16 ++++ .../checks/v3/schemas/AAR056/valid.yaml | 29 +++++++ .../v3/schemas/AAR056/wrong-version.yaml | 29 +++++++ .../checks/v31/schemas/AAR056/valid.yaml | 18 ++++ .../v31/schemas/AAR056/wrong-version.yaml | 18 ++++ 19 files changed, 513 insertions(+), 3 deletions(-) create mode 100644 src/main/java/apiquality/sonar/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheck.java create mode 100644 src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html create mode 100644 src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.json create mode 100644 src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html create mode 100644 src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.json create mode 100644 src/test/java/org/sonar/samples/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheckTest.java create mode 100644 src/test/resources/checks/v2/schemas/AAR056/non-avro-schema-format.yaml create mode 100644 src/test/resources/checks/v2/schemas/AAR056/valid.yaml create mode 100644 src/test/resources/checks/v2/schemas/AAR056/wrong-version.yaml create mode 100644 src/test/resources/checks/v3/schemas/AAR056/non-avro-schema-format.yaml create mode 100644 src/test/resources/checks/v3/schemas/AAR056/valid.yaml create mode 100644 src/test/resources/checks/v3/schemas/AAR056/wrong-version.yaml create mode 100644 src/test/resources/checks/v31/schemas/AAR056/valid.yaml create mode 100644 src/test/resources/checks/v31/schemas/AAR056/wrong-version.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 2613f54..4fea2aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.2-beta-3] - 2026-07-15 +## [2.0.2-beta-3] - 2026-07-21 ### Added - **AAR050InfoTitleRequiredCheck**: The `info.title` field must exist and not be empty, so the AsyncAPI title reliably identifies the messaging contract (BUG / MAJOR). +- **AAR056AvroSchemaFormatCheck**: Wherever `schemaFormat` appears in the document (message-level in v2, `message.payload` Multi-Format Schema Object in v3, or a `components.schemas` entry) and indicates Avro, it must be exactly `application/vnd.apache.avro;version=1.9.0`, the standard version used across Madrid Digital examples (BUG / MAJOR). ## [2.0.2-beta-2] - 2026-06-25 diff --git a/README.md b/README.md index 2fcfed0..b8f93c6 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ This plugin is supported by SonarQube versions greater or equal to `6.7.4` - **AAR042MessageIdentifierCheck**: It is recommended to have a unique identifier per message. - **AAR043SecurityChannelCheck**: It is recommended to add the security scheme to be used to each channel. - **AAR050InfoTitleRequiredCheck**: The info.title field must exist and not be empty. +- **AAR056AvroSchemaFormatCheck**: When `schemaFormat` indicates Avro, it must be exactly `application/vnd.apache.avro;version=1.9.0`. ## 💛 Sponsors cloudappi diff --git a/src/main/java/apiquality/sonar/asyncapi/checks/RulesLists.java b/src/main/java/apiquality/sonar/asyncapi/checks/RulesLists.java index 968aedb..7f879cc 100644 --- a/src/main/java/apiquality/sonar/asyncapi/checks/RulesLists.java +++ b/src/main/java/apiquality/sonar/asyncapi/checks/RulesLists.java @@ -72,7 +72,8 @@ public static List> getSchemasChecks() { AAR046AvroRecordDocCheck.class, AAR047AvroFieldDocCheck.class, AAR048AvroNameNomenclatureCheck.class, - AAR049AvroDefaultNullCheck.class + AAR049AvroDefaultNullCheck.class, + AAR056AvroSchemaFormatCheck.class ); } diff --git a/src/main/java/apiquality/sonar/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheck.java b/src/main/java/apiquality/sonar/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheck.java new file mode 100644 index 0000000..0b8362e --- /dev/null +++ b/src/main/java/apiquality/sonar/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheck.java @@ -0,0 +1,70 @@ +package apiquality.sonar.asyncapi.checks.schemas; + +import com.google.common.collect.Sets; +import com.sonar.sslr.api.AstNodeType; +import org.sonar.check.Rule; +import org.apiaddicts.apitools.dosonarapi.api.v4.AsyncApiGrammar; +import apiquality.sonar.asyncapi.checks.BaseCheck; +import apiquality.sonar.asyncapi.utils.AvroUtils; +import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode; + +import java.util.Map; +import java.util.Set; + +@Rule(key = AAR056AvroSchemaFormatCheck.CHECK_KEY) +public class AAR056AvroSchemaFormatCheck extends BaseCheck { + public static final String CHECK_KEY = "AAR056"; + private static final String ERROR_KEY = "AAR056.error"; + + private static final String SCHEMA_FORMAT_KEY = "schemaFormat"; + private static final String EXPECTED_SCHEMA_FORMAT = "application/vnd.apache.avro;version=1.9.0"; + + @Override + public Set subscribedKinds() { + return Sets.newHashSet(AsyncApiGrammar.ROOT); + } + + @Override + protected void visitNode(JsonNode rootNode) { + visit(rootNode); + } + + private void visit(JsonNode node) { + if (node == null || node.isMissing() || node.isNull()) { + return; + } + if (node.isArray()) { + for (JsonNode element : node.elements()) { + visit(element); + } + return; + } + if (!node.isObject()) { + return; + } + for (Map.Entry entry : node.propertyMap().entrySet()) { + if (SCHEMA_FORMAT_KEY.equals(entry.getKey())) { + validateSchemaFormat(entry.getValue()); + } + visit(entry.getValue()); + } + } + + private void validateSchemaFormat(JsonNode schemaFormatNode) { + if (schemaFormatNode == null || schemaFormatNode.isMissing() || schemaFormatNode.isNull()) { + return; + } + if (schemaFormatNode.isObject() || schemaFormatNode.isArray()) { + return; + } + + String value = schemaFormatNode.stringValue(); + if (value == null || !value.contains(AvroUtils.AVRO_SCHEMA_FORMAT_PREFIX)) { + return; + } + + if (!EXPECTED_SCHEMA_FORMAT.equals(value)) { + addIssue(CHECK_KEY, translate(ERROR_KEY, value, EXPECTED_SCHEMA_FORMAT), schemaFormatNode.key()); + } + } +} diff --git a/src/main/resources/messages/errors.properties b/src/main/resources/messages/errors.properties index a69edc4..d55c3bb 100644 --- a/src/main/resources/messages/errors.properties +++ b/src/main/resources/messages/errors.properties @@ -39,3 +39,4 @@ AAR047.error=Avro field should include the doc attribute with a description AAR048.error=Avro name must start with a letter or underscore, and can only contain letters, numbers and underscores AAR049.error=Optional Avro fields (union with null) must declare their default value as null AAR050.error=The info object must contain a non-empty title field +AAR056.error=The ''schemaFormat'' value ''{0}'' must be exactly ''{1}'' when the payload uses Avro diff --git a/src/main/resources/messages/errors_es.properties b/src/main/resources/messages/errors_es.properties index a22f5a9..d01abd7 100644 --- a/src/main/resources/messages/errors_es.properties +++ b/src/main/resources/messages/errors_es.properties @@ -36,4 +36,5 @@ AAR046.error=El registro Avro debería incluir el campo doc con una descripción AAR047.error=El campo Avro debería incluir el atributo doc con una descripción AAR048.error=El nombre Avro debe empezar con una letra o guion bajo, y solo puede contener letras, números y guiones bajos AAR049.error=Los campos opcionales de Avro (unión con null) deben declarar su valor por defecto como null -AAR050.error=El objeto info debe contener un campo title no vacío \ No newline at end of file +AAR050.error=El objeto info debe contener un campo title no vacío +AAR056.error=El valor de ''schemaFormat'' ''{0}'' debe ser exactamente ''{1}'' cuando el payload usa Avro diff --git a/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html new file mode 100644 index 0000000..17aaeff --- /dev/null +++ b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html @@ -0,0 +1,82 @@ +

When a message payload (AsyncAPI 2) or a Multi-Format Schema Object (AsyncAPI 3, on message.payload or a components.schemas entry) declares an Avro schemaFormat — i.e. its value contains application/vnd.apache.avro — that value must be exactly application/vnd.apache.avro;version=1.9.0.

+

Version 1.9.0 is the standard Avro schema version used across Madrid Digital and appears in every example throughout the Style Guide. Any other version string, or a missing version, is reported as an issue. schemaFormat values that are not Avro at all (e.g. a JSON Schema schemaFormat) are out of scope for this rule.

+

Noncompliant Code Example (AsyncAPI 2)

+
+asyncapi: '2.6.0'
+info:
+  title: Carga API
+  version: '1.0.0'
+channels:
+  carga:
+    subscribe:
+      message:
+        schemaFormat: 'application/vnd.apache.avro;version=1.8.0'
+        payload:
+          type: record
+          name: CargaValue
+          namespace: com.example.avro
+          fields:
+            - name: id
+              type: string
+
+

Compliant Solution (AsyncAPI 2)

+
+asyncapi: '2.6.0'
+info:
+  title: Carga API
+  version: '1.0.0'
+channels:
+  carga:
+    subscribe:
+      message:
+        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
+        payload:
+          type: record
+          name: CargaValue
+          namespace: com.example.avro
+          fields:
+            - name: id
+              type: string
+
+

Noncompliant Code Example (AsyncAPI 3)

+
+asyncapi: 3.0.0
+info:
+  title: Carga API
+  version: 1.0.0
+channels:
+  carga:
+    address: carga
+    messages:
+      CargaMessage:
+        payload:
+          schemaFormat: 'application/vnd.apache.avro;version=1.8.0'
+          schema:
+            type: record
+            name: CargaValue
+            namespace: com.example.avro
+            fields:
+              - name: id
+                type: string
+
+

Compliant Solution (AsyncAPI 3)

+
+asyncapi: 3.0.0
+info:
+  title: Carga API
+  version: 1.0.0
+channels:
+  carga:
+    address: carga
+    messages:
+      CargaMessage:
+        payload:
+          schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
+          schema:
+            type: record
+            name: CargaValue
+            namespace: com.example.avro
+            fields:
+              - name: id
+                type: string
+
diff --git a/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.json b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.json new file mode 100644 index 0000000..7d5c09a --- /dev/null +++ b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.json @@ -0,0 +1,13 @@ +{ + "title": "AAR056 - AvroSchemaFormat - The schemaFormat must be application/vnd.apache.avro;version=1.9.0", + "type": "BUG", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5mn" + }, + "tags": [ + "schemas" + ], + "defaultSeverity": "MAJOR" +} diff --git a/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html new file mode 100644 index 0000000..38ebb43 --- /dev/null +++ b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html @@ -0,0 +1,82 @@ +

Cuando el payload de un mensaje (AsyncAPI 2) o un Multi-Format Schema Object (AsyncAPI 3, en message.payload o en una entrada de components.schemas) declara un schemaFormat de Avro — es decir, su valor contiene application/vnd.apache.avro — ese valor debe ser exactamente application/vnd.apache.avro;version=1.9.0.

+

La versión 1.9.0 es la versión estándar de Avro utilizada en Madrid Digital y aparece en todos los ejemplos de la Guía de Estilo. Cualquier otra versión, o la ausencia de versión, se reporta como incidencia. Los valores de schemaFormat que no sean de Avro (por ejemplo, un schemaFormat de JSON Schema) quedan fuera del alcance de esta regla.

+

Ejemplo Noncompliant (AsyncAPI 2)

+
+asyncapi: '2.6.0'
+info:
+  title: Carga API
+  version: '1.0.0'
+channels:
+  carga:
+    subscribe:
+      message:
+        schemaFormat: 'application/vnd.apache.avro;version=1.8.0'
+        payload:
+          type: record
+          name: CargaValue
+          namespace: com.example.avro
+          fields:
+            - name: id
+              type: string
+
+

Solución Compliant (AsyncAPI 2)

+
+asyncapi: '2.6.0'
+info:
+  title: Carga API
+  version: '1.0.0'
+channels:
+  carga:
+    subscribe:
+      message:
+        schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
+        payload:
+          type: record
+          name: CargaValue
+          namespace: com.example.avro
+          fields:
+            - name: id
+              type: string
+
+

Ejemplo Noncompliant (AsyncAPI 3)

+
+asyncapi: 3.0.0
+info:
+  title: Carga API
+  version: 1.0.0
+channels:
+  carga:
+    address: carga
+    messages:
+      CargaMessage:
+        payload:
+          schemaFormat: 'application/vnd.apache.avro;version=1.8.0'
+          schema:
+            type: record
+            name: CargaValue
+            namespace: com.example.avro
+            fields:
+              - name: id
+                type: string
+
+

Solución Compliant (AsyncAPI 3)

+
+asyncapi: 3.0.0
+info:
+  title: Carga API
+  version: 1.0.0
+channels:
+  carga:
+    address: carga
+    messages:
+      CargaMessage:
+        payload:
+          schemaFormat: 'application/vnd.apache.avro;version=1.9.0'
+          schema:
+            type: record
+            name: CargaValue
+            namespace: com.example.avro
+            fields:
+              - name: id
+                type: string
+
diff --git a/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.json b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.json new file mode 100644 index 0000000..6d6927d --- /dev/null +++ b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.json @@ -0,0 +1,13 @@ +{ + "title": "AAR056 - AvroSchemaFormat - El schemaFormat debe ser application/vnd.apache.avro;version=1.9.0", + "type": "BUG", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5mn" + }, + "tags": [ + "schemas" + ], + "defaultSeverity": "MAJOR" +} diff --git a/src/test/java/org/sonar/samples/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheckTest.java b/src/test/java/org/sonar/samples/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheckTest.java new file mode 100644 index 0000000..4232340 --- /dev/null +++ b/src/test/java/org/sonar/samples/asyncapi/checks/schemas/AAR056AvroSchemaFormatCheckTest.java @@ -0,0 +1,66 @@ +package org.sonar.samples.asyncapi.checks.schemas; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.rule.Severity; +import org.sonar.api.rules.RuleType; +import org.sonar.samples.asyncapi.BaseCheckTest; + +import apiquality.sonar.asyncapi.checks.schemas.AAR056AvroSchemaFormatCheck; + +public class AAR056AvroSchemaFormatCheckTest extends BaseCheckTest { + + @Before + public void init() { + ruleName = "AAR056"; + check = new AAR056AvroSchemaFormatCheck(); + v2Path = getV2Path("schemas"); + v3Path = getV3Path("schemas"); + v31Path = getV31Path("schemas"); + } + + @Test + public void verifyV2Valid() { + verifyV2("valid.yaml"); + } + + @Test + public void verifyV2WrongVersion() { + verifyV2("wrong-version.yaml"); + } + + @Test + public void verifyV2NonAvroSchemaFormat() { + verifyV2("non-avro-schema-format.yaml"); + } + + @Test + public void verifyV3Valid() { + verifyV3("valid.yaml"); + } + + @Test + public void verifyV3WrongVersion() { + verifyV3("wrong-version.yaml"); + } + + @Test + public void verifyV3NonAvroSchemaFormat() { + verifyV3("non-avro-schema-format.yaml"); + } + + @Test + public void verifyV31Valid() { + verifyV31("valid.yaml"); + } + + @Test + public void verifyV31WrongVersion() { + verifyV31("wrong-version.yaml"); + } + + @Override + public void verifyRule() { + assertRuleProperties("AAR056 - AvroSchemaFormat - The schemaFormat must be application/vnd.apache.avro;version=1.9.0", RuleType.BUG, Severity.MAJOR, tags("schemas")); + } +} diff --git a/src/test/resources/checks/v2/schemas/AAR056/non-avro-schema-format.yaml b/src/test/resources/checks/v2/schemas/AAR056/non-avro-schema-format.yaml new file mode 100644 index 0000000..cf3f96e --- /dev/null +++ b/src/test/resources/checks/v2/schemas/AAR056/non-avro-schema-format.yaml @@ -0,0 +1,15 @@ +asyncapi: '2.6.0' +info: + title: Avro Schema Format Non Avro V2 + version: '1.0.0' +channels: + carga: + subscribe: + operationId: receiveCarga + message: + schemaFormat: 'application/schema+json;version=draft-07' + payload: + type: object + properties: + id: + type: string diff --git a/src/test/resources/checks/v2/schemas/AAR056/valid.yaml b/src/test/resources/checks/v2/schemas/AAR056/valid.yaml new file mode 100644 index 0000000..422196e --- /dev/null +++ b/src/test/resources/checks/v2/schemas/AAR056/valid.yaml @@ -0,0 +1,27 @@ +asyncapi: '2.6.0' +info: + title: Avro Schema Format Valid V2 + version: '1.0.0' +channels: + carga: + subscribe: + operationId: receiveCarga + message: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + payload: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string +components: + schemas: + CargaComponent: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + type: record + name: CargaComponent + namespace: com.example.avro + fields: + - name: id + type: string diff --git a/src/test/resources/checks/v2/schemas/AAR056/wrong-version.yaml b/src/test/resources/checks/v2/schemas/AAR056/wrong-version.yaml new file mode 100644 index 0000000..26be003 --- /dev/null +++ b/src/test/resources/checks/v2/schemas/AAR056/wrong-version.yaml @@ -0,0 +1,27 @@ +asyncapi: '2.6.0' +info: + title: Avro Schema Format Wrong Version V2 + version: '1.0.0' +channels: + carga: + subscribe: + operationId: receiveCarga + message: + schemaFormat: 'application/vnd.apache.avro;version=1.8.0' # Noncompliant {{AAR056: The 'schemaFormat' value 'application/vnd.apache.avro;version=1.8.0' must be exactly 'application/vnd.apache.avro;version=1.9.0' when the payload uses Avro}} + payload: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string +components: + schemas: + CargaComponent: + schemaFormat: 'application/vnd.apache.avro' # Noncompliant {{AAR056: The 'schemaFormat' value 'application/vnd.apache.avro' must be exactly 'application/vnd.apache.avro;version=1.9.0' when the payload uses Avro}} + type: record + name: CargaComponent + namespace: com.example.avro + fields: + - name: id + type: string diff --git a/src/test/resources/checks/v3/schemas/AAR056/non-avro-schema-format.yaml b/src/test/resources/checks/v3/schemas/AAR056/non-avro-schema-format.yaml new file mode 100644 index 0000000..83b7102 --- /dev/null +++ b/src/test/resources/checks/v3/schemas/AAR056/non-avro-schema-format.yaml @@ -0,0 +1,16 @@ +asyncapi: 3.0.0 +info: + title: Avro Schema Format Non Avro V3 + version: 1.0.0 +channels: + carga: + address: carga + messages: + CargaMessage: + payload: + schemaFormat: 'application/schema+json;version=draft-07' + schema: + type: object + properties: + id: + type: string diff --git a/src/test/resources/checks/v3/schemas/AAR056/valid.yaml b/src/test/resources/checks/v3/schemas/AAR056/valid.yaml new file mode 100644 index 0000000..9ea6785 --- /dev/null +++ b/src/test/resources/checks/v3/schemas/AAR056/valid.yaml @@ -0,0 +1,29 @@ +asyncapi: 3.0.0 +info: + title: Avro Schema Format Valid V3 + version: 1.0.0 +channels: + carga: + address: carga + messages: + CargaMessage: + payload: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + schema: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string +components: + schemas: + CargaComponent: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + schema: + type: record + name: CargaComponent + namespace: com.example.avro + fields: + - name: id + type: string diff --git a/src/test/resources/checks/v3/schemas/AAR056/wrong-version.yaml b/src/test/resources/checks/v3/schemas/AAR056/wrong-version.yaml new file mode 100644 index 0000000..c164c91 --- /dev/null +++ b/src/test/resources/checks/v3/schemas/AAR056/wrong-version.yaml @@ -0,0 +1,29 @@ +asyncapi: 3.0.0 +info: + title: Avro Schema Format Wrong Version V3 + version: 1.0.0 +channels: + carga: + address: carga + messages: + CargaMessage: + payload: + schemaFormat: 'application/vnd.apache.avro;version=1.8.0' # Noncompliant {{AAR056: The 'schemaFormat' value 'application/vnd.apache.avro;version=1.8.0' must be exactly 'application/vnd.apache.avro;version=1.9.0' when the payload uses Avro}} + schema: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string +components: + schemas: + CargaComponent: + schemaFormat: 'application/vnd.apache.avro' # Noncompliant {{AAR056: The 'schemaFormat' value 'application/vnd.apache.avro' must be exactly 'application/vnd.apache.avro;version=1.9.0' when the payload uses Avro}} + schema: + type: record + name: CargaComponent + namespace: com.example.avro + fields: + - name: id + type: string diff --git a/src/test/resources/checks/v31/schemas/AAR056/valid.yaml b/src/test/resources/checks/v31/schemas/AAR056/valid.yaml new file mode 100644 index 0000000..06e3d39 --- /dev/null +++ b/src/test/resources/checks/v31/schemas/AAR056/valid.yaml @@ -0,0 +1,18 @@ +asyncapi: 3.1.0 +info: + title: Avro Schema Format Valid V31 + version: 1.0.0 +channels: + carga: + address: carga + messages: + CargaMessage: + payload: + schemaFormat: 'application/vnd.apache.avro;version=1.9.0' + schema: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string diff --git a/src/test/resources/checks/v31/schemas/AAR056/wrong-version.yaml b/src/test/resources/checks/v31/schemas/AAR056/wrong-version.yaml new file mode 100644 index 0000000..c3c8ce2 --- /dev/null +++ b/src/test/resources/checks/v31/schemas/AAR056/wrong-version.yaml @@ -0,0 +1,18 @@ +asyncapi: 3.1.0 +info: + title: Avro Schema Format Wrong Version V31 + version: 1.0.0 +channels: + carga: + address: carga + messages: + CargaMessage: + payload: + schemaFormat: 'application/vnd.apache.avro;version=1.8.0' # Noncompliant {{AAR056: The 'schemaFormat' value 'application/vnd.apache.avro;version=1.8.0' must be exactly 'application/vnd.apache.avro;version=1.9.0' when the payload uses Avro}} + schema: + type: record + name: CargaValue + namespace: com.example.avro + fields: + - name: id + type: string From 061691bb18d6dbaef0197028a1e486d179f67dc8 Mon Sep 17 00:00:00 2001 From: Melsy Huamani Date: Tue, 4 Aug 2026 09:09:52 -0500 Subject: [PATCH 2/2] fix: rule oar056 avro schema docs --- CHANGELOG.md | 2 +- .../org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html | 2 +- .../sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fea2aa..e4e8478 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **AAR050InfoTitleRequiredCheck**: The `info.title` field must exist and not be empty, so the AsyncAPI title reliably identifies the messaging contract (BUG / MAJOR). -- **AAR056AvroSchemaFormatCheck**: Wherever `schemaFormat` appears in the document (message-level in v2, `message.payload` Multi-Format Schema Object in v3, or a `components.schemas` entry) and indicates Avro, it must be exactly `application/vnd.apache.avro;version=1.9.0`, the standard version used across Madrid Digital examples (BUG / MAJOR). +- **AAR056AvroSchemaFormatCheck**: Wherever `schemaFormat` appears in the document (message-level in v2, `message.payload` Multi-Format Schema Object in v3, or a `components.schemas` entry) and indicates Avro, it must be exactly `application/vnd.apache.avro;version=1.9.0`, the standard version used across the Style Guide examples (BUG / MAJOR). ## [2.0.2-beta-2] - 2026-06-25 diff --git a/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html index 17aaeff..68d211b 100644 --- a/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html +++ b/src/main/resources/org/sonar/l10n/asyncapi/rules/asyncapi/schemas/AAR056.html @@ -1,5 +1,5 @@

When a message payload (AsyncAPI 2) or a Multi-Format Schema Object (AsyncAPI 3, on message.payload or a components.schemas entry) declares an Avro schemaFormat — i.e. its value contains application/vnd.apache.avro — that value must be exactly application/vnd.apache.avro;version=1.9.0.

-

Version 1.9.0 is the standard Avro schema version used across Madrid Digital and appears in every example throughout the Style Guide. Any other version string, or a missing version, is reported as an issue. schemaFormat values that are not Avro at all (e.g. a JSON Schema schemaFormat) are out of scope for this rule.

+

Version 1.9.0 is the standard Avro schema version and appears in every example throughout the Style Guide. Any other version string, or a missing version, is reported as an issue. schemaFormat values that are not Avro at all (e.g. a JSON Schema schemaFormat) are out of scope for this rule.

Noncompliant Code Example (AsyncAPI 2)

 asyncapi: '2.6.0'
diff --git a/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html
index 38ebb43..033e8ba 100644
--- a/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html
+++ b/src/main/resources/org/sonar/l10n/es/asyncapi/rules/asyncapi/schemas/AAR056.html
@@ -1,5 +1,5 @@
 

Cuando el payload de un mensaje (AsyncAPI 2) o un Multi-Format Schema Object (AsyncAPI 3, en message.payload o en una entrada de components.schemas) declara un schemaFormat de Avro — es decir, su valor contiene application/vnd.apache.avro — ese valor debe ser exactamente application/vnd.apache.avro;version=1.9.0.

-

La versión 1.9.0 es la versión estándar de Avro utilizada en Madrid Digital y aparece en todos los ejemplos de la Guía de Estilo. Cualquier otra versión, o la ausencia de versión, se reporta como incidencia. Los valores de schemaFormat que no sean de Avro (por ejemplo, un schemaFormat de JSON Schema) quedan fuera del alcance de esta regla.

+

La versión 1.9.0 es la versión estándar de Avro y aparece en todos los ejemplos de la Guía de Estilo. Cualquier otra versión, o la ausencia de versión, se reporta como incidencia. Los valores de schemaFormat que no sean de Avro (por ejemplo, un schemaFormat de JSON Schema) quedan fuera del alcance de esta regla.

Ejemplo Noncompliant (AsyncAPI 2)

 asyncapi: '2.6.0'