2026-09-19 20:31:14 +02:00
|
|
|
SHELL := /bin/sh
|
feat: avatar, account menu, and single sign-on from Go Loose
Signing in now starts at the sign-in screen and one button that hands the
browser to Go Loose, which returns to the welcome page. Nothing redirects to the
identity provider on its own any more: that fired on every anonymous visit and
read as a redirect loop rather than as a choice to sign in. The password form
remains only where the API reports that Go Loose login is not configured for the
host, because otherwise the application is unreachable on a bare localhost.
A person's picture is carried through from the Go Loose identity and rendered in
the account menu and on the profile page, with their initials as the fallback.
Two things make that fallback necessary rather than decorative: Go Loose retires a
picture key when a picture is replaced, so a link cached in a browser can be dead,
and most people have not uploaded one. The URL is deliberately not persisted
locally, since a stored key would keep failing after the picture changed.
The account menu is a disclosure rather than a hover menu: a real button with
aria-expanded, Escape and outside clicks closing it, and focus returning to the
trigger. It is not an ARIA menu, because its actions are a link and a button and
menuitem roles would strip the link semantics from one of them for no gain.
The account URL of the Go Loose identity is resolved on each sign-in and is read
from the live identity provider every time, which is also what makes it correct
after a picture change.
Depends on the Go Loose revision that serves avatar_url through
/connect/userinfo, so the picture URL reaches this application at all.
2026-10-05 21:50:06 +02:00
|
|
|
REGISTRY_IMAGE ?= batty1039.startdedicated.net:5000/go-tell
|
2026-09-19 20:31:14 +02:00
|
|
|
DATABASE_URL ?= postgres://go_guess:go_guess@localhost:5432/go_guess?sslmode=disable
|
|
|
|
|
JWT_SECRET ?= local-development-secret-change-me-12345
|
|
|
|
|
GOOSE := cd backend && go run github.com/pressly/goose/v3/cmd/goose@v3.26.0
|
2026-09-20 09:13:48 +02:00
|
|
|
BDD_COMPOSE := docker compose -f docker-compose.bdd.yml
|
2026-09-20 10:49:09 +02:00
|
|
|
HELM ?= helm
|
|
|
|
|
HELM_CHART := deploy/helm/go-guess
|
|
|
|
|
HELM_RELEASE ?= go-guess
|
2026-10-03 04:39:14 +02:00
|
|
|
HELM_NAMESPACE ?= go-insane
|
|
|
|
|
KUBECONFIG ?= $(HOME)/.kube/config
|
|
|
|
|
HELM_KUBECTL := KUBECONFIG="$(KUBECONFIG)" $(HELM)
|
|
|
|
|
GO_LOOSE_SET ?= --set-string api.goLoose.tenants.nmbs.clientID="$${GO_LOOSE_NMBS_CLIENT_ID:-}" \
|
|
|
|
|
--set-string api.goLoose.tenants.nmbs.clientSecret="$${GO_LOOSE_NMBS_CLIENT_SECRET:-}" \
|
|
|
|
|
--set-string api.goLoose.tenants.ypto.clientID="$${GO_LOOSE_YPTO_CLIENT_ID:-}" \
|
|
|
|
|
--set-string api.goLoose.tenants.ypto.clientSecret="$${GO_LOOSE_YPTO_CLIENT_SECRET:-}"
|
2026-09-19 20:31:14 +02:00
|
|
|
|
2026-10-03 04:39:14 +02:00
|
|
|
.PHONY: help dev db-up db-down migrate migrate-down seed backend frontend frontend-install test test-backend test-frontend test-integration test-bdd test-bdd-down test-env test-env-down lint build rancher-storage ingress-nginx-install cert-manager-install cluster-prepare helm-lint helm-deploy-development helm-deploy-production helm-down-production helm-down-development
|
2026-09-19 20:31:14 +02:00
|
|
|
|
2026-09-20 09:01:35 +02:00
|
|
|
help:
|
2026-09-21 00:03:07 +02:00
|
|
|
@echo "make dev builds the demo docker image"
|
|
|
|
|
@echo "make db-up starts the database docker container"
|
|
|
|
|
@echo "make db-down stops the database docker container"
|
|
|
|
|
@echo "make migrate runs the sql scripts migration"
|
|
|
|
|
@echo "make migrate-down revert the sql scripts migration"
|
|
|
|
|
@echo "make seed seeds data into the database"
|
|
|
|
|
@echo "make backend runs the backend"
|
|
|
|
|
@echo "make frontend runs the frontend"
|
2026-09-20 09:01:35 +02:00
|
|
|
@echo "make frontend-install installs the dependencies for the frontend"
|
2026-09-21 00:03:07 +02:00
|
|
|
@echo "make test full test suite: frontend, integration, and browser BDD"
|
|
|
|
|
@echo "make test-backend runs the tests for the backend"
|
|
|
|
|
@echo "make test-frontend runs the tests for the frontend"
|
2026-09-20 09:01:35 +02:00
|
|
|
@echo "make test-integration runs the integration tests"
|
2026-09-21 00:03:07 +02:00
|
|
|
@echo "make test-bdd runs browser BDD stories against the production image"
|
|
|
|
|
@echo "make test-bdd-down removes the isolated BDD stack and database"
|
|
|
|
|
@echo "make test-env builds the docker tests image"
|
|
|
|
|
@echo "make test-env-down stops the test image"
|
|
|
|
|
@echo "make lint runs lint on the frontend"
|
|
|
|
|
@echo "make build builds the entire project"
|
feat: avatar, account menu, and single sign-on from Go Loose
Signing in now starts at the sign-in screen and one button that hands the
browser to Go Loose, which returns to the welcome page. Nothing redirects to the
identity provider on its own any more: that fired on every anonymous visit and
read as a redirect loop rather than as a choice to sign in. The password form
remains only where the API reports that Go Loose login is not configured for the
host, because otherwise the application is unreachable on a bare localhost.
A person's picture is carried through from the Go Loose identity and rendered in
the account menu and on the profile page, with their initials as the fallback.
Two things make that fallback necessary rather than decorative: Go Loose retires a
picture key when a picture is replaced, so a link cached in a browser can be dead,
and most people have not uploaded one. The URL is deliberately not persisted
locally, since a stored key would keep failing after the picture changed.
The account menu is a disclosure rather than a hover menu: a real button with
aria-expanded, Escape and outside clicks closing it, and focus returning to the
trigger. It is not an ARIA menu, because its actions are a link and a button and
menuitem roles would strip the link semantics from one of them for no gain.
The account URL of the Go Loose identity is resolved on each sign-in and is read
from the live identity provider every time, which is also what makes it correct
after a picture change.
Depends on the Go Loose revision that serves avatar_url through
/connect/userinfo, so the picture URL reaches this application at all.
2026-10-05 21:50:06 +02:00
|
|
|
@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"
|
2026-09-21 00:03:07 +02:00
|
|
|
@echo "make rancher-storage installs the persistent local-path StorageClass"
|
2026-10-03 04:39:14 +02:00
|
|
|
@echo "make ingress-nginx-install installs the ingress-nginx controller serving 80/443"
|
|
|
|
|
@echo "make cert-manager-install installs cert-manager for chart-issued TLS certificates"
|
|
|
|
|
@echo "make cluster-prepare runs every cluster prerequisite in order"
|
2026-09-21 00:03:07 +02:00
|
|
|
@echo "make helm-lint lints development and production Helm configurations"
|
2026-09-20 10:49:09 +02:00
|
|
|
@echo "make helm-deploy-development deploys the development Helm release"
|
|
|
|
|
@echo "make helm-deploy-production deploys the production Helm release"
|
2026-09-20 23:56:09 +02:00
|
|
|
@echo "make helm-down-development shuts down the development Helm release"
|
|
|
|
|
@echo "make helm-down-production shuts down the production Helm release"
|
2026-09-19 20:31:14 +02:00
|
|
|
dev:
|
|
|
|
|
docker compose up --build
|
|
|
|
|
|
|
|
|
|
db-up:
|
2026-09-20 12:29:11 +02:00
|
|
|
docker compose up -d db rabbitmq
|
2026-09-19 20:31:14 +02:00
|
|
|
|
|
|
|
|
db-down:
|
|
|
|
|
docker compose down
|
|
|
|
|
|
|
|
|
|
migrate:
|
2026-10-01 09:06:58 +02:00
|
|
|
$(GOOSE) -dir migrations postgres "host=localhost user=go_guess password=go_guess dbname=go_guess port=5432 sslmode=disable search_path=ypto" up
|
2026-09-19 20:31:14 +02:00
|
|
|
|
|
|
|
|
migrate-down:
|
2026-10-01 09:06:58 +02:00
|
|
|
$(GOOSE) -dir migrations postgres "host=localhost user=go_guess password=go_guess dbname=go_guess port=5432 sslmode=disable search_path=ypto" down
|
2026-09-19 20:31:14 +02:00
|
|
|
|
2026-09-19 21:11:20 +02:00
|
|
|
seed:
|
2026-10-02 18:50:37 +02:00
|
|
|
cd backend && DATABASE_URL="$(DATABASE_URL)&search_path=ypto,public" APP_ENV="$${APP_ENV:-development}" go run ./cmd/seed
|
2026-09-19 21:11:20 +02:00
|
|
|
|
2026-09-19 20:31:14 +02:00
|
|
|
backend:
|
|
|
|
|
cd backend && DATABASE_URL="$(DATABASE_URL)" JWT_SECRET="$(JWT_SECRET)" go run ./cmd/api
|
|
|
|
|
|
|
|
|
|
frontend:
|
2026-10-02 18:50:37 +02:00
|
|
|
cd frontend && npm run dev --host
|
2026-09-19 20:31:14 +02:00
|
|
|
|
2026-09-19 21:11:20 +02:00
|
|
|
frontend-install:
|
|
|
|
|
cd frontend && npm ci
|
|
|
|
|
|
2026-09-20 09:13:48 +02:00
|
|
|
test: frontend-install test-integration test-frontend test-bdd
|
2026-09-19 20:31:14 +02:00
|
|
|
|
|
|
|
|
test-backend:
|
|
|
|
|
cd backend && go test ./...
|
|
|
|
|
|
|
|
|
|
test-frontend:
|
|
|
|
|
cd frontend && npm test
|
|
|
|
|
|
|
|
|
|
test-integration:
|
2026-09-19 21:11:20 +02:00
|
|
|
cd backend && go test -tags=integration ./...
|
|
|
|
|
|
2026-09-20 09:13:48 +02:00
|
|
|
test-bdd:
|
|
|
|
|
@set -eu; \
|
|
|
|
|
$(BDD_COMPOSE) down -v --remove-orphans; \
|
|
|
|
|
trap '$(BDD_COMPOSE) down -v --remove-orphans >/dev/null 2>&1' EXIT INT TERM; \
|
|
|
|
|
$(BDD_COMPOSE) up --build --abort-on-container-exit --exit-code-from bdd
|
|
|
|
|
|
|
|
|
|
test-bdd-down:
|
|
|
|
|
$(BDD_COMPOSE) down -v --remove-orphans
|
|
|
|
|
|
2026-09-19 21:11:20 +02:00
|
|
|
test-env:
|
|
|
|
|
COMPOSE_PROJECT_NAME=go-guess-test APP_ENV=test DB_PORT=15432 API_PORT=18080 \
|
2026-09-19 21:58:24 +02:00
|
|
|
WEB_PORT=15173 FRONTEND_URL=http://localhost:15173 RABBITMQ_AMQP_PORT=15673 \
|
|
|
|
|
RABBITMQ_MANAGEMENT_PORT=25673 docker compose up -d --build
|
2026-09-19 21:11:20 +02:00
|
|
|
|
|
|
|
|
test-env-down:
|
|
|
|
|
COMPOSE_PROJECT_NAME=go-guess-test docker compose down -v --remove-orphans
|
2026-09-19 20:31:14 +02:00
|
|
|
|
|
|
|
|
lint:
|
|
|
|
|
cd backend && go vet ./...
|
|
|
|
|
cd frontend && npm run lint
|
|
|
|
|
|
|
|
|
|
build:
|
|
|
|
|
cd backend && go build ./...
|
|
|
|
|
cd frontend && npm run build
|
2026-09-20 10:49:09 +02:00
|
|
|
|
feat: avatar, account menu, and single sign-on from Go Loose
Signing in now starts at the sign-in screen and one button that hands the
browser to Go Loose, which returns to the welcome page. Nothing redirects to the
identity provider on its own any more: that fired on every anonymous visit and
read as a redirect loop rather than as a choice to sign in. The password form
remains only where the API reports that Go Loose login is not configured for the
host, because otherwise the application is unreachable on a bare localhost.
A person's picture is carried through from the Go Loose identity and rendered in
the account menu and on the profile page, with their initials as the fallback.
Two things make that fallback necessary rather than decorative: Go Loose retires a
picture key when a picture is replaced, so a link cached in a browser can be dead,
and most people have not uploaded one. The URL is deliberately not persisted
locally, since a stored key would keep failing after the picture changed.
The account menu is a disclosure rather than a hover menu: a real button with
aria-expanded, Escape and outside clicks closing it, and focus returning to the
trigger. It is not an ARIA menu, because its actions are a link and a button and
menuitem roles would strip the link semantics from one of them for no gain.
The account URL of the Go Loose identity is resolved on each sign-in and is read
from the live identity provider every time, which is also what makes it correct
after a picture change.
Depends on the Go Loose revision that serves avatar_url through
/connect/userinfo, so the picture URL reaches this application at all.
2026-10-05 21:50:06 +02:00
|
|
|
docker:
|
|
|
|
|
docker build -t $(IMAGE):$(TAG) .
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
2026-09-20 15:28:23 +02:00
|
|
|
rancher-storage:
|
|
|
|
|
KUBECONFIG="$(KUBECONFIG)" kubectl apply -f deploy/rancher/local-path.yaml
|
|
|
|
|
|
2026-10-03 04:39:14 +02:00
|
|
|
ingress-nginx-install:
|
|
|
|
|
$(HELM_KUBECTL) repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update
|
|
|
|
|
$(HELM_KUBECTL) repo update
|
|
|
|
|
$(HELM_KUBECTL) upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
|
|
|
|
|
--namespace ingress-nginx --create-namespace \
|
|
|
|
|
--set controller.service.type=NodePort \
|
|
|
|
|
--set controller.hostPort.enabled=true \
|
|
|
|
|
--set controller.kind=DaemonSet \
|
|
|
|
|
--set controller.admissionWebhooks.enabled=false \
|
|
|
|
|
--wait --timeout 10m
|
|
|
|
|
|
|
|
|
|
cert-manager-install:
|
|
|
|
|
$(HELM_KUBECTL) repo add jetstack https://charts.jetstack.io --force-update
|
|
|
|
|
$(HELM_KUBECTL) repo update
|
|
|
|
|
$(HELM_KUBECTL) upgrade --install cert-manager jetstack/cert-manager \
|
|
|
|
|
--namespace cert-manager --create-namespace \
|
|
|
|
|
--set crds.enabled=true \
|
|
|
|
|
--wait --timeout 10m
|
|
|
|
|
|
|
|
|
|
cluster-prepare: rancher-storage ingress-nginx-install cert-manager-install
|
|
|
|
|
|
2026-09-20 10:49:09 +02:00
|
|
|
helm-lint:
|
2026-09-20 15:18:00 +02:00
|
|
|
KUBECONFIG="$(KUBECONFIG)" $(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-development.yaml
|
|
|
|
|
KUBECONFIG="$(KUBECONFIG)" $(HELM) lint $(HELM_CHART) -f $(HELM_CHART)/values-production.yaml
|
|
|
|
|
KUBECONFIG="$(KUBECONFIG)" $(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
|
2026-09-20 10:49:09 +02:00
|
|
|
-f $(HELM_CHART)/values-development.yaml >/dev/null
|
2026-09-20 15:18:00 +02:00
|
|
|
KUBECONFIG="$(KUBECONFIG)" $(HELM) template $(HELM_RELEASE) $(HELM_CHART) \
|
2026-09-20 10:49:09 +02:00
|
|
|
-f $(HELM_CHART)/values-production.yaml >/dev/null
|
|
|
|
|
|
|
|
|
|
helm-deploy-development:
|
2026-10-03 04:39:14 +02:00
|
|
|
$(HELM_KUBECTL) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
|
|
|
|
|
--namespace $(HELM_NAMESPACE)-development --create-namespace \
|
|
|
|
|
-f $(HELM_CHART)/values-development.yaml \
|
|
|
|
|
--set secrets.postgresqlPassword="go_guess" \
|
|
|
|
|
--set secrets.rabbitmqPassword="guest" \
|
|
|
|
|
$(GO_LOOSE_SET) \
|
|
|
|
|
--rollback-on-failure --wait --timeout 10m
|
2026-09-20 10:49:09 +02:00
|
|
|
|
|
|
|
|
helm-deploy-production:
|
2026-10-03 04:39:14 +02:00
|
|
|
$(HELM_KUBECTL) upgrade --install $(HELM_RELEASE) $(HELM_CHART) \
|
2026-09-20 10:49:09 +02:00
|
|
|
--namespace $(HELM_NAMESPACE)-production --create-namespace \
|
2026-10-03 04:39:14 +02:00
|
|
|
-f $(HELM_CHART)/values-production.yaml \
|
2026-09-20 23:56:09 +02:00
|
|
|
--set secrets.postgresqlPassword="go_guess" \
|
2026-10-03 04:39:14 +02:00
|
|
|
--set secrets.rabbitmqPassword="guest" \
|
|
|
|
|
$(GO_LOOSE_SET) \
|
|
|
|
|
--wait --timeout 10m
|
2026-09-20 23:56:09 +02:00
|
|
|
|
|
|
|
|
helm-down-production:
|
2026-10-03 04:39:14 +02:00
|
|
|
$(HELM_KUBECTL) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-production
|
2026-09-20 23:56:09 +02:00
|
|
|
|
|
|
|
|
helm-down-development:
|
2026-10-03 04:39:14 +02:00
|
|
|
$(HELM_KUBECTL) uninstall $(HELM_RELEASE) -n $(HELM_NAMESPACE)-development
|