Contract Distribution Migration
Migrate proto modules to proper contract distribution with proto-only and -generated module split.
Purpose
Migrate proto modules from incorrect distribution (compiled code + dependencies) to proper contract distribution (proto-only artifacts). This ensures:
- External consumers can compile protos with their own gRPC versions
- No transitive dependency conflicts
- RFC-33 compliance
Skill Contents
Sections
- Purpose
- Prerequisites
- CRITICAL: Proto File Location and Package Naming
- Module Structure Transformation
- Migration Steps
- Migration Checklist
- Common Pitfalls
- Troubleshooting
- External Consumer Migration
- References
Available Resources
π references/ - Detailed documentation
Prerequisites
The grpc-compliance-validate-repository command must be available for the migration checklist validation step.
Cloud agents: Pre-installed (no action needed).
Local setup:
export HOMEBREW_GITHUB_API_TOKEN=your-token
brew tap bitsoex/homebrew-bitso
brew install bitso-grpc-linter
Verify: grpc-compliance-validate-repository --help
See ../grpc-services-rfc-33/references/installation.md for details.
CRITICAL: Proto File Location and Package Naming
File Location
Proto files MUST be in src/main/resources/ following the package structure:
- Correct:
package com.bitso.account.v1;βsrc/main/resources/com/bitso/account/v1/account.proto - Incorrect:
src/main/proto/account.protoorsrc/main/resources/proto/account.proto
Package Naming: Existing vs NEW Protos
β οΈ IMPORTANT: Different rules for existing vs new protos
| Proto Type | Package Rule | Example |
|------------|--------------|---------|
| EXISTING (being moved) | Keep original package for backwards compatibility | Keep package protos.model; if that's what it has |
| NEW (V2 services, new messages) | Use project-specific package | package com.bitso.{service}.v2; |
For EXISTING protos being moved:
// Keep the existing package - DO NOT CHANGE
syntax = "proto3";
package protos.model; // Keep this even though it's generic
option java_package = "com.bitso.iba.model";
// Just move to: src/main/resources/protos/model/
For NEW protos (V2 services, new error types):
// Use project-specific package - DO NOT use protos.model
syntax = "proto3";
package com.bitso.iba.rate.v2; // Project-specific
option java_package = "com.bitso.iba.rate.v2";
// Place in: src/main/resources/com/bitso/iba/rate/v2/
Determine project package convention by:
- Check existing Java packages in the codebase (e.g.,
com.bitso.iba.grpc.service) - Use the same root package structure for new proto contracts
Module Structure Transformation
Before (Incorrect)
project-root/
βββ account-protos/
β βββ build.gradle # Has protobuf plugin + dependencies
β βββ src/main/proto/ # Wrong location
β βββ account.proto
After (Correct)
project-root/
βββ account-protos/
β βββ build.gradle # NO protobuf plugin, NO dependencies
β βββ src/main/resources/ # Correct location
β βββ com/bitso/account/v1/ # Follows package structure
β βββ account.proto
βββ account-protos-generated/
β βββ build.gradle # Has protobuf plugin (internal only)
Migration Steps
Step 1: Move Proto Files to Follow Package Structure
# Example: package com.bitso.account.v1;
mkdir -p proto-module/src/main/resources/com/bitso/account/v1
mv proto-module/src/main/proto/*.proto proto-module/src/main/resources/com/bitso/account/v1/
rm -rf proto-module/src/main/proto
Step 2: Remove Protobuf Compilation from Proto-Only Module
Edit the proto-only module's build.gradle:
- Remove
com.google.protobufplugin - Remove all gRPC/protobuf dependencies
- Remove
protobuf {}configuration block
See references/BUILD_EXAMPLES.md for configuration templates.
Step 3: Create New -generated Module
mkdir -p proto-module-generated/src/main/java
# Create build.gradle with protobuf compilation config
See references/BUILD_EXAMPLES.md for the complete generated module configuration.
Step 4: Update All Project References
// Before
dependencies {
implementation project(':proto-module')
}
// After
dependencies {
implementation project(':proto-module-generated')
}
Step 5: Update settings.gradle
include 'proto-module'
include 'proto-module-generated' // NEW
Step 6: MANDATORY - Bump MAJOR Version in Protobuf Module
This step is NON-NEGOTIABLE. Contract distribution migration is a BREAKING CHANGE.
Update the version in the protobuf module's gradle.properties file:
# File: {proto-module}/gradle.properties
# Before: version=1.2.3
# After: version=2.0.0 (BREAKING CHANGE - MAJOR bump required)
# {proto-module}/gradle.properties
version=2.0.0
Why MAJOR version bump is mandatory:
- External consumers depend on the published proto-only module
- After migration, consumers must compile protos themselves (breaking workflow change)
- Proto files moved from compiled JAR to resources-only JAR
- gRPC/protobuf dependencies removed from published artifact
- Semantic versioning REQUIRES major bump for breaking changes
Failure to bump MAJOR version will cause:
- Silent breakage for external consumers
- Runtime ClassNotFoundException/NoSuchMethodError in downstream services
- Extremely difficult debugging and rollback scenarios
- RFC-33 compliance violations
Migration Checklist
Proto Module Updates
- [ ] Move proto files to
src/main/resources/{package/path}/matching package declaration - [ ] Delete old
src/main/proto/directory - [ ] Remove protobuf plugin from proto-only module
- [ ] Remove all gRPC/protobuf dependencies from proto-only module
- [ ] Remove
protobuf {}configuration from proto-only module
Generated Module Creation
- [ ] Create new
-generatedmodule directory - [ ] Configure protobuf compilation in
-generatedmodule - [ ] Make
-generateddepend on proto-only viaproject(':proto-module') - [ ] Update
settings.gradleto include-generatedmodule
Reference Updates
- [ ] Find and replace all
project(':proto-module')withproject(':proto-module-generated') - [ ] Verify proto-only module has zero dependencies
- [ ] Ensure only proto-only module is published (not
-generated) - [ ] Remove API/protoshim artifacts if present
Version Management (MANDATORY)
- [ ] CRITICAL: Bump MAJOR version in protobuf module's
gradle.properties(e.g., 1.2.3 β 2.0.0) - [ ] Location:
{proto-module}/gradle.properties - [ ] DO NOT proceed to PR creation without completing this step
Build Verification (MANDATORY)
- [ ] Run
./gradlew clean build - [ ] IF BUILD FAILS: Analyze errors, fix issues, repeat until SUCCESS
- [ ] Common fixes: wrong project references, missing imports, proto not regenerated
Validation
- [ ] Run
grpc-compliance-validate-repository --dir .and verify no ERRORS - [ ] Run
./gradlew test - [ ] β οΈ Only create PR after build passes
Common Pitfalls
Proto Files in Wrong Location
- Correct:
src/main/resources/com/bitso/account/v1/account.proto - Incorrect:
src/main/proto/account.proto
Not Bumping MAJOR Version (CRITICAL ERROR)
- gRPC migration is ALWAYS a breaking change - MAJOR version bump is mandatory
- Contract distribution changes break external consumers' build process
- Using MINOR/PATCH for contract changes violates semantic versioning
- This mistake causes production incidents in downstream services
Publishing -generated Modules
- Only publish proto-only modules
- Never publish
-generatedmodules to artifact repository
Troubleshooting
Proto files not found during compilation
- Verify proto files are in
src/main/resources/{package/path}/ - Check package declaration matches directory structure
- Ensure proto-only module is a dependency of -generated module
Consumer can't compile protos
- Verify proto-only module is published (not -generated)
- Check proto files are in JAR resources:
jar tf account-protos-2.0.0.jar | grep .proto
External Consumer Migration
After migration, external consumers must:
- Add protobuf plugin to their build
- Add gRPC dependencies
- Configure proto compilation
See references/BUILD_EXAMPLES.md for consumer configuration template.
References
references/BUILD_EXAMPLES.md- Complete Gradle configuration examples- RFC-33: gRPC Service Standards