Gradle plugin for registering Avro schemas to Schema Registry and checking their compatibility.
// build.gradle.kts
plugins {
id("io.github.rudikone.avroschema-wizard-plugin") version "3.3.0"
}
avroWizardConfig {
schemaRegistryUrl.set("http://localhost:8081")
configs {
topic("my-topic") {
schema.set("MyRecord")
}
}
}# Register schemas
./gradlew registerAllSchemas
# Check compatibility
./gradlew checkCompatibility --compatibility=BACKWARDThe plugin is built for Java 17 bytecode and is verified against the following toolchain versions:
| Component | Version |
|---|---|
| Gradle (min) | 8.4 |
| Gradle (tested up to) | 9.8.1 |
| Java (min) | 17 |
| Kotlin Gradle plugin (tested) | 1.8.0, 1.9.20, 2.2.0 |
| confluent:kafka-schema-registry-client | 8.4.0 |
| confluent:kafka-schema-serializer | 8.4.0 |
Configuration Cache Support: since version 3.3.0
- Register Avro schemas to Schema Registry
- Schema compatibility checking (BACKWARD, FORWARD, FULL)
- Support for .avsc files and .avpr protocols
- Schema references between already-registered schemas (
references { reference { ... } }) - Three subject naming strategies: TopicNameStrategy, RecordNameStrategy, TopicRecordNameStrategy
- Configuration Cache compatible
- Local testing and CI/CD integration
build.gradle.kts:
plugins {
id("io.github.rudikone.avroschema-wizard-plugin") version "3.3.0"
}
avroWizardConfig {
schemaRegistryUrl.set("http://localhost:8081")
configs {
topic("my-first-topic") {
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
protocol.set("ExampleProtocol")
schema.set("FirstExampleRecordFromProtocol")
subjectNameStrategy.set("TopicNameStrategy")
}
topic("my-second-topic") {
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
protocol.set("ExampleProtocol")
schema.set("SecondExampleRecordFromProtocol")
subjectNameStrategy.set("RecordNameStrategy")
}
topic("my-third-topic") {
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
schema.set("Example")
// subjectNameStrategy defaults to TopicNameStrategy
}
}
}build.gradle (Groovy):
plugins {
id 'io.github.rudikone.avroschema-wizard-plugin' version '3.3.0'
}
avroWizardConfig {
schemaRegistryUrl.set('http://localhost:8081')
configs {
topic('my-topic') {
schema.set('MyRecord')
}
}
}| Property | Description | Default Value | Required |
|---|---|---|---|
schemaRegistryUrl |
Schema Registry URL | http://localhost:10081 |
❌ |
configs |
Topic configurations | — | ✅ |
| Property | Description | Default Value | Required |
|---|---|---|---|
searchAvroFilePath |
Directory to search for .avsc/.avpr files | <buildDir> of project |
❌ |
protocol |
Name of .avpr file (without extension) | — | ❌¹ |
schema |
Schema name (.avsc) or record from protocol | — | ✅ |
subjectNameStrategy |
Strategy: TopicNameStrategy, RecordNameStrategy, TopicRecordNameStrategy |
TopicNameStrategy |
❌ |
references |
List of references to already-registered schemas (see below) | [] |
❌ |
¹ — protocol and schema (without protocol) are interchangeable: specify either protocol+schema, or just schema.
Registers Avro schemas to Schema Registry based on configuration.
./gradlew registerAllSchemasHow it works:
- For each
topic()configuration:- If
protocolis specified — searches for.avprfile insearchAvroFilePath - If only
schemais specified — searches for.avscfile insearchAvroFilePath
- If
- Registers the schema under a subject name formed by
subjectNameStrategy
Output:
Registered FirstExampleRecordFromProtocol with id: 123 under subject my-topic-value
Notes:
- If file is not found — task fails with error
- Each schema is registered independently for each topic
- When registering the same schema under different subjects, ID is assigned once
If a schema references another Avro type (an external named type), it can only be registered when
the referenced schema is already present in Schema Registry. Declare each reference by its
name (the fully-qualified type name as used in the parent schema), subject and version
of the already-registered referenced schema:
avroWizardConfig {
schemaRegistryUrl.set("http://localhost:8081")
configs {
topic("shared-topic") {
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
schema.set("SharedRecord")
}
topic("main-topic") {
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
schema.set("MainRecord")
references {
reference {
name.set("ru.rudikov.reference.SharedRecord")
subject.set("shared-topic-value")
version.set(1)
}
}
}
}
}The plugin reads the referenced schema from Schema Registry (via subject + version) and passes
it together with the parent schema, so the parent schema is registered as valid. Referenced schemas
are not registered automatically — they must already exist.
References also work for types defined in .avpr protocols. Use protocol + schema as usual
and declare the referenced, already-registered types in references. If a protocol type references
another type defined in the same protocol, register that type separately and declare it as a
reference too.
Notes:
- References apply to both
.avscschemas and.avprprotocol types - If a reference points to a non-existent
subjectorversion, the task fails with a clear error naming the reference
Verifies Avro schema compatibility with the latest version in Schema Registry.
./gradlew checkCompatibility --compatibility=BACKWARDAvailable compatibility levels: BACKWARD, FORWARD, FULL, NONE
How it works:
- For each
topic()configuration:- Finds schema (by protocol or schema)
- Checks compatibility against current version in Schema Registry
- Uses specified compatibility level (or default from SR)
Output:
Schema ru.rudikov.example.Example is compatible with subject my-topic-value. Compatibility: BACKWARD
When incompatible:
Schema ru.rudikov.example.Example is not compatible with subject my-topic-value. Compatibility: BACKWARD
→ {errorType:'TYPE_MISMATCH', description:'The type (path '/fields/0/type') of a field in the new schema does not match with the old schema', additionalInfo:'reader type: STRING not compatible with writer type: INT'}
./gradlew checkCompatibility --subject=my-topic-value --schema=MyRecord --compatibility=BACKWARDNotes:
- If subject does not exist in Schema Registry — task fails with error
- If schema file is not found — task fails with error
Use a test Schema Registry instance:
# Run via Docker
docker run -d --name schema-registry -p 8081:8081 confluentinc/cp-schema-registry:latestThe plugin is tested using built-in test framework. See examples:
Detailed schema evolution and compatibility check examples:
All compatible/incompatible change types are tested against Confluent Schema Registry 8.4.0 (confluentinc/cp-schema-registry:8.4.0, see BaseTaskTest).
📖 Confluent Docs: Schema Evolution
Cause: .avsc or .avpr file not found in specified directory.
Solution:
topic("my-topic") {
// Specify correct path to files
searchAvroFilePath.set("$projectDir/src/main/resources/avro")
schema.set("MyRecord") // Ensure MyRecord.avsc exists
}Cause: Invalid subject naming strategy specified.
Solution: Use one of the allowed values:
TopicNameStrategyRecordNameStrategyTopicRecordNameStrategy
Cause: No topics configured in configs.
Solution:
avroWizardConfig {
configs {
topic("my-topic") {
schema.set("MyRecord")
}
}
}Cause: Incorrect URL or service unavailable.
Solution:
- Verify
schemaRegistryUrlin configuration - Ensure Schema Registry is running and accessible
- Check network settings and firewall
Cause: Non-cacheable elements in configuration.
Solution: Since version 3.3.0, the plugin fully supports Configuration Cache. If issues occur:
./gradlew build --configuration-cache --refresh-configuration-cache- name: Register Avro Schemas
run: ./gradlew registerAllSchemas
env:
SCHEMA_REGISTRY_URL: ${{ secrets.SCHEMA_REGISTRY_URL }}
- name: Check Compatibility
run: ./gradlew checkCompatibility --compatibility=BACKWARDavro-check:
script:
- ./gradlew checkCompatibility --compatibility=BACKWARD
variables:
SCHEMA_REGISTRY_URL: $SCHEMA_REGISTRY_URLFeel free to open issues or submit pull requests for any bugs/improvements.
This plugin is licensed under the MIT License — see the LICENSE file for details.