Files
go-server-with-otel/AGENTS.md
T
rmcguire 3241fc7107
Build and Publish / check-chart (push) Successful in 33s
Build and Publish / helm-release (push) Has been skipped
Build and Publish / container-images (push) Successful in 3m30s
Build and Publish / go-binaries (push) Successful in 5m2s
add AGENTS.md, update deps, fix mcp
2026-07-04 17:21:22 -04:00

65 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md — go-server-with-otel (template)
A ready-to-fork template app for the `go-app` framework: HTTP + gRPC +
grpc-gateway + MCP + OTEL/Prometheus, wired and building. Fork it, rename it,
replace the `demo` domain with your service. See go-app's AGENTS.md for
framework internals.
## Kick off a new app (do these in order)
1. **Rename via the Makefile** (rewrites module path, binary/app name,
Dockerfile, helm, buf `merge_file_name`, main.go `appName`; deletes the old
swagger file). GNU `sed` required (macOS: `brew install gnu-sed` or coreutils
on PATH). The target is interactive, so pipe confirmation:
```sh
echo y | make rename NAME=your.gitremote/pathto/newapp APP=new-app-name
```
It does **not** rename the `demo` domain — that's steps 46. Afterward verify
`git grep go-server-with-otel` is empty and update `.gitea/workflows/ci.yml`.
2. **Edit config** (`pkg/config/custom.go`): put app fields on `ServiceConfig`
(keep the embedded `*config.AppConfig`). Add `env:"..."` tags for anything
env-configurable — **and see the env gotcha below.** Update `config.yaml`,
`env-sample`, and `helm/values.yaml` to match. Then `make schema`.
3. **Define your proto**: replace `proto/demo/app/v1alpha1/` with
`proto/<domain>/v1alpha1/`, update `PROTO_DIRS` in the Makefile, and run
`make proto` (buf; managed mode → generates into `api/<same path>`, so the
proto `go_package` option is overridden — don't fight it). Delete `api/demo`.
4. **Implement `service.AppService`** (`Init`, `GetGRPC`, `GetHTTP`) in a new
`pkg/<domain>/` package, mirroring `pkg/demo`:
- `<domain>grpc/` — gRPC impl (embed `pb.Unimplemented...Server`); `GetServices`
returns `*opts.GRPCService`; `GetDialOpts` adds the insecure creds the
gateway needs.
- `<domain>mcp/` — `mcp.NewServer` exposed as `HTTPHandler{Prefix:"/api/mcp"}`;
tools via `mcp.AddTool`, typically delegating to the gRPC impl.
- Remove `demohttp/` unless you actually need plain HTTP funcs.
5. **Register it in `main.go`**: set `appServices = []service.AppService{&yoursvc}`.
This should be the only functional change in `main.go`.
6. **Delete `pkg/demo`** and any remaining `demo` references.
7. Build/verify: `go build ./... && go test ./...`, then run and hit `/metrics`,
`/api/...` (REST), `:8081` (grpc + reflection), `/api/mcp`.
## Gotchas the template inherits from go-app
- **Custom-field env doesn't auto-apply.** `MustLoadConfigInto` only parses env
for the embedded `AppConfig`. Add a `ServiceConfig.LoadEnv()` that runs
`env.Parse` over the custom fields (nil the embedded `*AppConfig` first to keep
go-app's precedence) and call it in `main.go` right after `MustLoadConfigInto`.
- **REST gateway 404s** unless `grpcGatewayPathStrip: true` is set in the grpc
config (default is false, so the `/api` prefix isn't stripped before matching).
- **Prometheus double-unit suffix**: don't use `metric.WithUnit` for gauges whose
names already carry the unit; the exporter appends another suffix.
- MCP streamable HTTP: clients must POST to `/api/mcp/` (trailing slash); the
bare path 307-redirects.
## What `make rename` does NOT touch
The `demo` domain naming: package dirs (`pkg/demo*`), `proto/demo`, `api/demo`,
types (`DemoService`, `DemoAppService`, `DemoTool`, …), `PROTO_DIRS`, and the
demo values in `config.yaml`/`helm`. Rename those by hand in steps 26.