OpenAPI Spec Generation
Issue: #263 - Agentic Chat
Overview
The openapi.yaml file is automatically generated from Protocol Buffer definitions during the Maven build process. This ensures the OpenAPI spec is always in sync with your gRPC services.
How It Works
Automatic Generation (Maven Build)
During mvn compile, the build process:
- Checks for protoc-gen-openapiv2 tool
- If found: Generates
openapi.yamlfrom all.protofiles - If not found: Uses existing
openapi.yaml(fallback) - Copies the spec to
src/main/resources/for packaging in JAR
Configuration: See pom.xml → exec-maven-plugin → generate-openapi-spec execution
Output Files
target/generated-openapi/api.swagger.json ← Generated by protoc
target/generated-openapi/openapi.yaml ← Converted to YAML
openapi.yaml ← Project root (for local dev)
src/main/resources/openapi.yaml ← Packaged in JAR (for Cloud Run)
Installation (One-Time Setup)
To enable automatic OpenAPI generation during build:
Step 1: Install Go
# macOS
brew install go
# Linux (if not already installed in dev container)
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
Step 2: Install protoc-gen-openapiv2
# Add Go bin to PATH
export PATH="$PATH:$HOME/go/bin"
# Install the protoc plugin
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
# Verify installation
which protoc-gen-openapiv2
protoc-gen-openapiv2 --version
Step 3: Install Python YAML (Optional - for JSON → YAML conversion)
pip3 install pyyaml
Step 4: Test Generation
# Clean build with OpenAPI generation
export JAVA_HOME=/usr/lib/jvm/temurin-23-jdk-arm64
export PATH="$PATH:$HOME/go/bin"
mvn clean compile -DskipTests
Expected output:
[OpenAPI] Generating OpenAPI spec from proto files...
[OpenAPI] Converting swagger.json to yaml...
[OpenAPI] ✓ Generated openapi.yaml (includes ChatService endpoints)
Verification
After build, verify ChatService endpoints are included:
# Check for chat endpoints
grep -A 3 "/v1/chat/sessions" openapi.yaml
# Should show:
# /v1/chat/sessions:
# post:
# operationId: ChatService_CreateSession
Manual Generation (Alternative)
If you need to generate OpenAPI spec without Maven:
# Set up paths
export PATH="$PATH:$HOME/go/bin"
PROTO_DIR="src/main/proto"
GOOGLEAPIS_DIR="env/dependencies/googleapis"
OUTPUT_DIR="target/generated-openapi"
# Generate
mkdir -p $OUTPUT_DIR
protoc \
--proto_path=$PROTO_DIR \
--proto_path=$GOOGLEAPIS_DIR \
--openapiv2_out=$OUTPUT_DIR \
--openapiv2_opt=logtostderr=true \
--openapiv2_opt=allow_merge=true \
--openapiv2_opt=merge_file_name=api \
$PROTO_DIR/*.proto
# Copy to project
cp $OUTPUT_DIR/api.swagger.json openapi.json
# Or convert to YAML
python3 -c "import json, yaml; yaml.dump(json.load(open('$OUTPUT_DIR/api.swagger.json')), open('openapi.yaml', 'w'), default_flow_style=False, sort_keys=False)"
ChatService Endpoints
After regeneration, openapi.yaml will include:
paths:
/v1/chat/sessions:
post:
operationId: ChatService_CreateSession
summary: Create a new chat session
# ...
/v1/chat/sessions/{session_id}:
get:
operationId: ChatService_GetSessionHistory
summary: Get chat session history with messages
# ...
delete:
operationId: ChatService_DeleteSession
summary: Delete a chat session (soft delete)
# ...
/v1/chat/sessions/{session_id}/stream:
post:
operationId: ChatService_StreamChat
summary: Stream chat messages from the AI agent
# ...
CI/CD Integration
GitHub Actions / Cloud Build
Add to your build pipeline:
# Install Go and protoc tools
- name: Install Go tools
run: |
export PATH="$PATH:/usr/local/go/bin:$HOME/go/bin"
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
# Build will automatically generate openapi.yaml
- name: Build
run: |
export PATH="$PATH:$HOME/go/bin"
mvn clean package -DskipTests
Docker Build
The Dockerfile should include Go tools:
# Install Go tools in builder stage
RUN go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
ENV PATH="$PATH:/go/bin"
# Build will generate openapi.yaml automatically
RUN mvn clean package -DskipTests
Troubleshooting
Issue: "protoc-gen-openapiv2 not found"
Solution: Install the tool:
export PATH="$PATH:$HOME/go/bin"
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
Issue: "Python yaml module not found"
Solution: Install PyYAML or use JSON:
pip3 install pyyaml
Or just use the JSON file:
# ChatAgentService can load JSON too
cp target/generated-openapi/api.swagger.json src/main/resources/openapi.json
Issue: Generated spec doesn't include ChatService
Check: Make sure chat.proto has gRPC-Gateway annotations:
import "google/api/annotations.proto";
service ChatService {
rpc StreamChat(...) returns (stream ...) {
option (google.api.http) = {
post: "/v1/chat/sessions/{session_id}/stream"
body: "*"
};
}
}
Fallback Mode
If protoc-gen-openapiv2 is not installed, the build will:
- ✅ Continue without error
- ⚠️ Skip OpenAPI generation
- ✅ Copy existing
openapi.yamlto resources - ✅ Build succeeds
This allows builds to work in environments without Go tools installed, using the last-generated spec.
Best Practices
- Always regenerate after proto changes: Add new services or modify existing ones
- Commit generated openapi.yaml: Check it into git so CI/CD has a fallback
- Verify endpoints: After regeneration, check that all expected endpoints are present
- Test locally: Use openapi.yaml with tools like Postman or Swagger UI
Next: After generating openapi.yaml with ChatService endpoints, redeploy to Cloud Run