Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GiECd9RWGMKV7n3K1mdy8T
182 lines
9.2 KiB
Makefile
182 lines
9.2 KiB
Makefile
# LA LEGGENDA DEL REGOLO — comandi di sviluppo, verifica, grafica e Docker.
|
|
# `make` o `make help` elenca i target.
|
|
|
|
SHELL := /bin/bash
|
|
.DEFAULT_GOAL := help
|
|
|
|
PORT ?= 8000
|
|
DOCKER_PORT ?= 8080
|
|
IMAGE ?= leggenda-regolo
|
|
TAG ?= latest
|
|
COMPOSE ?= DOCKER_PORT=$(DOCKER_PORT) docker compose
|
|
PYTHON ?= python3
|
|
NODE ?= node
|
|
# Personaggio da ritagliare: make character NAME=andrea (foglio in assets/raw/$(NAME)-sheet.png, 4x2)
|
|
NAME ?= andrea
|
|
SHEET ?= assets/raw/$(NAME)-sheet.png
|
|
HEIGHT ?= 120
|
|
FRAMES ?= walk_1,walk_2,walk_3,walk_4,stand,talk,take,back
|
|
REF ?= stand
|
|
# Sfondo da preparare: make background SRC=assets/generated/pieve-dalla-salita.png (CROP=x,y,w,h facoltativo)
|
|
SRC ?=
|
|
DST ?= assets/scenes/$(notdir $(SRC))
|
|
CROP ?=
|
|
COLORS ?= 64
|
|
|
|
.PHONY: help serve open test browser verify check-public bump voci voci-elenco sfondi sfondi-genera sfondi-confronto background character \
|
|
build up down restart logs ps shell image-size deploy deploy-vps deploy-logs clean distclean
|
|
|
|
## ------------------------------------------------------------ sviluppo
|
|
|
|
help: ## Mostra questo aiuto
|
|
@echo "LA LEGGENDA DEL REGOLO — target disponibili:"; echo
|
|
@grep -hE '^[a-zA-Z0-9_-]+:.*?## ' $(MAKEFILE_LIST) | \
|
|
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
@echo; echo "Variabili: PORT=$(PORT) DOCKER_PORT=$(DOCKER_PORT) IMAGE=$(IMAGE):$(TAG)"
|
|
|
|
serve: ## Avvia il server statico locale (PORT=8000)
|
|
@echo "→ http://localhost:$(PORT)"
|
|
$(PYTHON) -m http.server $(PORT) --bind 0.0.0.0
|
|
|
|
open: ## Apre il gioco nel browser predefinito (serve già avviato)
|
|
@xdg-open "http://localhost:$(PORT)" >/dev/null 2>&1 || open "http://localhost:$(PORT)"
|
|
|
|
## ------------------------------------------------------------ verifica
|
|
|
|
test: ## Test della logica, della storia, della soluzione completa e del generatore
|
|
$(NODE) --test tests/*.test.mjs
|
|
$(PYTHON) -m unittest discover -s tests -p "test_*.py" -q
|
|
|
|
browser: ## Partita completa nel browser con Playwright
|
|
$(NODE) tests/browser.mjs
|
|
|
|
verify: test browser check-public ## Tutti i controlli
|
|
|
|
check-public: ## Prima di pubblicare: niente prompt, fogli grezzi, segreti o nomi della rete di casa (tutta la storia)
|
|
bash scripts/check-public.sh
|
|
|
|
bump: ## Nuova versione (PARTE=patch|minor|major): verifica, commit e tag v<versione>; poi make deploy
|
|
scripts/bump.sh $(or $(PARTE),patch)
|
|
|
|
## ------------------------------------------------------------ grafica
|
|
|
|
voci: ## Voci dei personaggi con XTTS sulla GPU: solo le battute nuove o cambiate (RIFAI='testo' per ritentarne una)
|
|
$(NODE) tools/voci.mjs $(if $(RIFAI),--rifai "$(RIFAI)")
|
|
|
|
ascolta: ## Riascolta le voci con Whisper (mbot ascolta) e elenca quelle che dicono altro (SOLO='testo' per alcune)
|
|
$(NODE) tools/ascolta.mjs $(if $(SOLO),"$(SOLO)")
|
|
|
|
voci-elenco: ## Quali battute mancano di voce, senza generare niente
|
|
$(NODE) tools/voci.mjs --dry
|
|
|
|
sfondi: ## Prova a secco del generatore: quali foto di assets/raw/foto/ genererebbe (nessuna API)
|
|
$(PYTHON) tools/genera.py --dry-run
|
|
|
|
sfondi-genera: ## Genera davvero gli sfondi con l'API (serve OPENAI_API_KEY; ogni immagine si paga)
|
|
@test -n "$$OPENAI_API_KEY" || { echo "manca OPENAI_API_KEY nell'ambiente"; exit 2; }
|
|
$(PYTHON) tools/genera.py
|
|
|
|
sfondi-confronto: ## Rifà il confronto foto/immagini in assets/generated/index.html e lo apre
|
|
$(PYTHON) tools/genera.py --gallery-only
|
|
@xdg-open assets/generated/index.html >/dev/null 2>&1 || open assets/generated/index.html
|
|
|
|
miniature: ## Le miniature della mappa (assets/scenes/mini/) dagli sfondi
|
|
$(PYTHON) tools/miniature.py
|
|
|
|
background: ## Porta uno sfondo a 640x360 nel gioco (SRC=..., DST=..., CROP=x,y,w,h, COLORS=64)
|
|
@test -n "$(SRC)" || { echo "uso: make background SRC=assets/generated/nome.png [CROP=x,y,w,h]"; exit 2; }
|
|
$(PYTHON) tools/prepare_background.py $(SRC) $(DST) $(if $(CROP),--crop $(CROP)) --colors $(COLORS)
|
|
|
|
character: ## Ritaglia un foglio sprite 4x2 e prepara il personaggio (NAME=andrea, SHEET=..., HEIGHT=120, FRAMES=..., REF=stand, FIX=wave=1.3)
|
|
$(PYTHON) tools/slice_sprites.py --sheet $(SHEET) --out /tmp/regolo-$(NAME) --cols 4 --rows 2 \
|
|
--despill --names $(FRAMES) --prefix $(NAME)_
|
|
$(PYTHON) tools/prepare_character.py /tmp/regolo-$(NAME) $(NAME) assets/characters --height $(HEIGHT) \
|
|
--frames $(FRAMES) --ref $(REF) $(if $(FIX),--fix $(FIX))
|
|
|
|
## ------------------------------------------------------------ docker
|
|
|
|
build: ## Costruisce l'immagine Docker
|
|
docker build -t $(IMAGE):$(TAG) .
|
|
|
|
up: ## Avvia il container (DOCKER_PORT=8080)
|
|
$(COMPOSE) up -d --build
|
|
@echo "→ http://localhost:$(DOCKER_PORT)"
|
|
|
|
down: ## Ferma e rimuove il container
|
|
$(COMPOSE) down
|
|
|
|
restart: down up ## Riavvia il container
|
|
|
|
logs: ## Segue i log del container
|
|
$(COMPOSE) logs -f
|
|
|
|
ps: ## Stato del container
|
|
$(COMPOSE) ps
|
|
|
|
shell: ## Shell dentro il container
|
|
$(COMPOSE) exec leggenda-regolo sh
|
|
|
|
image-size: ## Dimensione dell'immagine
|
|
@docker image ls $(IMAGE):$(TAG) --format '{{.Repository}}:{{.Tag}} {{.Size}}'
|
|
|
|
## ------------------------------------------------------------ deploy su un server proprio
|
|
|
|
# Host e indirizzo stanno in deploy.local.mk, fuori da git, per esempio:
|
|
# DEPLOY_HOST = root@mio-server
|
|
# DEPLOY_URL = https://gioco.esempio
|
|
# VPS_URL = https://gioco.esempio (make deploy-vps controlla lì la versione pubblicata)
|
|
# VPS_HOST = mio-vps (facoltativo: una seconda copia, con make deploy-vps)
|
|
# VPS_DIR = docker/leggenda-regolo
|
|
-include deploy.local.mk
|
|
DEPLOY_DIR ?= /root/leggenda-regolo
|
|
DEPLOY_TMP := $(shell mktemp -d -u /tmp/regolo-deploy.XXXXXX)
|
|
|
|
# Si pubblica l'ultimo commit (git archive HEAD), mai la cartella di lavoro: un'altra sessione può avere modifiche a
|
|
# metà. Test su quella copia, immagine costruita e provata qui, poi spedita già pronta (docker save | docker load):
|
|
# sul server non si compila niente.
|
|
SMOKE_PORT ?= 18737
|
|
deploy: ## Pubblica l'ultimo commit: test, immagine costruita e provata qui, spedita al server e riavviata
|
|
@test -n "$(DEPLOY_HOST)" || { echo "manca DEPLOY_HOST: scrivilo in deploy.local.mk"; exit 2; }
|
|
mkdir -p $(DEPLOY_TMP) && git archive HEAD | tar -x -C $(DEPLOY_TMP)
|
|
cd $(DEPLOY_TMP) && $(NODE) --test tests/*.test.mjs
|
|
docker build -q -t $(IMAGE):latest -t $(IMAGE):$$(git rev-parse --short HEAD) $(DEPLOY_TMP)
|
|
@docker rm -f $(IMAGE)-prova >/dev/null 2>&1 || true
|
|
docker run -d --rm --name $(IMAGE)-prova -p 127.0.0.1:$(SMOKE_PORT):80 $(IMAGE):latest >/dev/null
|
|
@ok=1; sleep 1; for u in / /src/main.js /assets/voices/index.json /assets/audio/cartello.mp3; do \
|
|
c=$$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:$(SMOKE_PORT)$$u); echo " prova $$u → $$c"; [ "$$c" = 200 ] || ok=0; done; \
|
|
docker rm -f $(IMAGE)-prova >/dev/null; [ $$ok = 1 ] || { echo "l'immagine non risponde come deve: non la spedisco"; exit 1; }
|
|
ssh $(DEPLOY_HOST) 'mkdir -p $(DEPLOY_DIR)'
|
|
scp -q $(DEPLOY_TMP)/docker-compose.homeserver.yml $(DEPLOY_HOST):$(DEPLOY_DIR)/docker-compose.yml
|
|
docker save $(IMAGE):latest | gzip | ssh $(DEPLOY_HOST) 'gunzip | docker load -q && cd $(DEPLOY_DIR) && docker compose up -d && docker image prune -f >/dev/null'
|
|
rm -rf $(DEPLOY_TMP)
|
|
@# Sul server il prune toglie l'immagine vecchia; qui restano solo latest e quella appena pubblicata.
|
|
@docker image ls $(IMAGE) --format '{{.Tag}}' | grep -v -x -e latest -e $$(git rev-parse --short HEAD) | \
|
|
xargs -r -I{} docker image rm -f $(IMAGE):{} >/dev/null
|
|
@echo "→ $(DEPLOY_URL) ($$(git log -1 --format='%h %s'))"
|
|
|
|
deploy-vps: ## Spedisce al VPS (VPS_HOST, VPS_DIR in deploy.local.mk) l'immagine dell'ultimo commit già provata da make deploy
|
|
@test -n "$(VPS_HOST)" -a -n "$(VPS_DIR)" || { echo "mancano VPS_HOST e VPS_DIR: scrivili in deploy.local.mk"; exit 2; }
|
|
@docker image inspect $(IMAGE):$$(git rev-parse --short HEAD) >/dev/null 2>&1 || \
|
|
{ echo "manca l'immagine dell'ultimo commit ($$(git rev-parse --short HEAD)): prima make deploy"; exit 1; }
|
|
ssh $(VPS_HOST) 'mkdir -p $(VPS_DIR)'
|
|
git show HEAD:docker-compose.homeserver.yml | ssh $(VPS_HOST) 'cat > $(VPS_DIR)/docker-compose.yml'
|
|
docker save $(IMAGE):$$(git rev-parse --short HEAD) $(IMAGE):latest | gzip | \
|
|
ssh $(VPS_HOST) 'gunzip | docker load -q && cd $(VPS_DIR) && docker compose up -d && docker image prune -f >/dev/null'
|
|
@ssh $(VPS_HOST) "docker exec $(IMAGE) grep -o \"VERSION = '[^']*'\" /usr/share/nginx/html/src/version.js" | sed 's/^/→ $(VPS_HOST): /'
|
|
@# L'indirizzo pubblico (VPS_URL), se c'è: deve servire la versione appena spedita.
|
|
@test -z "$(VPS_URL)" || { v=$$(grep -o "VERSION = '[^']*'" src/version.js); \
|
|
for i in 1 2 3 4 5; do curl -s $(VPS_URL)/src/version.js | grep -qF "$$v" && break; sleep 2; done; \
|
|
curl -s $(VPS_URL)/src/version.js | grep -qF "$$v" && echo "→ $(VPS_URL): $$v" || { echo "$(VPS_URL) non serve $$v"; exit 1; }; }
|
|
|
|
deploy-logs: ## Log del container sul server di deploy
|
|
@test -n "$(DEPLOY_HOST)" || { echo "manca DEPLOY_HOST: scrivilo in deploy.local.mk"; exit 2; }
|
|
ssh $(DEPLOY_HOST) 'cd $(DEPLOY_DIR) && docker compose logs -f --tail 50'
|
|
|
|
## ------------------------------------------------------------ pulizia
|
|
|
|
clean: ## Rimuove file temporanei
|
|
find . -name '__pycache__' -type d -prune -exec rm -rf {} +
|
|
|
|
distclean: clean down ## clean + container + immagine Docker
|
|
-docker image rm $(IMAGE):$(TAG)
|