template-monorepo/Makefile

217 lines
9.4 KiB
Makefile
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.

# go-zero 生成風格
GO_ZERO_STYLE := go_zero
GO ?= go
GOFMT ?= gofmt
GOFILES := $(shell find . -name '*.go' -not -path './generate/doc-generate/*')
GO_DOC_DIR := generate/doc-generate
GO_DOC_BIN := $(GO_DOC_DIR)/bin/go-doc
API_ENTRY := ./generate/api/gateway.api
DOC_OUT := ./docs/openapi
GOCTL ?= goctl
GOCTL_PKG := github.com/zeromicro/go-zero/tools/goctl@latest
GOLANGCI_PKG := github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2
.DEFAULT_GOAL := help
help: ## 顯示可用指令
@echo "Gateway Makefile"
@echo ""
@echo "首次開發:"
@echo " make tools 安裝 goctl、goimports、golangci-lint寫入 \$$GOPATH/bin"
@echo " go mod download"
@echo ""
@echo "常用:"
@grep -E '^[a-zA-Z0-9_-]+:.*## ' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*## "}; {printf " make %-14s %s\n", $$1, $$2}'
tools: ## 安裝 goctl、goimports、golangci-lint需 Go且 GOPATH/bin 在 PATH
@command -v $(GOCTL) >/dev/null 2>&1 || (echo ">> installing goctl" && $(GO) install $(GOCTL_PKG))
@command -v goimports >/dev/null 2>&1 || (echo ">> installing goimports" && $(GO) install golang.org/x/tools/cmd/goimports@latest)
@if ! command -v golangci-lint >/dev/null 2>&1 || ! golangci-lint version 2>/dev/null | grep -q 'version 2\.'; then \
echo ">> installing golangci-lint v2"; \
$(GO) install $(GOLANGCI_PKG); \
fi
@echo "tools OK"
@echo " goctl: $$(goctl --version 2>/dev/null || echo missing)"
@echo " golangci-lint: $$(golangci-lint version 2>/dev/null | head -1 || echo missing)"
gen-api: tools ## 由 .api 生成 handler / logic / types自訂 handler 模板)
$(GOCTL) api go -api $(API_ENTRY) -dir . -style $(GO_ZERO_STYLE) -home generate/goctl
gen-mock: ## 依 go:generate 產生 internal/model/*/mockgomock
$(GO) generate ./internal/model/...
build-go-doc: ## 編譯 go-docOpenAPI 文件生成器)
@echo ">> building $(GO_DOC_BIN)"
@mkdir -p $(GO_DOC_DIR)/bin
@cd $(GO_DOC_DIR) && $(GO) build -o bin/go-doc ./cmd/go-doc
gen-doc: build-go-doc ## 從 .api 生成 OpenAPI 3.0 YAML
@mkdir -p $(DOC_OUT)
$(GO_DOC_BIN) -a $(API_ENTRY) -d $(DOC_OUT) -f gateway -s openapi3.0 -y
@echo "Generated: $(DOC_OUT)/gateway.yaml"
test: ## 執行測試
$(GO) test ./...
fmt: ## gofmt + goimports不含 lint
$(GOFMT) -s -w $(GOFILES)
@command -v goimports >/dev/null 2>&1 && goimports -w . || (echo "goimports not found; run: make tools" && exit 1)
lint: tools ## golangci-lint 靜態檢查
golangci-lint run ./...
lint-fix: tools ## 自動修正可修的 lint / formatter 問題(見 .golangci.yml
golangci-lint run --fix ./...
fix: fmt lint-fix lint ## 格式化 + 自動修 lint + 再檢查(提交前建議)
check: fix test ## 提交 / PR 前完整檢查fmt、lint、test
# ============================================================
# Docker compose本機依賴
# ============================================================
DOCKER_COMPOSE ?= docker compose
COMPOSE_FILE := deploy/docker-compose.yml
COMPOSE := $(DOCKER_COMPOSE) -f $(COMPOSE_FILE)
deps-up: ## 起 Mongo + Redis最小本機依賴
$(COMPOSE) up -d mongo redis
deps-up-smtp: ## 起 Mongo + Redis + MailHog
$(COMPOSE) --profile smtp up -d mongo redis mailhog
deps-down: ## 停服務(保留 volume
$(COMPOSE) --profile smtp --profile k6 down
deps-down-v: ## 停服務並刪 volume會清資料
$(COMPOSE) --profile smtp --profile k6 down -v
deps-logs: ## 看 compose log
$(COMPOSE) --profile smtp --profile k6 logs -f
# ============================================================
# k6 測試test/k6/
# ============================================================
K6 ?= k6
K6_GATEWAY_CONFIG := etc/gateway.k6.yaml
K6_GATEWAY_BIN := bin/gateway-k6
K6_DIR := test/k6
K6_PAT_FILE := deploy/zitadel/machinekey/zitadel-admin-sa.token
K6_ENV_FILE := deploy/zitadel/machinekey/k6.env
ZITADEL_HEALTH_URL := http://localhost:8080/debug/healthz
# k6 安裝指引macOS / Linux
define K6_INSTALL_HINT
k6 not found in PATH.
Install:
macOS (Homebrew): brew install k6
Linux (apt): sudo gpg -k && sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 \
&& echo 'deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main' | sudo tee /etc/apt/sources.list.d/k6.list \
&& sudo apt update && sudo apt install k6
Other: https://grafana.com/docs/k6/latest/set-up/install-k6/
Or use docker (no install): K6='docker run --rm -i --network host -v $$PWD:/app -w /app grafana/k6:latest' make k6-smoke
endef
export K6_INSTALL_HINT
k6-check: ## 檢查 k6 是否安裝(沒裝會印 install 指引)
@command -v $(K6) >/dev/null 2>&1 || (echo "$$K6_INSTALL_HINT"; exit 1)
@echo "k6: $$($(K6) version 2>&1 | head -1)"
k6-up: ## 起 k6 全棧mongo + redis + mailhog + postgres + zitadel
$(COMPOSE) --profile k6 up -d mongo redis mailhog postgres zitadel
@echo "ZITADEL bootstrapping (this can take 3090s the first time)…"
@echo "→ run 'make k6-wait' to block until it is ready"
k6-wait: ## 等 ZITADEL ready + 把 PAT 寫到 deploy/zitadel/machinekey/k6.env
@echo "waiting for ZITADEL at $(ZITADEL_HEALTH_URL)"
@for i in $$(seq 1 120); do \
if curl -fsS $(ZITADEL_HEALTH_URL) >/dev/null 2>&1; then \
echo "zitadel ready ($$i s)"; break; \
fi; \
sleep 1; \
if [ $$i -eq 120 ]; then echo "zitadel did not become ready in 120s"; exit 1; fi; \
done
@for i in $$(seq 1 30); do \
if [ -s "$(K6_PAT_FILE)" ]; then break; fi; \
sleep 1; \
done
@if [ ! -s "$(K6_PAT_FILE)" ]; then \
echo "PAT file $(K6_PAT_FILE) missing — check 'docker logs gateway-zitadel'"; \
exit 1; \
fi
@PAT=$$(tr -d '\n' < $(K6_PAT_FILE)); \
printf 'export ZITADEL_SERVICE_TOKEN=%s\nexport BASE_URL=http://localhost:8888\nexport MAILHOG_URL=http://localhost:8025\nexport REDIS_ADDR=localhost:6379\n' "$$PAT" > $(K6_ENV_FILE); \
echo "wrote $(K6_ENV_FILE)"
@$(MAKE) -s k6-seed-fixtures
@echo "tip: 'source $(K6_ENV_FILE)' to load into your shell"
# k6-seed-fixtures idempotently upserts the k6-tenant + K6INVITE invite code
# into gateway_k6 so /auth/register resolves successfully. The invite hash is
# sha256("K6INVITE") — see internal/model/auth/domain/const.go HashInviteCode.
# Uses mongosh inside the container; no extra Go binary needed.
K6_TENANT_ID := k6-tenant
K6_INVITE_HASH := e62a291f0dcf88c50c91fdc78e3539c55e1e20ef645c640b1ec778fe4fabb4cb
k6-seed-fixtures: ## upsert k6-tenant + K6INVITE 到 mongo
@docker exec gateway-mongo mongosh --quiet --eval '\
db = db.getSiblingDB("gateway_k6"); \
var now = NumberLong(Date.now()); \
var t = db.tenants.updateOne( \
{tenant_id: "$(K6_TENANT_ID)"}, \
{$$set: {tenant_id: "$(K6_TENANT_ID)", slug: "$(K6_TENANT_ID)", name: "k6 Tenant", uid_prefix: "K6", status: "active", update_at: now}, $$setOnInsert: {create_at: now}}, \
{upsert: true} \
); \
var i = db.invite_codes.updateOne( \
{tenant_id: "$(K6_TENANT_ID)", code_hash: "$(K6_INVITE_HASH)"}, \
{$$set: {tenant_id: "$(K6_TENANT_ID)", code_hash: "$(K6_INVITE_HASH)", max_uses: NumberLong(1000000), expires_at: NumberLong(0), new_users_only: false, update_at: now}, $$setOnInsert: {used_count: NumberLong(0), create_at: now}}, \
{upsert: true} \
); \
print("tenant matched=" + t.matchedCount + " upserted=" + (t.upsertedId?1:0) + ", invite matched=" + i.matchedCount + " upserted=" + (i.upsertedId?1:0));' && \
echo "seeded fixtures (tenant=$(K6_TENANT_ID) invite=K6INVITE) into gateway_k6"
# Back-compat alias
k6-seed-tenant: k6-seed-fixtures ## (alias for k6-seed-fixtures)
k6-build: ## 建 gateway binary 給 k6 使用
@mkdir -p $(dir $(K6_GATEWAY_BIN))
$(GO) build -o $(K6_GATEWAY_BIN) ./gateway.go
k6-gateway: k6-build ## 前景啟 gateway吃 etc/gateway.k6.yaml + ZITADEL env
@if [ ! -s "$(K6_ENV_FILE)" ]; then echo "run 'make k6-wait' first"; exit 1; fi
@set -a; . $(K6_ENV_FILE); set +a; \
$(K6_GATEWAY_BIN) -f $(K6_GATEWAY_CONFIG)
k6-smoke: k6-check ## 跑 smoke 測試(每個端點一發)
@if [ ! -s "$(K6_ENV_FILE)" ]; then echo "run 'make k6-wait' first"; exit 1; fi
@set -a; . $(K6_ENV_FILE); set +a; \
for f in $(K6_DIR)/smoke/*.js; do \
echo "==> $$f"; $(K6) run "$$f" || exit 1; \
done
k6-journey: k6-check ## 跑 journey 測試(多步驟流程)
@if [ ! -s "$(K6_ENV_FILE)" ]; then echo "run 'make k6-wait' first"; exit 1; fi
@set -a; . $(K6_ENV_FILE); set +a; \
for f in $(K6_DIR)/journeys/*.js; do \
echo "==> $$f"; $(K6) run "$$f" || exit 1; \
done
k6-all: k6-smoke k6-journey ## smoke + journey
k6-seed-admin: k6-build ## 註冊 k6-admin 並 seed tenant_admin rolerbac journey 用)
@if [ ! -s "$(K6_ENV_FILE)" ]; then echo "run 'make k6-wait' first"; exit 1; fi
@mkdir -p bin
$(GO) build -o bin/k6-seed-admin ./cmd/k6-seed-admin
@set -a; . $(K6_ENV_FILE); set +a; \
./bin/k6-seed-admin > $(K6_ENV_FILE).admin || (echo "k6-seed-admin failed"; exit 1); \
cat $(K6_ENV_FILE).admin >> $(K6_ENV_FILE); \
echo "admin credentials appended to $(K6_ENV_FILE):"; \
cat $(K6_ENV_FILE).admin
k6-down: ## 停 k6 stack 並清 volume會清 Postgres / Mongo / Redis 資料)
$(COMPOSE) --profile k6 down -v
@rm -f $(K6_PAT_FILE) $(K6_ENV_FILE) $(K6_ENV_FILE).admin $(K6_ENV_FILE).tmp deploy/zitadel/machinekey/zitadel-admin-sa.json
@echo "k6 stack stopped, volumes & PAT removed"