main is protected on the remote and takes no direct pushes, so a release arrives as a pull request from dev. Document that flow. `make image` refuses to run outside main. That check has to live locally: the tag and the image are made before anything reaches the remote, so branch protection cannot catch a release built from the wrong branch. A pre-commit hook was tried and dropped. It needed installing per clone, so it enforced nothing that the remote was not already enforcing, while implying it did.
121 lines
4.3 KiB
Makefile
121 lines
4.3 KiB
Makefile
# Foodster. Run `make` for the target list.
|
|
|
|
COMPOSE ?= podman compose
|
|
BIN := foodster
|
|
PKG := ./cmd/foodster
|
|
STATIC := cmd/foodster/static
|
|
|
|
# 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 icons 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"
|
|
|
|
icons: ## Rasterise home-screen PNGs from assets/icon.svg and optimise them
|
|
rsvg-convert -w 180 -h 180 assets/icon.svg -o $(STATIC)/apple-touch-icon.png
|
|
rsvg-convert -w 192 -h 192 assets/icon.svg -o $(STATIC)/icon-192.png
|
|
rsvg-convert -w 512 -h 512 assets/icon.svg -o $(STATIC)/icon-512.png
|
|
# oxipng -o max alone loses to optipng on the 512; --zopfli wins at every
|
|
# size. Slow, but these are three tiny files built by hand.
|
|
oxipng -o max --zopfli --quiet \
|
|
$(STATIC)/apple-touch-icon.png $(STATIC)/icon-192.png $(STATIC)/icon-512.png
|
|
@ls -l $(STATIC)/*.png
|
|
|
|
vendor: ## Re-download the Datastar client (DATASTAR_VERSION=v1.0.3)
|
|
curl -sSfL -o $(STATIC)/datastar.js \
|
|
"https://cdn.jsdelivr.net/gh/starfederation/datastar@$(DATASTAR_VERSION)/bundles/datastar.js"
|
|
@head -1 $(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; }
|
|
@# A release tag must point into main, or the tag records a commit that
|
|
@# was never released.
|
|
@branch=$$(git symbolic-ref --short HEAD); \
|
|
if [ "$$branch" != "main" ]; then \
|
|
echo "releases are cut from main, not $$branch:"; \
|
|
echo " git switch main && git merge --ff-only dev"; \
|
|
exit 1; \
|
|
fi
|
|
@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
|