BIN_DIR := bin GO_CACHE_DIR := $(CURDIR)/.cache/go-build SERVER_BIN := $(BIN_DIR)/amcs-server CMD_SERVER := ./cmd/amcs-server BUILDINFO_PKG := git.warky.dev/wdevs/amcs/internal/buildinfo UI_DIR := $(CURDIR)/ui PATCH_INCREMENT ?= 1 RELEASE_VERSION ?= RELEASE_REMOTE ?= origin VERSION_TAG ?= $(shell git describe --tags --exact-match 2>/dev/null || echo dev) COMMIT_SHA ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) BUILD_DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) RELSPEC ?= $(shell command -v relspec 2>/dev/null || echo $(HOME)/go/bin/relspec) SCHEMA_FILES := $(sort $(wildcard schema/*.dbml)) MERGE_TARGET_TMP := $(CURDIR)/.cache/schema.merge-target.dbml GENERATED_SCHEMA_MIGRATION := migrations/020_generated_schema.sql GENERATED_MODELS_DIR := internal/generatedmodels PNPM ?= pnpm LDFLAGS := -s -w \ -X $(BUILDINFO_PKG).Version=$(VERSION_TAG) \ -X $(BUILDINFO_PKG).TagName=$(VERSION_TAG) \ -X $(BUILDINFO_PKG).Commit=$(COMMIT_SHA) \ -X $(BUILDINFO_PKG).BuildDate=$(BUILD_DATE) .PHONY: all build clean migrate release-version release-build test generate-migrations generate-models check-schema-drift build-cli ui-install ui-build ui-dev ui-check help all: build help: @echo "Available targets:" @echo " build Build server binary (includes UI build)" @echo " build-cli Build CLI binary" @echo " test Run all tests (includes UI check)" @echo " clean Remove build artifacts" @echo " migrate Run database migrations" @echo " release-version Tag and push a release (auto patch bump or RELEASE_VERSION=vX.Y.Z)" @echo " release-build Build with a specific release tag (RELEASE_VERSION=vX.Y.Z)" @echo " generate-migrations Generate SQL migration from DBML schema files" @echo " generate-models Generate Go models from DBML schema" @echo " check-schema-drift Verify generated migration matches current schema" @echo " ui-install Install UI dependencies" @echo " ui-build Build UI assets" @echo " ui-dev Start UI dev server" @echo " ui-check Run UI type checks" build: ui-build @mkdir -p $(BIN_DIR) go build -ldflags "$(LDFLAGS)" -o $(SERVER_BIN) $(CMD_SERVER) ui-install: cd $(UI_DIR) && $(PNPM) install --frozen-lockfile ui-build: ui-install cd $(UI_DIR) && $(PNPM) run build ui-dev: ui-install cd $(UI_DIR) && $(PNPM) run dev ui-check: ui-install cd $(UI_DIR) && $(PNPM) run check test: ui-check @mkdir -p $(GO_CACHE_DIR) GOCACHE=$(GO_CACHE_DIR) go test ./... release-version: @case "$(PATCH_INCREMENT)" in \ ''|*[!0-9]*|0) echo "PATCH_INCREMENT must be a positive integer" >&2; exit 1 ;; \ esac @if ! git diff --quiet || ! git diff --cached --quiet; then \ echo "Refusing to release from a dirty working tree. Commit or stash changes first." >&2; \ exit 1; \ fi @next_tag="$(RELEASE_VERSION)"; \ if [ -z "$$next_tag" ]; then \ latest=$$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n 1); \ if [ -z "$$latest" ]; then latest="v0.0.0"; fi; \ version=$${latest#v}; \ major=$${version%%.*}; \ rest=$${version#*.}; \ minor=$${rest%%.*}; \ patch=$${rest##*.}; \ next_patch=$$((patch + $(PATCH_INCREMENT))); \ next_tag="v$$major.$$minor.$$next_patch"; \ fi; \ case "$$next_tag" in \ v[0-9]*.[0-9]*.[0-9]*) ;; \ *) echo "RELEASE_VERSION must look like vX.Y.Z (got '$$next_tag')" >&2; exit 1 ;; \ esac; \ if git rev-parse -q --verify "refs/tags/$$next_tag" >/dev/null; then \ echo "$$next_tag already exists" >&2; \ exit 1; \ fi; \ git tag -a "$$next_tag" -m "Release $$next_tag"; \ git push $(RELEASE_REMOTE) "$$next_tag"; \ $(MAKE) release-build RELEASE_VERSION="$$next_tag"; \ echo "Released $$next_tag" release-build: @case "$(RELEASE_VERSION)" in \ v[0-9]*.[0-9]*.[0-9]*) ;; \ *) echo "RELEASE_VERSION must look like vX.Y.Z" >&2; exit 1 ;; \ esac @$(MAKE) build build-cli VERSION_TAG="$(RELEASE_VERSION)" migrate: ./scripts/migrate.sh clean: rm -rf $(BIN_DIR) generate-migrations: @test -n "$(SCHEMA_FILES)" || (echo "No DBML schema files found in schema/" >&2; exit 1) @command -v $(RELSPEC) >/dev/null 2>&1 || (echo "relspec not found; install git.warky.dev/wdevs/relspecgo/cmd/relspec@latest" >&2; exit 1) @mkdir -p $(dir $(MERGE_TARGET_TMP)) @: > $(MERGE_TARGET_TMP) @schema_list=$$(printf '%s\n' $(SCHEMA_FILES) | paste -sd, -); \ $(RELSPEC) merge --target dbml --target-path $(MERGE_TARGET_TMP) --source dbml --from-list "$$schema_list" --output pgsql --output-path $(GENERATED_SCHEMA_MIGRATION) generate-models: @test -n "$(SCHEMA_FILES)" || (echo "No DBML schema files found in schema/" >&2; exit 1) @./scripts/generate-models.sh check-schema-drift: @test -f $(GENERATED_SCHEMA_MIGRATION) || (echo "$(GENERATED_SCHEMA_MIGRATION) is missing; run make generate-migrations" >&2; exit 1) @command -v $(RELSPEC) >/dev/null 2>&1 || (echo "relspec not found; install git.warky.dev/wdevs/relspecgo/cmd/relspec@latest" >&2; exit 1) @mkdir -p $(dir $(MERGE_TARGET_TMP)) @tmpfile=$$(mktemp); \ : > $(MERGE_TARGET_TMP); \ schema_list=$$(printf '%s\n' $(SCHEMA_FILES) | paste -sd, -); \ $(RELSPEC) merge --target dbml --target-path $(MERGE_TARGET_TMP) --source dbml --from-list "$$schema_list" --output pgsql --output-path $$tmpfile; \ if ! cmp -s $$tmpfile $(GENERATED_SCHEMA_MIGRATION); then \ echo "Schema drift detected between schema/*.dbml and $(GENERATED_SCHEMA_MIGRATION)" >&2; \ diff -u $(GENERATED_SCHEMA_MIGRATION) $$tmpfile || true; \ rm -f $$tmpfile; \ exit 1; \ fi; \ rm -f $$tmpfile build-cli: @mkdir -p $(BIN_DIR) go build -o $(BIN_DIR)/amcs-cli ./cmd/amcs-cli