Files
foodster/Makefile
T
Esa Kataja e4503e8433 Build the Kirjaa log flow and Historia list
Stage 1's point is collecting eating history, so the logging path is the one
that has to be frictionless: pick a dish, tick sides, done.

Kirjaa:
- dishes ordered and sized by how often they have been eaten, so the likely
  answer is the biggest target on the screen
- picking a dish opens the sides step; a dish with has_sides false says so
  instead of offering an empty list
- saving redirects, so a refresh cannot double-post
- a day already logged shows the entry with edit and delete. Editing reopens
  the sides step with the existing sides ticked, which makes editing and
  creating the same screen
- day switcher and a server-side search over the catalog

Historia walks back day by day to the oldest entry, so a day nobody wrote
down appears as an explicit gap rather than quietly missing.

No JavaScript is involved: every interaction is a link or a form, and the
checked-chip styling is :has(input:checked). Datastar stays loaded but unused
until an interaction genuinely needs to avoid a page load.

Also fix a Makefile ordering bug: lint did not depend on generate, so `go vet`
could run against templ output that was being rewritten. check now runs its
phases as sub-makes so `make -j` cannot interleave them.

Records two features that are specified but not built: dish CRUD in the UI
(§7.3, only import exists today) and a per-device light/dark switch (§7.4).
The switch must show the state that is active, not the one clicking produces.
2026-09-05 18:29:38 +03:00

102 lines
3.4 KiB
Makefile

# Foodster. Run `make` for the target list.
COMPOSE ?= podman compose
BIN := foodster
PKG := ./cmd/foodster
# Vendored Datastar client. Bump, run `make vendor`, commit the result.
DATASTAR_VERSION ?= v1.0.3
SEED ?= seeds/testi.json
# Registry coordinates, shared password and TZ live here. Gitignored.
ifneq (,$(wildcard .env))
include .env
export
endif
# Generated templ output is excluded — it is not ours to format.
GOFILES = $(shell find . -name '*.go' -not -name '*_templ.go' 2>/dev/null)
.DEFAULT_GOAL := help
.PHONY: help generate build run seed test smoke check lint fix vendor image push release up down logs clean
help: ## Show this help
@grep -hE '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) \
| awk -F':.*## ' '{printf " \033[1m%-9s\033[0m %s\n", $$1, $$2}'
generate: ## Generate Go from .templ files
go tool templ generate
build: generate ## Build ./foodster
CGO_ENABLED=0 go build -trimpath \
-ldflags="-s -w -X main.version=dev" -o $(BIN) $(PKG)
run: generate ## Run locally on :8080 (database in ./data)
FOODSTER_PASSWORD=$${FOODSTER_PASSWORD:-dev} go run $(PKG)
seed: ## Import a dish bundle (SEED=seeds/testi.json)
go run $(PKG) -import $(SEED)
test: generate ## Run unit tests
go test ./...
smoke: generate ## End-to-end check: auth, static assets, bundle import
./scripts/smoke.sh
# Sub-makes rather than prerequisites: these must run in order even under
# `make -j`, and a parallel run vets generated code that is being rewritten.
check: ## Everything that must pass before a commit
@$(MAKE) --no-print-directory lint
@$(MAKE) --no-print-directory test
@$(MAKE) --no-print-directory smoke
@echo "check: all passed"
vendor: ## Re-download the Datastar client (DATASTAR_VERSION=v1.0.3)
curl -sSfL -o cmd/foodster/static/datastar.js \
"https://cdn.jsdelivr.net/gh/starfederation/datastar@$(DATASTAR_VERSION)/bundles/datastar.js"
@head -1 cmd/foodster/static/datastar.js
lint: generate ## go vet, gofmt check, golangci-lint when installed
go vet ./...
@bad=$$(gofmt -l $(GOFILES) 2>/dev/null); \
if [ -n "$$bad" ]; then echo "gofmt needed:"; echo "$$bad"; exit 1; fi
@if command -v golangci-lint >/dev/null 2>&1; then golangci-lint run; \
else echo "golangci-lint not installed - skipped"; fi
fix: ## Format Go and templ sources, tidy go.mod
@if [ -n "$(GOFILES)" ]; then gofmt -w $(GOFILES); fi
go tool templ fmt .
go mod tidy
image: ## Build and tag an image as vYYYYMMDD-N. Creates a git tag.
@test -n "$(FOODSTER_REPO)" || { echo "set FOODSTER_REPO in .env"; exit 1; }
@day=$$(date +%Y%m%d); \
tag="v$$day-$$(( $$(git tag -l "v$$day-*" | wc -l) + 1 ))"; \
echo "==> $$tag"; \
git tag "$$tag"; \
podman build --platform linux/amd64 --build-arg VERSION="$$tag" \
-t "$(FOODSTER_REPO):$$tag" -t "$(FOODSTER_REPO):latest" .
push: ## Push the newest tag and :latest
@test -n "$(FOODSTER_REPO)" || { echo "set FOODSTER_REPO in .env"; exit 1; }
@tag=$$(git tag -l 'v*' --sort=-creatordate | head -n1); \
test -n "$$tag" || { echo "no tags yet - run make image"; exit 1; }; \
podman push "$(FOODSTER_REPO):$$tag"; \
podman push "$(FOODSTER_REPO):latest"
release: image push ## Build, tag and push in one go
up: ## Start the stack
@mkdir -p data # or the engine creates it root-owned and the app cannot write
$(COMPOSE) up -d
down: ## Stop the stack
$(COMPOSE) down
logs: ## Follow app logs
$(COMPOSE) logs -f app
clean: ## Remove the binary and generated templates
rm -f $(BIN)
find . -name '*_templ.go' -delete