Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1d238fd
feat: add docker-compose local dev stack with profiles
ankurs Apr 8, 2026
97f763e
fix: remove spurious 'build-' prefix from Dockerfile app label
ankurs Apr 8, 2026
3f37915
feat: add Grafana dashboard, include_docker_compose flag, deploy/loca…
ankurs Apr 8, 2026
c686cab
feat: infra-only local-stack, load testing, dynamic endpoint display
ankurs Apr 8, 2026
3dbf8e6
fix: stop gitignoring misc/, add loadtest config
ankurs Apr 8, 2026
c0c6e0b
fix: add --remove-orphans to local-stack, fix gitignore test
ankurs Apr 8, 2026
a8110cc
feat: add metrics package with interface, promauto, and sample usage
ankurs Apr 8, 2026
b3eb038
feat: add Jaeger to obs profile for OTEL distributed tracing
ankurs Apr 8, 2026
5f90a49
fix: address PR review — portable compose, rm cleanup, psql exec, YAM…
ankurs Apr 8, 2026
a134364
feat: per-service docker-compose profiles with inline option selection
ankurs Apr 8, 2026
2829222
fix: AlloyDB, local-exec, obs shortcut, code review fixes
ankurs Apr 8, 2026
ed0c4d1
fix: stale deps reference in AGENTS.md load testing note
ankurs Apr 8, 2026
8722574
fix: PR review — Grafana UID, health checks, Linux support, skip warning
ankurs Apr 8, 2026
31c1d91
fix: ministack image name, gatherMetric error handling, alloydb in Ma…
ankurs Apr 8, 2026
58d690a
fix: local-stack-obs reuses endpoint display, local-stack-down uses -…
ankurs Apr 8, 2026
f05db4e
chore: reorder cookiecutter prompts, update README features list
ankurs Apr 8, 2026
d1c867c
fix: sanitize hyphens/dots in Prometheus metrics namespace
ankurs Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions tests/test_cookiecutter_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ def test_expected_files_exist(self, bake_project):
"main.go",
"Makefile",
"Dockerfile",
"docker-compose.local.yml",
"deploy/prometheus.yml",
"go.mod",
"README.md",
"AGENTS.md",
Expand Down Expand Up @@ -277,6 +279,16 @@ def test_go_tool_commands(self, bake_project):
assert "go tool mockery" in content
assert "go tool govulncheck" in content

def test_local_stack_targets(self, bake_project):
project = bake_project()
content = (project / "Makefile").read_text()
assert "local-stack:" in content
assert "local-stack-down:" in content
assert "local-stack-logs:" in content
assert "local-stack-reset:" in content
assert "local-psql:" in content
assert "docker-compose.local.yml" in content

def test_bench_run_pattern(self, bake_project):
project = bake_project()
content = (project / "Makefile").read_text()
Expand Down Expand Up @@ -346,6 +358,33 @@ def test_gitlab_ci_go_tool_cobertura(self, bake_project):
# ---------------------------------------------------------------------------


class TestDockerCompose:
def test_compose_service_name(self, bake_project):
project = bake_project()
content = (project / "docker-compose.local.yml").read_text()
assert "testservice:" in content
assert "9090:9090" in content
assert "9091:9091" in content

def test_compose_profiles(self, bake_project):
project = bake_project()
content = (project / "docker-compose.local.yml").read_text()
assert 'profiles: ["deps"]' in content
assert 'profiles: ["obs"]' in content

def test_compose_db_name(self, bake_project):
project = bake_project()
content = (project / "docker-compose.local.yml").read_text()
assert "POSTGRES_DB: testservice_dev" in content

def test_agents_md_local_stack(self, bake_project):
project = bake_project()
content = (project / "AGENTS.md").read_text()
assert "make local-stack" in content
assert "PROFILES=" in content
assert "localhost:9091" in content


class TestConfigFiles:
def test_gitignore_entries(self, bake_project):
project = bake_project()
Expand Down
23 changes: 23 additions & 0 deletions {{cookiecutter.app_name}}/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,29 @@ GOPRIVATE is pre-configured in Makefile, Dockerfile, and CI workflows. For priva
- **CI**: uncomment the auth steps in `.github/workflows/go.yml` or `.gitlab-ci.yml`
- See [Private Modules guide](https://docs.coldbrew.cloud/howto/private-modules/) for details

## Local Development Stack

Start the service and dependencies with docker-compose:

```bash
make local-stack # service only
make local-stack PROFILES="deps" # + Postgres, Redis, Adminer
make local-stack PROFILES="deps obs" # + Prometheus, Grafana
make local-stack-logs # follow logs
make local-stack-down # stop stack
make local-stack-reset # stop, remove, restart
make local-psql # open Postgres shell
```

Endpoints when running with all profiles:
- Service HTTP/Swagger: http://localhost:9091/swagger/
- Service gRPC: localhost:9090
- Postgres: localhost:5433 (user: postgres, password: postgres, db: {{cookiecutter.app_name}}_dev)
- Redis: localhost:6379
- Adminer (DB UI): http://localhost:8088
- Prometheus: http://localhost:9100
- Grafana: http://localhost:3000 (admin/admin)

## Rules

- **Never edit generated files** — files in `proto/*.pb.go`, `proto/*_grpc.pb.go`, `proto/*.gw.go` are generated. Edit the `.proto` file and run `make generate`.
Expand Down
34 changes: 33 additions & 1 deletion {{cookiecutter.app_name}}/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build build-alpine clean test default deps generate run run-docker fmt help bench build-docker coverage-html dep lint mock runj vulncheck
.PHONY: build build-alpine clean test default deps generate run run-docker fmt help bench build-docker coverage-html dep lint mock runj vulncheck local-stack local-stack-down local-stack-logs local-stack-rm local-stack-reset local-psql

BIN_NAME={{cookiecutter.app_name}}
GOPRIVATE ?= {{cookiecutter.goprivate}}
Expand Down Expand Up @@ -35,6 +35,11 @@ help:
@echo ' make run-docker Run the project in a docker container.'
@echo ' make runj Run the project locally with jq log parsing.'
@echo ' make test Run tests.'
@echo ' make local-stack Start local dev stack (PROFILES="deps" for db/redis, "deps obs" for full).'
@echo ' make local-stack-down Stop local dev stack.'
@echo ' make local-stack-logs Follow local dev stack logs.'
@echo ' make local-stack-reset Reset local dev stack (down + rm + up).'
@echo ' make local-psql Open psql shell in local Postgres.'
@echo

build:
Expand Down Expand Up @@ -100,3 +105,30 @@ runj: build

run-docker: build-docker
docker run -p 9091:9091 -p 9090:9090 --env-file local.env ${IMAGE_NAME}:local

# Local development stack (docker-compose)
# Usage:
# make local-stack # service only
# make local-stack PROFILES="deps" # + postgres, redis, adminer
# make local-stack PROFILES="deps obs" # + prometheus, grafana
# make local-stack-down PROFILES="deps" # tear down with deps

COMPOSE_FILE := docker-compose.local.yml
PROFILE_FLAGS := $(foreach p,$(PROFILES),--profile $(p))

local-stack:
docker-compose -f $(COMPOSE_FILE) $(PROFILE_FLAGS) up -d --wait

local-stack-down:
docker-compose -f $(COMPOSE_FILE) $(PROFILE_FLAGS) down

Comment thread
ankurs marked this conversation as resolved.
local-stack-logs:
docker-compose -f $(COMPOSE_FILE) $(PROFILE_FLAGS) logs -f

local-stack-rm:
docker-compose -f $(COMPOSE_FILE) $(PROFILE_FLAGS) rm
Comment thread
ankurs marked this conversation as resolved.
Outdated

local-stack-reset: local-stack-down local-stack-rm local-stack
Comment thread
ankurs marked this conversation as resolved.
Outdated
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

local-psql:
docker exec -ti {{cookiecutter.app_name}}-db-1 bash -c 'PGPASSWORD=postgres psql -U postgres -d {{cookiecutter.app_name}}_dev'
Comment thread
ankurs marked this conversation as resolved.
Outdated
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
7 changes: 7 additions & 0 deletions {{cookiecutter.app_name}}/deploy/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
global:
scrape_interval: 15s

scrape_configs:
- job_name: {{cookiecutter.app_name}}
static_configs:
- targets: ["{{cookiecutter.app_name}}:9091"]
51 changes: 51 additions & 0 deletions {{cookiecutter.app_name}}/docker-compose.local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
services:
{{cookiecutter.app_name}}:
build: .
restart: always
ports:
- "9090:9090"
- "9091:9091"
env_file:
- local.env

db:
image: postgres:17-alpine
restart: always
profiles: ["deps"]
ports:
- "5433:5432"
environment:
POSTGRES_DB: {{cookiecutter.app_name}}_dev
POSTGRES_PASSWORD: postgres
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

redis:
image: redis:8-alpine
restart: always
profiles: ["deps"]
ports:
- "6379:6379"

adminer:
image: adminer
restart: always
profiles: ["deps"]
ports:
- "8088:8080"

prometheus:
image: prom/prometheus:latest
restart: always
profiles: ["obs"]
ports:
- "9100:9090"
volumes:
- ./deploy/prometheus.yml:/etc/prometheus/prometheus.yml

grafana:
image: grafana/grafana:latest
restart: always
profiles: ["obs"]
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
Loading