A multi-language Protocol Buffer code generation and release management project using Maven. This project demonstrates how to generate gRPC/protobuf code for Java, Go, Python, and Rust from a single .proto definition, and deploy the generated artifacts to a local Nexus repository.
- Multi-language protobuf compilation: Generate gRPC stubs and protobuf messages for Java, Go, Python, and Rust
- Centralized version management: Maven manages versions across all language targets
- Local Nexus deployment: Deploy Maven JARs, Python packages (PyPI), Go modules, and Rust crates to a local Nexus repository
- Automated Go module versioning: Go modules are automatically versioned based on Maven project version
- JReleaser integration: Automated GitHub releases with changelog generation, replacing
maven-release-plugin
.
├── pom.xml # Parent POM with shared configuration
├── manage.go # Go utility for module version management
├── hello/ # Example service module
│ ├── pom.xml
│ ├── src/main/protobuf/ # Proto definitions
│ │ └── hello.proto
│ └── rust/ # Rust crate (optional)
│ ├── Cargo.toml
│ └── src/
├── services-parent/ # Parent POM for service modules
│ ├── pom.xml # Plugin configurations for all languages
│ ├── go/ # Generated Go code
│ └── setup.py.template # Python package template
└── settings.xml # Maven settings for Nexus integration
This project uses SDKMAN! for Java and Maven version management. Install SDKMAN:
curl -s "https://get.sdkman.io" | bashThen install the required versions:
sdk env installThis will install the versions specified in .sdkmanrc:
- Java 21 (Temurin)
- Maven 3.9.9
Aqua manages Go and protobuf code generators.
# macOS (Homebrew)
brew install aquaproj/aqua/aqua
# Linux / macOS (Shell script)
curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v3.1.1/aqua-installer | bash
# Windows (Scoop)
scoop install aquaaqua installThis installs tools defined in aqua.yaml:
| Tool | Version | Purpose |
|---|---|---|
go |
1.22.5 | Go runtime |
protoc-gen-go |
1.36.1 | Go protobuf code generator |
protoc-gen-go-grpc |
1.5.1 | Go gRPC code generator |
Note: The
protoccompiler is automatically downloaded by the Maven protobuf plugin during build.
For Rust code generation, install Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default stablePython 3 with pip is required for Python code generation:
pip install grpcio-tools build twineA local Nexus Repository Manager is required for artifact deployment. See nexus-data/READMe.md for setup instructions.
mvn clean compileThis will:
- Generate Java protobuf/gRPC code
- Generate Go protobuf/gRPC code (versioned modules)
- Generate Python protobuf/gRPC code
- Compile Rust crate (if present)
mvn packageCreates:
- Java JAR files
- Python wheel and source distributions
export NEXUS_USER=admin
export NEXUS_PASSWORD=your-password
mvn deploy -s settings.xmlDeploys:
- Java JARs to Maven repository
- Python packages to PyPI repository
- Rust crates to Cargo registry (if present)
This project uses JReleaser with the versions-maven-plugin to manage releases, replacing the traditional maven-release-plugin.
| maven-release-plugin | JReleaser + versions-maven-plugin |
|---|---|
mvn release:prepare |
mvn versions:set -DremoveSnapshot + mvn jreleaser:release |
mvn release:perform |
mvn deploy (artifacts already built) |
JReleaser handles most of the release process automatically via hooks in jreleaser.yml:
| Step | Handled By |
|---|---|
| Commit release version | JReleaser before hook |
| Create Git tag | JReleaser |
| Create GitHub Release | JReleaser |
| Generate changelog | JReleaser |
| Create Go module tags | JReleaser success hook |
| Set next SNAPSHOT | JReleaser success hook |
| Commit & push | JReleaser success hook |
# Step 1: Remove SNAPSHOT (must be done before JReleaser reads version)
mvn versions:set -DremoveSnapshot -DprocessAllModules && mvn versions:commit
# Step 2: JReleaser handles everything else!
export JRELEASER_GITHUB_TOKEN=ghp_your_token_here
mvn jreleaser:releaseThis will automatically:
- ✅ Commit:
[release] prepare release v1.7 - ✅ Create Git tag
v1.7 - ✅ Create GitHub Release with auto-generated changelog
- ✅ Create Go module tags (e.g.,
hello/go/v1.7) - ✅ Set next SNAPSHOT version (e.g.,
1.8-SNAPSHOT) - ✅ Commit:
[release] prepare for next development iteration - ✅ Push to
main
mvn versions:set -DremoveSnapshot -DprocessAllModules && mvn versions:commit && \
JRELEASER_GITHUB_TOKEN=ghp_xxx mvn jreleaser:releasemvn versions:set -DremoveSnapshot -DprocessAllModules && mvn versions:commit && \
mvn clean package -DskipTests && \
JRELEASER_GITHUB_TOKEN=ghp_xxx mvn jreleaser:release| Goal | Description |
|---|---|
mvn jreleaser:config |
Display current configuration |
mvn jreleaser:release |
Create Git tag + GitHub release |
mvn jreleaser:full-release |
Full release including announcements |
mvn jreleaser:changelog |
Generate changelog only |
Test the release without making changes:
mvn jreleaser:release -Djreleaser.dry.run=trueThis project includes GitHub Actions workflows for automated releases.
Trigger a release manually from the GitHub Actions UI:
- Go to Actions → Release → Run workflow
- Click Run workflow (no inputs required - versions are calculated automatically!)
- The workflow will:
- Strip
-SNAPSHOTviaversions:set -DremoveSnapshot - Build artifacts
- Run JReleaser which handles:
- Commit:
[release] prepare release vX.Y - Create Git tag + GitHub Release
- Create Go module tags
- Set next SNAPSHOT via
versions:set -DnextSnapshot - Commit:
[release] prepare for next development iteration - Push to main
- Commit:
- Strip
Push a version tag to trigger a release:
git tag v1.7
git push origin v1.7This will:
- Create Go module tags automatically
- Build all artifacts
- Create a GitHub Release using JReleaser
Configure these secrets in your repository settings:
| Secret | Description |
|---|---|
NEXUS_USER |
Nexus repository username (optional) |
NEXUS_PASSWORD |
Nexus repository password (optional) |
Note:
GITHUB_TOKENis automatically provided by GitHub Actions.
Copy settings.xml to ~/.m2/settings.xml or use -s settings.xml flag:
<servers>
<server>
<id>local-nexus</id>
<username>${NEXUS_USER}</username>
<password>${NEXUS_PASSWORD}</password>
</server>
</servers>| Variable | Description |
|---|---|
NEXUS_USER |
Nexus repository username |
NEXUS_PASSWORD |
Nexus repository password |
- Create a new directory under the project root:
mkdir -p my-service/src/main/protobuf-
Add your
.protofile(s) tomy-service/src/main/protobuf/ -
Create
my-service/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example.jreleaser</groupId>
<artifactId>services-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../services-parent</relativePath>
</parent>
<artifactId>my-service</artifactId>
<build>
<plugins>
<plugin>
<groupId>io.github.ascopes</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>- Add the module to the root
pom.xml:
<modules>
<module>hello</module>
<module>my-service</module>
<module>services-parent</module>
</modules>The manage.go utility handles Go module versioning automatically:
- Extracts major version from Maven
pom.xml - Creates versioned directories (
go/v1,go/v2, etc.) - Updates
go.modmodule paths for major version changes
Run manually if needed:
go run manage.go upgrade-mod services-parent
go run manage.go clean services-parent/go- Protobuf 4.33.1
- gRPC 1.77.0
- Guava 33.5.0-jre
- tonic 0.14.2
- prost 0.14.1
- tokio 1.48.0
MIT License - see LICENSE for details.