first commit
This commit is contained in:
137
Makefile
Normal file
137
Makefile
Normal file
@@ -0,0 +1,137 @@
|
||||
# ============================================================================
|
||||
# Krow backend — developer tasks
|
||||
#
|
||||
# Migration commands are thin wrappers over the golang-migrate CLI. The
|
||||
# migration FILES are the source of truth for the schema; nothing here or in
|
||||
# go-api/ ever issues DDL of its own.
|
||||
#
|
||||
# brew install golang-migrate # or see github.com/golang-migrate/migrate
|
||||
# ============================================================================
|
||||
|
||||
SHELL := /bin/bash
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# Capture APP_ENV as the process environment supplied it, BEFORE .env is
|
||||
# included. Make gives an included assignment precedence over the environment,
|
||||
# so without this `APP_ENV=production make migrate-down` would silently read
|
||||
# `development` out of .env and the guard below would not fire.
|
||||
APP_ENV_FROM_ENVIRONMENT := $(APP_ENV)
|
||||
|
||||
ifneq (,$(wildcard .env))
|
||||
include .env
|
||||
export
|
||||
endif
|
||||
|
||||
# The environment wins; .env is only the fallback. A command-line override
|
||||
# (`make migrate-down APP_ENV=production`) outranks both, as Make intends.
|
||||
ifneq (,$(APP_ENV_FROM_ENVIRONMENT))
|
||||
APP_ENV := $(APP_ENV_FROM_ENVIRONMENT)
|
||||
endif
|
||||
|
||||
MIGRATIONS_DIR ?= ./migrations
|
||||
DATABASE_SCHEMA ?= public
|
||||
DATABASE_SSLMODE ?= disable
|
||||
|
||||
# URL-encode the credentials and the database name. "Krow-force" is mixed-case
|
||||
# and hyphenated, and a password can contain anything; neither is safe raw.
|
||||
enc = $(shell printf '%s' '$(1)' | python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read(), safe=""))')
|
||||
|
||||
DB_URL = postgres://$(call enc,$(DATABASE_USER)):$(call enc,$(DATABASE_PASSWORD))@$(DATABASE_HOST):$(DATABASE_PORT)/$(call enc,$(DATABASE_NAME))?sslmode=$(DATABASE_SSLMODE)&search_path=$(DATABASE_SCHEMA)
|
||||
MIGRATE = migrate -path $(MIGRATIONS_DIR) -database "$(DB_URL)"
|
||||
|
||||
PSQL = psql -h $(DATABASE_HOST) -p $(DATABASE_PORT) -U $(DATABASE_USER) -d "$(DATABASE_NAME)"
|
||||
|
||||
.PHONY: help
|
||||
help: ## Show this help
|
||||
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
# ── Go ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
.PHONY: run
|
||||
run: ## Run the API against the local database
|
||||
cd go-api && go run ./cmd/api
|
||||
|
||||
.PHONY: build
|
||||
build: ## Compile the API to go-api/bin/api
|
||||
cd go-api && go build -o bin/api ./cmd/api
|
||||
|
||||
.PHONY: tidy
|
||||
tidy: ## go mod tidy
|
||||
cd go-api && go mod tidy
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## gofmt the module
|
||||
cd go-api && gofmt -w ./cmd ./internal
|
||||
|
||||
.PHONY: vet
|
||||
vet: ## go vet the module
|
||||
cd go-api && go vet ./...
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run the Go tests
|
||||
cd go-api && go test ./...
|
||||
|
||||
.PHONY: check
|
||||
check: fmt vet test ## Format, vet and test
|
||||
|
||||
# ── Database ────────────────────────────────────────────────────────────────
|
||||
|
||||
.PHONY: db-create
|
||||
db-create: ## Create the database if it does not exist (never drops anything)
|
||||
@if psql -h $(DATABASE_HOST) -p $(DATABASE_PORT) -U $(DATABASE_USER) -d postgres -tAc \
|
||||
"SELECT 1 FROM pg_database WHERE datname = '$(DATABASE_NAME)'" | grep -q 1; then \
|
||||
echo "database \"$(DATABASE_NAME)\" already exists — nothing to do"; \
|
||||
else \
|
||||
psql -h $(DATABASE_HOST) -p $(DATABASE_PORT) -U $(DATABASE_USER) -d postgres -c \
|
||||
'CREATE DATABASE "$(DATABASE_NAME)"' && echo "created \"$(DATABASE_NAME)\""; \
|
||||
fi
|
||||
|
||||
.PHONY: seed
|
||||
seed: ## Load the frontend demo dataset (idempotent upsert in one transaction)
|
||||
cd go-api && SEED_FIXTURE_PATH=$(CURDIR)/seed/fixtures/seed.json go run ./cmd/seed
|
||||
|
||||
.PHONY: gen-resources
|
||||
gen-resources: ## Regenerate domain descriptors from the live schema
|
||||
python3 scripts/gen_resources.py > go-api/internal/domain/resources_gen.go
|
||||
cd go-api && gofmt -w ./internal/domain
|
||||
|
||||
.PHONY: db-health
|
||||
db-health: ## Ask the running API for its database health
|
||||
@curl -fsS http://$(HTTP_HOST):$(HTTP_PORT)/health | python3 -m json.tool
|
||||
|
||||
# ── Migrations ──────────────────────────────────────────────────────────────
|
||||
|
||||
.PHONY: migrate-up
|
||||
migrate-up: ## Apply all pending migrations
|
||||
$(MIGRATE) up
|
||||
|
||||
.PHONY: migrate-down
|
||||
migrate-down: ## Roll back exactly one migration (guarded outside development)
|
||||
@if [ "$(APP_ENV)" != "development" ]; then \
|
||||
echo "refusing: migrate-down is only permitted when APP_ENV=development (got '$(APP_ENV)')"; \
|
||||
echo "roll back staging/production deliberately, with a reviewed plan and a fresh backup."; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(MIGRATE) down 1
|
||||
|
||||
.PHONY: migrate-status
|
||||
migrate-status: ## Show the currently applied migration version
|
||||
@$(MIGRATE) version
|
||||
|
||||
.PHONY: migrate-new
|
||||
migrate-new: ## Create a new migration pair: make migrate-new NAME=add_widgets
|
||||
@test -n "$(NAME)" || { echo "usage: make migrate-new NAME=add_widgets"; exit 1; }
|
||||
migrate create -ext sql -dir $(MIGRATIONS_DIR) -seq $(NAME)
|
||||
|
||||
.PHONY: migrate-force
|
||||
migrate-force: ## Clear a dirty state: make migrate-force VERSION=1
|
||||
@test -n "$(VERSION)" || { echo "usage: make migrate-force VERSION=1"; exit 1; }
|
||||
$(MIGRATE) force $(VERSION)
|
||||
|
||||
# There is deliberately no `migrate-drop` target. golang-migrate's `drop`
|
||||
# command deletes every table in the database; it must never be one keystroke
|
||||
# away from a developer who meant `down`. Run it by hand if you truly need it.
|
||||
|
||||
.PHONY: verify-schema
|
||||
verify-schema: ## Print the tables, enums, FKs and indexes that exist in the target schema
|
||||
@$(PSQL) -f scripts/verify_schema.sql
|
||||
Reference in New Issue
Block a user