Makefile
Rama main · réplica de lectura del repositorio original.
.PHONY: build dev dev-conductor dev-cashier dev-dashboard dev-docs dev-logs dev-stop cockpit cockpit-dev generate-graphql generate-cli-docs lint minikube dns infra infra-down infra-forward infra-forward-stop db-forward deploy-prod deploy-prod-infra
# Build all Go services
build:
go build ./services/conductor/cmd/conductor/...
go build ./services/builder/cmd/builder/...
go build ./services/cashier/cmd/cashier/...
go build ./services/exporter/cmd/exporter/...
go build ./services/stagehand/cmd/stagehand/...
# Generate GraphQL resolvers (requires gqlgen)
generate-graphql:
cd services/conductor && go generate ./internal/api/graphql/resolver.go
# Regenerate the CLI reference in the docs from the CLI's help texts
generate-cli-docs:
cd cli && go run ./cmd/docgen ./cmd/lucity ../docs/content/17.cli.md
# Start all services with hot reload (air + vite)
dev:
@bash scripts/dev.sh
# View all service logs
dev-logs:
@tail -f tmp/logs/*.log
# View specific service logs (e.g., make dev-logs-conductor)
dev-logs-%:
@tail -f tmp/logs/$*.log
# Stop all dev services
dev-stop:
@bash scripts/dev-stop.sh
# Run individual services (without air)
dev-conductor:
cd services/conductor && set -a && . .env 2>/dev/null && set +a && go run ./cmd/conductor/...
dev-cashier:
cd services/cashier && set -a && . .env 2>/dev/null && set +a && go run ./cmd/cashier/...
dev-dashboard:
cd services/dashboard && npm run dev
dev-docs:
cd docs && npm run dev
# Ops cockpit desktop window, opens on the environment used last (or ENV=dev|prod) and switches in the window
cockpit:
cd services/cockpit/web && npm run build
cd services/cockpit && go run ./cmd/cockpit $(if $(ENV),-env $(ENV)) -deployments $(CURDIR)/deployments
# Same window with the UI served by Vite: web/ edits hot reload, Go edits need a restart
cockpit-dev:
cd services/cockpit/web && (test -d dist || npm run build)
(cd services/cockpit/web && exec node_modules/.bin/vite) & pid=$$!; trap "kill $$pid 2>/dev/null" EXIT; \
cd services/cockpit && FRONTEND_DEVSERVER_URL=http://127.0.0.1:5175 go run ./cmd/cockpit $(if $(ENV),-env $(ENV)) -deployments $(CURDIR)/deployments
# Lint
lint:
cd services/dashboard && npm run lint
# Create minikube cluster for local development
# --insecure-registry covers the entire service CIDR so Docker trusts Zot over HTTP.
# See: https://minikube.sigs.k8s.io/docs/handbook/registry/#enabling-insecure-registries
minikube:
minikube start --insecure-registry="10.96.0.0/12"
# Set up local DNS so *.lucity.local resolves to 127.0.0.1 (requires Homebrew)
# Run once — survives reboots. Uses dnsmasq on port 5380 (unprivileged) with
# macOS /etc/resolver pointing to it. No root needed for dnsmasq itself.
dns:
@if ! command -v dnsmasq >/dev/null 2>&1; then \
echo "Installing dnsmasq..."; \
brew install dnsmasq; \
fi
@if ! grep -q 'port=5380' /opt/homebrew/etc/dnsmasq.conf 2>/dev/null; then \
echo "port=5380" >> /opt/homebrew/etc/dnsmasq.conf; \
echo "Set dnsmasq to listen on port 5380."; \
fi
@if ! grep -q 'address=/lucity.local/' /opt/homebrew/etc/dnsmasq.conf 2>/dev/null; then \
echo "address=/lucity.local/127.0.0.1" >> /opt/homebrew/etc/dnsmasq.conf; \
echo "Added *.lucity.local → 127.0.0.1 to dnsmasq config."; \
else \
echo "dnsmasq already configured for *.lucity.local."; \
fi
@sudo mkdir -p /etc/resolver
@printf "nameserver 127.0.0.1\nport 5380\n" | sudo tee /etc/resolver/lucity.local > /dev/null
@brew services restart dnsmasq
@echo "Done. All *.lucity.local domains now resolve to 127.0.0.1."
# Deploy infrastructure (Zot + Envoy Gateway + CNPG) to a cluster
# Envoy Gateway is installed separately — it needs its own namespace for cert management.
# Usage: make infra CLUSTER=flxp
CLUSTER ?= minikube
infra:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
helm upgrade --install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
--version v1.2.6 -n envoy-gateway-system --create-namespace --skip-crds
@kubectl apply -f - <<< '{"apiVersion":"gateway.networking.k8s.io/v1","kind":"GatewayClass","metadata":{"name":"eg"},"spec":{"controllerName":"gateway.envoyproxy.io/gatewayclass-controller"}}'
helm dependency update charts/lucity-infra
helm upgrade --install lucity-infra charts/lucity-infra \
-n lucity-system --create-namespace \
-f deployments/$(CLUSTER)/values.yaml
infra-down:
helm uninstall lucity-infra -n lucity-system
# Port-forward infrastructure services for local development
infra-forward: infra-forward-stop
@echo "Port-forwarding Zot (5000), Gateway (8880), VictoriaMetrics (8428), VictoriaLogs (9428), Logto Admin (3002), Grafana (3000)..."
@kubectl port-forward svc/lucity-infra-zot 5000:5000 -n lucity-system &
@(GATEWAY_SVC=$$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=lucity-gateway -o name 2>/dev/null) && \
[ -n "$$GATEWAY_SVC" ] && kubectl port-forward $$GATEWAY_SVC 8880:80 -n envoy-gateway-system &) 2>/dev/null || true
@kubectl port-forward svc/lucity-infra-logto 3002:3002 -n lucity-system &
@kubectl port-forward svc/lucity-infra-victoria-metrics-single-server 8428:8428 -n lucity-system &
@kubectl port-forward svc/lucity-infra-victoria-logs-single-server 9428:9428 -n lucity-system &
@kubectl port-forward svc/lucity-infra-grafana 3000:80 -n lucity-system &
@echo "Ready. Use 'make infra-forward-stop' to stop."
infra-forward-stop:
@for port in 5000 8880 3002 8428 9428 3000; do \
lsof -ti :$$port | xargs kill 2>/dev/null || true; \
done
# Port-forward a project's database for local development (interactive picker)
db-forward:
@bash scripts/db-forward.sh
# Production deployment from OCI registry charts
# Usage: make deploy-prod VERSION=0.0.0-85-gabcdef0 HELM_ARGS="..."
# Secrets are split into infra-secrets.yaml and secrets.yaml (both gitignored).
# First deploy: copy from *.example files and fill in values.
PROD_CONTEXT ?= lucity-prod
VERSION ?=
deploy-prod-infra:
@test -f deployments/lucity-prod/infra-secrets.yaml || { echo "Error: deployments/lucity-prod/infra-secrets.yaml not found. Copy deployments/infra-secrets.yaml.example and fill in values."; exit 1; }
helm upgrade --install lucity-infra \
oci://ghcr.io/zeitlos/lucity/charts/lucity-infra \
$(if $(VERSION),--version $(VERSION)) \
--kube-context $(PROD_CONTEXT) \
-n lucity-system --create-namespace \
-f deployments/lucity-prod/infra-values.yaml \
-f deployments/lucity-prod/infra-secrets.yaml \
$(HELM_ARGS)
deploy-prod:
@test -f deployments/lucity-prod/secrets.yaml || { echo "Error: deployments/lucity-prod/secrets.yaml not found. Copy deployments/secrets.yaml.example and fill in values."; exit 1; }
helm upgrade --install lucity \
oci://ghcr.io/zeitlos/lucity/charts/lucity \
$(if $(VERSION),--version $(VERSION)) \
--kube-context $(PROD_CONTEXT) \
-n lucity-system --create-namespace \
-f deployments/lucity-prod/values.yaml \
-f deployments/lucity-prod/secrets.yaml \
$(HELM_ARGS)
# Development cluster deployment from OCI registry charts
# Usage: make deploy-dev VERSION=26.9.1
# Always pass VERSION= explicitly: "latest" resolves to the highest stable tag,
# which ranks below every prerelease.
DEV_CONTEXT ?= lucity-dev
deploy-dev-infra:
@test -f deployments/lucity-dev/infra-secrets.yaml || { echo "Error: deployments/lucity-dev/infra-secrets.yaml not found. Copy deployments/infra-secrets.yaml.example and fill in values."; exit 1; }
helm upgrade --install lucity-infra \
oci://ghcr.io/zeitlos/lucity/charts/lucity-infra \
$(if $(VERSION),--version $(VERSION)) \
--kube-context $(DEV_CONTEXT) \
-n lucity-system --create-namespace \
-f deployments/lucity-dev/infra-values.yaml \
-f deployments/lucity-dev/infra-secrets.yaml \
$(HELM_ARGS)
deploy-dev:
@test -f deployments/lucity-dev/secrets.yaml || { echo "Error: deployments/lucity-dev/secrets.yaml not found. Copy deployments/secrets.yaml.example and fill in values."; exit 1; }
helm upgrade --install lucity \
oci://ghcr.io/zeitlos/lucity/charts/lucity \
$(if $(VERSION),--version $(VERSION)) \
--kube-context $(DEV_CONTEXT) \
-n lucity-system --create-namespace \
-f deployments/lucity-dev/values.yaml \
-f deployments/lucity-dev/secrets.yaml \
$(HELM_ARGS)
# Sync workspace
sync:
go work sync