{"id":41612717,"url":"https://github.com/esurdam/go-grpc-bazel-example","last_synced_at":"2026-01-24T12:20:08.482Z","repository":{"id":296178051,"uuid":"370238607","full_name":"esurdam/go-grpc-bazel-example","owner":"esurdam","description":"Example monorepo for scalable Go microservices with gRPC and Bazel, including REST, Swagger, Docker, and Kubernetes.","archived":false,"fork":false,"pushed_at":"2025-11-04T10:08:12.000Z","size":227,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-04T10:18:18.785Z","etag":null,"topics":["bazel","docker","example","go","golang","grpc","grpc-gateway","kubernetes","microservices","monorepo","openapi","protobuf","reference-architecture","swagger"],"latest_commit_sha":null,"homepage":"","language":"Starlark","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/esurdam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-05-24T05:32:35.000Z","updated_at":"2025-11-04T10:07:09.000Z","dependencies_parsed_at":"2025-06-03T02:03:15.185Z","dependency_job_id":null,"html_url":"https://github.com/esurdam/go-grpc-bazel-example","commit_stats":null,"previous_names":["esurdam/go-grpc-bazel-example"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/esurdam/go-grpc-bazel-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esurdam%2Fgo-grpc-bazel-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esurdam%2Fgo-grpc-bazel-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esurdam%2Fgo-grpc-bazel-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esurdam%2Fgo-grpc-bazel-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/esurdam","download_url":"https://codeload.github.com/esurdam/go-grpc-bazel-example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/esurdam%2Fgo-grpc-bazel-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28727532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bazel","docker","example","go","golang","grpc","grpc-gateway","kubernetes","microservices","monorepo","openapi","protobuf","reference-architecture","swagger"],"created_at":"2026-01-24T12:20:07.812Z","updated_at":"2026-01-24T12:20:08.467Z","avatar_url":"https://github.com/esurdam.png","language":"Starlark","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-grpc-bazel-example\n\n[![test](https://github.com/esurdam/go-grpc-bazel-example/actions/workflows/go.yml/badge.svg)](https://github.com/esurdam/go-grpc-bazel-example/actions/workflows/go.yml)\n\n## Project Overview\n\nThis repository demonstrates a modern monorepo setup for building scalable gRPC microservices in Go, using Bazel for reproducible builds and dependency management. It provides a reference architecture for teams looking to:\n- Share protobuf definitions and implementations across services\n- Use Bazel for fast, hermetic builds and CI/CD\n- Integrate gRPC, REST (via grpc-gateway), and OpenAPI/Swagger documentation\n- Deploy services to Kubernetes and container registries\n\nThe example service, `helloworld`, showcases the recommended project structure, build rules, and development workflow.\n\n## Features\n\n- **Monorepo structure** for multiple Go microservices\n- **gRPC** and **grpc-gateway** for both gRPC and RESTful APIs\n- **Bazel** for fast, reproducible builds and dependency management\n- **Protobuf** definitions and code generation\n- **OpenAPI/Swagger** documentation generation\n- **Docker/OCI** image builds and publishing\n- **Kubernetes** deployment manifests and scripts\n- **CI/CD** with GitHub Actions\n\n## Quickstart\n\nFollow these steps to get the example service running locally:\n\n1. **Install Prerequisites**\n   - [Go](https://golang.org/doc/install) (\u003e= 1.23)\n   - [Bazel](https://docs.bazel.build/versions/master/install.html) (tested with 8.2.1)\n   - [Docker](https://www.docker.com/) (optional, for container builds)\n\n2. **Clone the Repository**\n   ```bash\n   git clone https://github.com/esurdam/go-grpc-bazel-example.git\n   cd go-grpc-bazel-example\n   ```\n\n3. **Generate Protobuf and Build Files**\n   ```bash\n   make link      # Generates protobuf Go code for local development (optional)\n   ```\n\n4. **Run Tests**\n   ```bash\n   make test\n   ```\n\n5. **Run the Example Service Locally**\n   - Generate self-signed TLS certificates:\n     ```bash\n     mkdir -p ssl\n     go run $GOROOT/src/crypto/tls/generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,localhost,localhost:4443 --ca --start-date \"Jan 1 00:00:00 1970\" --duration=1000000h -certfile ssl/cert.pem -keyfile ssl/key.pem\n     ```\n   - Start the service:\n     ```bash\n     bazel run //services/helloworld:helloworld -- -http-port 4443 -cert $(pwd)/ssl/cert.pem -key $(pwd)/ssl/key.pem\n     ```\n   - Test with cURL:\n     ```bash\n     curl -X POST -k https://localhost:4443/v1/greeter -d '{\"name\": \"TestName\"}'\n     ```\n\n6. **View Swagger/OpenAPI Docs**\n   - Open [https://localhost:4443/swagger.json](https://localhost:4443/swagger.json) in your browser.\n\n_For more details, see the sections below._\n\n## Project Layout\n\n```\n.github/     # github Action CI configs\nci/          # contains ci/automation scripts\ncmd/         # command line tool entrypoints\npb/          # contains all proto definitions and gen output\npkg/         # contains proto implementations\nservices/    # entrypoints for kubernetes defined microservices\ntools/       # tool versioning\nBUILD        # root bazel BUILD definitions; aggregates services\nWORKSPACE    # bazel workspace rules; external code \n```\n\n## Requirements\n\n- Go (\u003e= 1.23)\n- Bazel (tested with 8.2.1)\n\n## Development Workflow\n\n### Creating a New Service\n\n1. Create proto file and define types/service:\n   ```bash\n   touch pb/helloworld/helloworld.proto # Add definitions to this file\n   ```\n2. Generate `BUILD.bazel` files and add generated files locally:\n   ```bash\n   make gazelle\n   make link\n   ```\n3. Implement proto service in `pkg`:\n   ```bash\n   mkdir -p pkg/helloworld/server\n   touch pkg/helloworld/server/server.go\n   ```\n4. Create service entrypoint in `services`:\n   ```bash\n   mkdir services/helloworld\n   touch services/helloworld/main.go\n   ```\n5. Define kubernetes service in `ci/services`:\n   ```bash\n   touch ci/services/helloworld.yaml\n   ```\n6. Add the service definition to aggregate rule in `BUILD`.\n\nExample service scaffold:\n```\nproject   \n│\n└───ci\n│   └───services\n│       │   helloworld.yaml\n│\n└───pb\n│   └───helloworld\n│       │   helloworld.proto\n│   \n└───pkg\n│   └───helloworld\n│       └───server\n│           │   server.go\n|\n└───services\n│   └───helloworld\n│       │   main.go\n|\n```\n\n### Generating BUILD Files\n\nRun `make gazelle` to generate/update BUILD files (which include test and binaries). This also updates the WORKSPACE with required deps. BUILD.bazel files located in pb directory will contain grpc rules.\n\n### Generating Proto Files\n\nUse JetBrains/VSCode plugin to handle the Bazel workspace to not require local files for development. \n\nGenerated files don't necessarily need to be checked in to repo. Bazel will handle generating the pb file during build. \n\nIt is generally a good idea to track changes to pb in repo.\n\n```bash\nmake link\n```\n\n### Testing\n\nTo run all tests:\n\n```bash\nmake test\n```\n\nTest individual package:\n\n```bash\nbazel test --@rules_go//go/config:race \\\n  --verbose_failures \\\n  --test_output=errors \\\n  //pkg/helloworld/server:server_test\n```\n\nTests can also be aggregated into test groups to be tested at once.\n\n### Running Locally\n\nGenerate a self-signed certificate (cert.pem \u0026 key.pem) to run services locally. Required for multiplexing grpc/http2 over single port. \n\n```bash\nmkdir -p ssl \u0026\u0026 \\\n  (cd ssl \u0026\u0026 \\\n    go run $GOROOT/src/crypto/tls/generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,localhost,localhost:443,localhost:4443 --ca --start-date \"Jan 1 00:00:00 1970\" --duration=1000000h)\n```\n\nUse bazel to run the service\n```bash\nbazel run //services/helloworld:helloworld -- -http-port 4443 -cert $(pwd)/ssl/cert.pem -key $(pwd)/ssl/key.pem\n```\n\nThen we use cURL to send HTTP requests\n\n```bash\ncurl -X POST -k https://localhost:4443/v1/greeter -d '{\"name\": \"TestName\"}'\n```\n\nYou can view the swagger at [https://localhost:4443/swagger.json](https://localhost:4443/swagger.json)\n\nOr use the client:\nWith the server running, you can test command line tools from `cmd`.\n```bash\n$ bazel run //cmd/helloworld-client -- \\\n    --name \"Beutiful\" \\\n    --server-addr localhost:4443 \\\n    --ca-cert $(pwd)/ssl/cert.pem\n\nINFO: Analyzed target //cmd/helloworld-client:helloworld-client (0 packages loaded, 0 targets configured).\nINFO: Found 1 target...\nTarget //cmd/helloworld-client:helloworld-client up-to-date:\n  bazel-bin/cmd/helloworld-client/helloworld-client_/helloworld-client\nINFO: Elapsed time: 0.365s, Critical Path: 0.00s\nINFO: 1 process: 1 internal.\nINFO: Build completed successfully, 1 total action\nINFO: Running command line: bazel-bin/cmd/helloworld-client/helloworld-client_/helloworld-client --name 'Beutiful' --server-addr localhost:4443 --cert ...\nINFO: Build completed successfully, 1 total action\n\n2022/10/22 18:03:59 message:\"Hello Beutiful!\"\n```\n\n### Running with Docker\n\n```\noci_load(\n    name = \"load\",\n    # Use the image built for the target platform\n    image = \":transitioned_image\",\n    repo_tags = [\"ghcr.io/esurdam/go-grpc-bazel-example/cmd/helloworld-client:latest\"],\n)\n```\n\nFor example, to load tarball with current architecture:\n```bash\nbazel run //services/helloworld:load\n\n# Run the loaded image\ndocker run --rm -v $(pwd)/ssl:/ssl -p 4443:4443 ghcr.io/esurdam/go-grpc-bazel-example/services/helloworld:latest --http-port 4443 --cert /ssl/cert.pem --key /ssl/key.pem\n```\n\narch example:\n```bash\n bazel run \\\n  --platforms=@rules_go//go/toolchain:linux_amd64 \\\n  --cpu=k8 \\\n  //services/helloworld:load\n```\n\n## Swagger + JSON Gateway\n\nServices may utilize `grpc-gateway` for a JSON-to-GRPC proxy. This is autogenerated with the `gateway_grpc_library` rule. Swagger json is autogenerated via the `gateway_openapiv2_compile` rule.\n\n```\nload(\"@rules_proto_grpc//grpc-gateway:defs.bzl\", \"gateway_grpc_compile\", \"gateway_grpc_library\", \"gateway_openapiv2_compile\")\n\ngateway_grpc_library(\n    name = \"helloworld_gateway_lib_proto\",\n    importpath = \"github.com/esurdam/go-grpc-bazel-example/pb/helloworld\",\n    protos = [\":helloworld_proto\"],\n    visibility = [\"//visibility:public\"],\n)\n\ngateway_openapiv2_compile(\n    name = \"helloworld_gateway_grpc\",\n    protos = [\":helloworld_proto\"],\n    visibility = [\"//visibility:public\"],\n)\n```\n\nServices can then use the `embed` rule to embed the `swagger.json` compiled output.\n\nView the `genrule` in [BUILD.bazel](services/helloworld/BUILD.bazel)\n\n```\n//go:embed helloworld_openapi_swagger.json\nvar Data []byte\n```\n\nServices can then expose the `swagger.json` file directly.\n\n## Deployment\n\n### Pushing to Container Registry\n\nUsed to deploy a service to the container registry.\n\nEach service should contain a `oci_push` rule, which defines the container registry and stamped image. The `:transitioned_image` contains multi-arch capabilites. \n\n```\noci_push(\n    name = \"push\",\n    image = \":transitioned_image\",\n    remote_tags = \":stamped\",\n    repository = \"ghcr.io/esurdam/go-grpc-bazel-example/cmd/helloworld-client\",\n    visibility = [\"//visibility:public\"],\n)\n```\n\nTo push an individual service (where version is the container label):\n\nIterates through all `:push` targets and pushes to the container registry.\n```bash\nmake push\n```\n\ne.g.\n```bash\nbazel run \\\n  --cpu=k8 \\\n  //services/helloworld:push\n```\n\nSee [ci/push-service.sh](ci/push-service.sh)\n\n### Kubernetes Deployment\n\nSince [rules_docker](https://github.com/bazelbuild/rules_docker?) has been deprecated, we can no longer use the `k8s_deploy` rule to deploy to k8s. Instead, we can use the `oci_push` rule to push the image to the container registry, and then use `kubectl` to apply the deployment.\n\nIterates through all `:push` targets, uses the stamp to update the image tag and applies the k8s deployment.\n```bash\nmake deploy\n```\n\nSee [ci/deploy.sh](ci/deploy.sh)\n\n## Useful Links\n\n**GRPC**\n\n- [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway)\n\n**Bazelbuild rules**\n\n- [bazel central registry](https://registry.bazel.build)\n- [rules_oci](https://github.com/bazel-contrib/rules_oci/tree/main)\n- [rules_docker](https://github.com/bazelbuild/rules_docker)\n- [rules_go](https://github.com/bazelbuild/rules_go)\n- [rules_k8s](https://github.com/bazelbuild/rules_k8s)\n- [rules_proto](https://github.com/bazelbuild/rules_proto)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesurdam%2Fgo-grpc-bazel-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesurdam%2Fgo-grpc-bazel-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesurdam%2Fgo-grpc-bazel-example/lists"}