Files
Felix FaerberandClaude Opus 4.7 032a22b6ee init devops repo
Mirrors cipherdolls/devops layout. Hostinger Swarm stacks for the t4t
hosted-gateway and local docker-compose for development + e2e tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 10:31:30 +03:00

160 lines
5.6 KiB
Makefile

# Hosted gateway — local dev + test orchestration.
# Mirrors cipherdolls/devops/local/Makefile.
PROJECT := hosted-gateway
COMPOSE_DEV := docker-compose.yaml
COMPOSE_TEST := docker-compose-test.yaml
DC := docker compose -p $(PROJECT) -f $(COMPOSE_TEST)
DC_DEV := docker compose -p $(PROJECT)-dev -f $(COMPOSE_DEV)
TEST_CONTAINER := $(PROJECT)-bun
LOG_DIR := /tmp/hosted-gateway-test-logs
SPEC ?= accounts
SPECS := health auth models gateway ledger cancellation concurrency
TIMEOUT ?= 600
SERVICES := postgres redis prisma api worker
# Specs that need the gnosis-fork stack (anvil + bee) and/or a registered
# provider → activate the `gateway` compose profile. `models` only needs the
# fork (read-only chain calls); `gateway`/`concurrency`/`cancellation` also
# need the t4t-provider + mock-ollama containers.
GATEWAY_SPECS := models gateway concurrency cancellation
gateway_profile = $(if $(filter $(1),$(GATEWAY_SPECS)),--profile gateway,)
.PHONY: dev-up dev-down dev-watch up up-detached down logs build clean test test-all $(addprefix test-,$(SPECS)) help lock
# ---------- dev ----------
dev-up:
$(DC_DEV) up
dev-down:
$(DC_DEV) down -v --remove-orphans -t 0
dev-watch:
$(DC_DEV) watch
# ---------- test ----------
# Generate / refresh bun.lock inside the hosted-gateway repo via a one-shot
# container. Mirrors cipherdolls' approach so no host-side Bun install is
# required.
lock:
@echo "========== Generating bun.lock =========="
docker run --rm -v ../../hosted-gateway:/app -w /app oven/bun:1.2-alpine bun install
@echo "========== bun.lock updated =========="
# Run a single spec by name. Example: `make test SPEC=accounts`
define run_test
bash -c '\
set +e; \
mkdir -p $(LOG_DIR); \
cleanup() { \
echo ""; \
echo "========== Cleaning up =========="; \
docker rm -f $(TEST_CONTAINER) 2>/dev/null; \
$(DC) kill 2>/dev/null; \
$(DC) down -v --remove-orphans -t 0 2>/dev/null; \
}; \
trap cleanup EXIT; \
echo "========== Updating bun.lock =========="; \
docker run --rm -v ../../hosted-gateway:/app -w /app oven/bun:1.2-alpine bun install --frozen-lockfile 2>/dev/null || \
docker run --rm -v ../../hosted-gateway:/app -w /app oven/bun:1.2-alpine bun install; \
echo "========== Starting services =========="; \
$(DC) $(call gateway_profile,$(1)) up -d --build --wait $(SERVICES); \
if [ "$(call gateway_profile,$(1))" != "" ]; then \
echo "========== Starting gateway profile (anvil) =========="; \
$(DC) $(call gateway_profile,$(1)) up -d --build --wait anvil || { echo "gateway profile failed to start"; exit 1; }; \
if [ "$(1)" != "models" ]; then \
echo "========== Starting t4t-provider + mock-ollama =========="; \
$(DC) $(call gateway_profile,$(1)) up -d --build --wait t4t-provider mock-ollama || { echo "provider profile failed to start"; exit 1; }; \
fi; \
fi; \
echo "========== Running $(1) =========="; \
$(DC) build --no-cache bun; \
$(DC) $(call gateway_profile,$(1)) run -d --no-deps --name $(TEST_CONTAINER) \
-e SPEC_GLOB="./test/$(1).e2e-spec.ts" \
bun; \
\
docker wait $(TEST_CONTAINER) &>/dev/null & \
WAIT_PID=$$!; \
stdbuf -oL docker logs -f $(TEST_CONTAINER) 2>&1 \
| stdbuf -oL sed "s/\x1b\[[0-9;]*m//g" \
> $(LOG_DIR)/$(1).log & \
LOGS_PID=$$!; \
\
if ! timeout $(TIMEOUT) tail --pid=$$WAIT_PID -f /dev/null 2>/dev/null; then \
echo "========== TIMEOUT after $(TIMEOUT)s =========="; \
docker kill $(TEST_CONTAINER) 2>/dev/null; \
fi; \
wait $$WAIT_PID 2>/dev/null; \
rc=$$(docker inspect -f "{{.State.ExitCode}}" $(TEST_CONTAINER) 2>/dev/null || echo 1); \
kill $$LOGS_PID 2>/dev/null; \
wait $$LOGS_PID 2>/dev/null; \
echo "========== Tests finished (rc=$$rc) — log: $(LOG_DIR)/$(1).log =========="; \
exit $$rc'
endef
test:
$(call run_test,$(SPEC))
test-all:
@failed=""; \
for spec in $(SPECS); do \
echo ""; \
echo "========== Suite: $$spec =========="; \
$(MAKE) --no-print-directory test SPEC=$$spec; \
if [ $$? -ne 0 ]; then failed="$$failed $$spec"; fi; \
done; \
if [ -n "$$failed" ]; then \
echo ""; \
echo "Failed specs:$$failed"; exit 1; \
else \
echo ""; \
echo "All specs passed"; \
fi
$(addprefix test-,$(SPECS)):
$(call run_test,$(subst test-,,$@))
up:
$(DC) up
up-detached:
$(DC) up -d
down:
$(DC) kill 2>/dev/null || true
$(DC) down -v --remove-orphans -t 0
logs:
$(DC) logs -f
build:
$(DC) build
clean:
$(DC) kill 2>/dev/null || true
$(DC) down -v --remove-orphans --rmi local -t 0
@docker ps -aq --filter "label=com.docker.compose.project=$(PROJECT)" | xargs -r docker rm -f 2>/dev/null || true
@docker volume ls -q --filter "label=com.docker.compose.project=$(PROJECT)" | xargs -r docker volume rm -f 2>/dev/null || true
@docker network ls -q --filter "label=com.docker.compose.project=$(PROJECT)" | xargs -r docker network rm 2>/dev/null || true
help:
@echo "Usage:"
@echo " make dev-up Start dev stack (postgres, redis, anvil, bee, api, worker)"
@echo " make dev-down Stop and clean dev stack"
@echo " make dev-watch Dev with file sync"
@echo " make test SPEC=accounts Run one e2e spec inside docker"
@echo " make test-accounts Same as `make test SPEC=accounts`"
@echo " make test-all Run every spec sequentially"
@echo " make up Start test stack (no test runner)"
@echo " make down Tear down test stack"
@echo " make logs Tail test stack logs"
@echo " make lock Regenerate bun.lock via docker"
@echo " make clean Nuclear cleanup"
@echo ""
@echo "Available specs:"
@echo " $(SPECS)" | fold -s -w 70