SHELL := /bin/sh

IMAGE ?= go-tell
TAG ?= latest
REGISTRY_IMAGE ?= batty1039.startdedicated.net:5000/go-tell
HELM ?= helm
HELM_CHART := deploy/helm/go-tell
HELM_RELEASE ?= go-tell
HELM_NAMESPACE ?= go-tell
# The development and production releases share one cluster, so both point at the
# same kubeconfig and only the namespace and the values profile differ.
KUBECONFIG ?= $(HOME)/.kube/config
# Secret holding the platform CA bundle the pod needs to reach auth.dev. Create it
# per namespace with kubectl create secret generic local-ca --from-file=ca.crt=...
GO_LOOSE_CA_SECRET ?= local-ca

# Helm receives the Go Loose credentials from the environment instead of a values
# file. make sources the gitignored .env first, so a configured checkout only has
# to run the target.
GO_LOOSE_SET = $(if $(GO_LOOSE_CLIENT_ID),--set-string goLoose.clientID=$(GO_LOOSE_CLIENT_ID)) \
	$(if $(GO_LOOSE_CLIENT_SECRET),--set-string goLoose.clientSecret=$(GO_LOOSE_CLIENT_SECRET)) \
	$(if $(GO_LOOSE_CA_SECRET),--set-string goLoose.ca.existingSecret=$(GO_LOOSE_CA_SECRET))

.PHONY: help ui frontend backend demo production run test check docker docker-push docker-run clean ingress-nginx-install cert-manager-install cluster-prepare helm-lint helm-deploy-development helm-deploy-production helm-down-development helm-down-production helm-proxy-development helm-proxy-production

help:
	@echo "make ui         			build the React app into cmd/server/web/dist"
	@echo "make frontend   			run the Vite UI with API changes proxied to :8080"
	@echo "make backend    			run the Go server on :8080 (serves the last UI build)"
	@echo "make demo       			run the in-memory demo profile"
	@echo "make production 			run the SSO production profile"
	@echo "make run        			build the UI, then run the server"
	@echo "make test       			run the Go test suite"
	@echo "make check      			gofmt, vet, and tests"
	@echo "make docker     			build the all-in-one image"
	@echo "make docker-push			build and push the image to the private registry"
	@echo "make docker-run 			run the image on :8080"
	@echo "make clean      			remove build output"
	@echo "make ingress-nginx-install		install the ingress controller in the cluster"
	@echo "make cert-manager-install   	install cert-manager in the cluster"
	@echo "make cluster-prepare       		prepare the cluster for both releases"
	@echo "make helm-lint      			linting the helm charts"
	@echo "make helm-deploy-development		deploy to development"
	@echo "make helm-deploy-production     	deploy to production"
	@echo "make helm-down-development      	development down"
	@echo "make helm-down-production      		production down"
	@echo "make helm-proxy-development     	proxy development"
	@echo "make helm-proxy-production      	proxy production"

# The Go server embeds the compiled frontend, so the UI is built first and copied
# into the embed directory that cmd/server/main.go points at.
ui:
	@if [ ! -d ui/app/node_modules ]; then \
		npm --prefix ui/app ci; \
	fi
	npm --prefix ui/app run build
	rm -rf cmd/server/web/dist
	mkdir -p cmd/server/web/dist
	cp -R ui/dist/. cmd/server/web/dist/

frontend:
	@if [ ! -d ui/app/node_modules ]; then \
		npm --prefix ui/app ci; \
	fi
	npm --prefix ui/app run dev -- --host 0.0.0.0

backend:
	set -a; [ ! -f .env ] || . ./.env; set +a; \
	go run ./cmd/server

demo:
	CMS_PROFILE=demo $(MAKE) backend

production:
	CMS_PROFILE=production $(MAKE) backend

run: ui backend

test:
	go test ./...

check:
	gofmt -l ./cmd ./internal
	go vet ./...
	go test ./...

docker:
	docker compose build

docker-push: docker
	docker tag $(IMAGE):$(TAG) $(REGISTRY_IMAGE):$(TAG)
	docker push $(REGISTRY_IMAGE):$(TAG)

docker-run:
	docker run --rm -p 8080:8080 --env-file .env $(IMAGE):$(TAG)

clean:
	rm -rf cmd/server/web/dist ui/dist
	mkdir -p cmd/server/web/dist
	printf 'Placeholder so the Go embed directive resolves before the frontend is built.\nRun `make ui` to replace this directory with the real React build.\n' > cmd/server/web/dist/placeholder.txt
ingress-nginx-install:
	kubectl --kubeconfig "$(KUBECONFIG)" apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.14.1/deploy/static/provider/kind/deploy.yaml
	kubectl --kubeconfig "$(KUBECONFIG)" -n ingress-nginx rollout status deployment/ingress-nginx-controller --timeout=5m

cert-manager-install:
	kubectl --kubeconfig "$(KUBECONFIG)" apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.1/cert-manager.yaml
	kubectl --kubeconfig "$(KUBECONFIG)" -n cert-manager rollout status deployment/cert-manager-webhook --timeout=5m
	kubectl --kubeconfig "$(KUBECONFIG)" -n cert-manager rollout status deployment/cert-manager-cainjector --timeout=5m
	kubectl --kubeconfig "$(KUBECONFIG)" -n cert-manager rollout status deployment/cert-manager --timeout=5m

cluster-prepare: ingress-nginx-install cert-manager-install

helm-lint:
	$(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-development.yaml
	$(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-production.yaml
	$(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
		-f $(HELM_CHART)/values-development.yaml >/dev/null
	$(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
		-f $(HELM_CHART)/values-production.yaml \
		--set-string goLoose.clientID=lint --set-string goLoose.clientSecret=lint >/dev/null

# Go Loose credentials are never stored in the values files. Pass them on the
# command line, from a secret store, or with --set-file:
#   make helm-deploy-production \
#     --set goLoose.clientID=$(GO_LOOSE_CLIENT_ID) \
#     --set goLoose.clientSecret=$(GO_LOOSE_CLIENT_SECRET) \
#     --set goLoose.ca.existingSecret=local-ca
helm-deploy-development:
	KUBECONFIG="$(KUBECONFIG)" $(HELM) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
		--namespace $(HELM_NAMESPACE)-development --create-namespace \
		-f $(HELM_CHART)/values-development.yaml \
		--rollback-on-failure --wait --timeout 10m

helm-deploy-production:
	set -a; [ ! -f .env ] || . ./.env; set +a; \
	KUBECONFIG="$(KUBECONFIG)" $(HELM) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
		--namespace $(HELM_NAMESPACE)-production --create-namespace \
		-f $(HELM_CHART)/values-production.yaml \
		$(GO_LOOSE_SET) \
		--rollback-on-failure --wait --timeout 10m

helm-down-production:
	KUBECONFIG="$(KUBECONFIG)" $(HELM) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-production

helm-down-development:
	KUBECONFIG="$(KUBECONFIG)" $(HELM) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-development

helm-proxy-production:
	kubectl --kubeconfig "$(KUBECONFIG)" port-forward -n $(HELM_NAMESPACE)-production service/$(HELM_RELEASE) 31373:80 --address 0.0.0.0
helm-proxy-development:
	kubectl --kubeconfig "$(KUBECONFIG)" port-forward -n $(HELM_NAMESPACE)-development service/$(HELM_RELEASE) 30010:80 --address 0.0.0.0