CI/CD for a gRPC Service with GitHub Actions
Lint your protos, detect breaking changes, and ship your gRPC service.
A gRPC service is defined by .proto files, so CI should lint them and catch breaking API changes before generating code. This recipe uses Buf to lint and check breaking changes, then builds and tests the service.
What the pipeline does
- lint protos with buf lint
- check for breaking changes against main
- generate code with buf generate
- run service tests
- build and push a Docker image
The workflow
buf breaking compares against the main branch so an incompatible proto change fails the PR. After codegen, build and test the service in your language of choice.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
proto:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: bufbuild/buf-action@v1
with:
lint: true
breaking: true
breaking_against: 'https://github.com/${{ github.repository }}.git#branch=main'
- run: buf generate
- run: echo "build and test the generated service here"Caching and speed
Cache the language toolchain caches (Go module cache, Cargo, npm, or Gradle depending on your stack) and the Buf cache. Codegen is fast; the service build and Docker image are the slow steps, where cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) save time and auto-retry transient registry pushes.
Deploying
Push the service image to a registry and deploy to Kubernetes (with a gRPC-aware ingress or service mesh), ECS, or Cloud Run with HTTP/2 enabled. Publish generated client stubs to a package registry so consumers stay in sync with the proto contract.
Key takeaways
- Use buf lint and buf breaking to gate proto changes.
- Run breaking checks against the main branch.
- Publish generated stubs so clients stay in sync.