diff --git a/README.md b/README.md index 10705b3..521dbf3 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,89 @@ # cookiecutter-coldbrew -Powered by [Cookiecutter](https://github.com/audreyr/cookiecutter), Cookiecutter Coldbrew is a framework for jumpstarting production-ready go projects quickly. +Powered by [Cookiecutter](https://github.com/cookiecutter/cookiecutter), Cookiecutter Coldbrew is a template for jumpstarting production-ready Go gRPC microservices with the [ColdBrew framework](https://docs.coldbrew.cloud). ## Features -- Generous `Makefile` with management commands -- injects build time and git hash at build time. -- Powered by [ColdBrew](https://docs.coldbrew.cloud) +- Complete gRPC service with HTTP/JSON gateway (grpc-gateway) +- Kubernetes health checks (liveness + readiness probes) +- Prometheus metrics, distributed tracing, structured logging +- Swagger UI for interactive API documentation +- Multi-stage Docker build for minimal production images +- CI/CD pipelines for GitHub Actions and GitLab CI +- golangci-lint v2 configuration with govulncheck +- Makefile with build, test, lint, benchmark, and run targets +- Build-time version injection (git commit, branch, date) -## Constraints +## Prerequisites -- Uses `mod` for dependency management -- Only maintained 3rd party libraries are used. -- Use multistage docker builds for super small docker images -- Make sure '$GOBIN' is set in PATH +Install [Cookiecutter](https://cookiecutter.readthedocs.io/): -## Docker - -This template uses docker multistage builds to make images slimmer and containers only the final project binary and assets with no source code whatsoever. - -## Usage +```shell +brew install cookiecutter +``` -Let's pretend you want to create a project called "echoserver". +Or via pip: -Rather than starting from scratch maybe copying some files and then editing the results to include your name, email, and various configuration issues that always get forgotten until the worst possible moment, get cookiecutter to do all the work. +```shell +pip install cookiecutter +``` -### Prerequisites -First, get Cookiecutter. Trust me, it's awesome: +## Usage ```shell -$ pip install cookiecutter +cookiecutter gh:go-coldbrew/cookiecutter-coldbrew ``` -Alternatively, you can install `cookiecutter` with homebrew: +Answer the prompts: ```shell -$ brew install cookiecutter +source_path [github.com/ankurs]: github.com/yourname +app_name [MyApp]: EchoServer +grpc_package [com.github.ankurs]: com.github.yourname +service_name [MySvc]: EchoSvc +project_short_description [A Golang project.]: My first ColdBrew service +docker_image [alpine:latest]: +docker_build_image [golang]: +Select docker_build_image_version: +1 - 1.26 +2 - 1.25 +Choose from 1, 2 [1]: 1 ``` -### Using the ColdBrew Cookiecutter Template -To run it based on this template, type: +Then build and run: ```shell -$ cookiecutter gh:go-coldbrew/cookiecutter-coldbrew +cd EchoServer/ +make run ``` -You will be asked about your basic info \(name, project name, app name, etc.\). This info will be used to customise your new project. +Your service starts on `:9090` (gRPC) and `:9091` (HTTP/Swagger). -### Providing your app information to the cookiecutter +For a full walkthrough, see the [Getting Started](https://docs.coldbrew.cloud/getting-started) guide. -Warning: After this point, change 'github.com/ankurs', 'MyApp', etc to your own information. +## CI/CD -Answer the prompts with your own desired options. For example: +The generated project includes ready-to-use CI pipelines for both platforms. Delete whichever you don't need. -```shell -source_path [github.com/ankurs]: github.com/ankurs -app_name [MyApp]: MyApp -grpc_package [github.com.ankurs]: github.com.ankurs -service_name [MySvc]: MySvc -project_short_description [A Golang project.]: A Golang project -docker_image [alpine:latest]: -docker_build_image [golang]: -Select docker_build_image_version: -1 - 1.19 -2 - 1.20 -Choose from 1, 2 [1]: 2 -``` +### GitHub Actions (`.github/workflows/go.yml`) -### Checkout your new project +Runs on push to `main`/`master` and on pull requests. Four parallel jobs: **build**, **test** (race detector + coverage), **benchmark**, and **lint** (govulncheck + golangci-lint). Each job has concurrency control to cancel duplicate runs. -Enter the project and take a look around: +### GitLab CI (`.gitlab-ci.yml`) -```shell -$ cd MyApp/ -$ ls -``` +Three jobs in a single `test` stage: **unit-test** (with Cobertura coverage report), **lint** (golangci-lint + govulncheck), and **benchmark**. Go module caching is enabled. + +## Docker -Run `make help` to see the available management commands, or just run `make build` to build your project. +Uses multi-stage builds: compiles a static Go binary in the builder stage, then copies it to a minimal Alpine image. Ports 9090 (gRPC) and 9091 (HTTP) are exposed. ```shell -$ make run +make build-docker +make run-docker ``` -### Working with your new project -Your project is now ready to be worked on. You can find the generated `README.md` file in the project root directory. It contains a lot of useful information about the project. You can also find the generated `Dockerfile` in the project root directory. It contains a lot of useful commands to build, test, and run your project. You can also find the generated `Makefile` in the project root directory. It contains a lot of useful commands to build, test, and run your project. You can run `make help` to see the available management commands. +## Documentation +- [Getting Started](https://docs.coldbrew.cloud/getting-started) — Full walkthrough +- [ColdBrew Documentation](https://docs.coldbrew.cloud) — Framework reference +- [How-To Guides](https://docs.coldbrew.cloud/howto/) — Tracing, logging, metrics, and more diff --git a/{{cookiecutter.app_name}}/.github/workflows/go.yml b/{{cookiecutter.app_name}}/.github/workflows/go.yml index e2b3b74..c30be71 100644 --- a/{{cookiecutter.app_name}}/.github/workflows/go.yml +++ b/{{cookiecutter.app_name}}/.github/workflows/go.yml @@ -11,7 +11,9 @@ on: jobs: build: - concurrency: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + concurrency: + group: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -24,7 +26,9 @@ jobs: run: make build test: - concurrency: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + concurrency: + group: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -35,9 +39,18 @@ jobs: cache: true - name: Test run: make test + - name: Generate coverage report + run: go tool gocover-cobertura < cover.out > cover.xml + - name: Upload coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: cover.xml benchmark: - concurrency: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + concurrency: + group: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -50,7 +63,9 @@ jobs: run: make bench lint: - concurrency: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + concurrency: + group: {% raw -%}ci-${{ github.job }}-${{ github.ref }}{%- endraw %} + cancel-in-progress: true runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/{{cookiecutter.app_name}}/AGENTS.md b/{{cookiecutter.app_name}}/AGENTS.md index b0a3e74..8ccba41 100644 --- a/{{cookiecutter.app_name}}/AGENTS.md +++ b/{{cookiecutter.app_name}}/AGENTS.md @@ -41,8 +41,12 @@ make run-docker # Run in Docker container │ └── version.go # Build-time version info (injected via ldflags) ├── third_party/ │ └── OpenAPI/ # Swagger UI assets (embedded via go:embed) +├── .github/workflows/ +│ └── go.yml # GitHub Actions CI (build, test, bench, lint) +├── .gitlab-ci.yml # GitLab CI (unit-test, lint, benchmark) ├── Makefile # Build automation ├── Dockerfile # Multi-stage Docker build +├── .golangci.yml # Linter configuration ├── buf.yaml # Protobuf linting rules ├── buf.gen.yaml # Code generation plugins └── local.env.example # Example environment variables (copy to local.env) diff --git a/{{cookiecutter.app_name}}/README.md b/{{cookiecutter.app_name}}/README.md index a1dd9cb..c787834 100644 --- a/{{cookiecutter.app_name}}/README.md +++ b/{{cookiecutter.app_name}}/README.md @@ -42,6 +42,18 @@ To run the image, run: $ make run-docker ``` +## CI/CD + +The project includes ready-to-use CI pipelines for both GitHub and GitLab. Delete whichever platform you don't use. + +### GitHub Actions (`.github/workflows/go.yml`) + +Runs on push to `main`/`master` and on pull requests. Four parallel jobs: **build**, **test** (race detector + coverage), **benchmark**, and **lint** (govulncheck + golangci-lint). Each job has concurrency control to cancel duplicate runs. + +### GitLab CI (`.gitlab-ci.yml`) + +Three jobs in a single `test` stage: **unit-test** (with Cobertura coverage report), **lint** (golangci-lint + govulncheck), and **benchmark**. Go module caching is enabled. + ## Adding a new endpoint to the API Our service is grpc first. We use [grpc-gateway] to automatically map HTTP requests to gRPC requests. This means that you can add a new endpoint to the API by adding a new rpc to `service {{cookiecutter.service_name}}` in `proto/{{cookiecutter.app_name|lower}}.proto` file. Then, you can run `make generate` to generate grpc/http endpoints.