BINARY_NAME = pg-api
VERSION = $(shell cat VERSION 2>/dev/null || echo "0.1.0")
BUILD_DATE = $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_COMMIT = $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
RUST_VERSION = $(shell rustc --version | cut -d' ' -f2)
INSTALL_PATH ?= /opt/prod/pg-api
BUILD_DIR = target
RELEASE_DIR = $(BUILD_DIR)/release
DEBUG_DIR = $(BUILD_DIR)/debug
DIST_DIR = dist
RUSTFLAGS = -C link-arg=-s
CARGO = cargo
COLOR_RESET = \033[0m
COLOR_BOLD = \033[1m
COLOR_GREEN = \033[32m
COLOR_YELLOW = \033[33m
COLOR_BLUE = \033[34m
COLOR_RED = \033[31m
.DEFAULT_GOAL := help
.PHONY: all build build-release test clean install uninstall package help version check lint fmt security-audit run dev setup-dev
help:
@echo "$(COLOR_BOLD)PostgreSQL API Service - Makefile$(COLOR_RESET)"
@echo "$(COLOR_BLUE)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_BOLD)Usage:$(COLOR_RESET)"
@echo " make $(COLOR_GREEN)<target>$(COLOR_RESET)"
@echo ""
@echo "$(COLOR_BOLD)Available targets:$(COLOR_RESET)"
@awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z_-]+:.*?##/ { printf " $(COLOR_GREEN)%-15s$(COLOR_RESET) %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
@echo ""
@echo "$(COLOR_BOLD)Examples:$(COLOR_RESET)"
@echo " $(COLOR_YELLOW)make build$(COLOR_RESET) @echo " $(COLOR_YELLOW)make release$(COLOR_RESET) @echo " $(COLOR_YELLOW)make test$(COLOR_RESET) @echo " $(COLOR_YELLOW)make package$(COLOR_RESET) @echo ""
@echo "$(COLOR_BOLD)Version:$(COLOR_RESET) $(VERSION)"
@echo "$(COLOR_BOLD)Commit:$(COLOR_RESET) $(GIT_COMMIT)"
all: lint test build
build:
@echo "$(COLOR_BLUE)Building debug binary...$(COLOR_RESET)"
@$(CARGO) build
@echo "$(COLOR_GREEN)✓ Debug build complete: $(DEBUG_DIR)/$(BINARY_NAME)$(COLOR_RESET)"
release:
@echo "$(COLOR_BLUE)Building release binary...$(COLOR_RESET)"
@RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build --release
@echo "$(COLOR_GREEN)✓ Release build complete: $(RELEASE_DIR)/$(BINARY_NAME)$(COLOR_RESET)"
@ls -lh $(RELEASE_DIR)/$(BINARY_NAME)
dev:
@echo "$(COLOR_BLUE)Starting development server...$(COLOR_RESET)"
@RUST_LOG=debug $(CARGO) run
run: build
@echo "$(COLOR_BLUE)Running debug binary...$(COLOR_RESET)"
@RUST_LOG=info $(DEBUG_DIR)/$(BINARY_NAME)
test:
@echo "$(COLOR_BLUE)Running tests...$(COLOR_RESET)"
@$(CARGO) test --all-features
@echo "$(COLOR_GREEN)✓ All tests passed$(COLOR_RESET)"
test-verbose:
@echo "$(COLOR_BLUE)Running tests (verbose)...$(COLOR_RESET)"
@$(CARGO) test --all-features -- --nocapture
test-single: ## Run a single test (use TEST=test_name)
@echo "$(COLOR_BLUE)Running test: $(TEST)$(COLOR_RESET)"
@$(CARGO) test $(TEST) -- --nocapture
bench:
@echo "$(COLOR_BLUE)Running benchmarks...$(COLOR_RESET)"
@$(CARGO) bench
check:
@echo "$(COLOR_BLUE)Checking code...$(COLOR_RESET)"
@$(CARGO) check --all-features
@echo "$(COLOR_GREEN)✓ Code check complete$(COLOR_RESET)"
lint:
@echo "$(COLOR_BLUE)Running clippy...$(COLOR_RESET)"
@$(CARGO) clippy -- -D warnings
@echo "$(COLOR_GREEN)✓ Linting complete$(COLOR_RESET)"
fmt:
@echo "$(COLOR_BLUE)Formatting code...$(COLOR_RESET)"
@$(CARGO) fmt
@echo "$(COLOR_GREEN)✓ Code formatted$(COLOR_RESET)"
fmt-check:
@echo "$(COLOR_BLUE)Checking code format...$(COLOR_RESET)"
@$(CARGO) fmt -- --check
@echo "$(COLOR_GREEN)✓ Code format check complete$(COLOR_RESET)"
security-audit:
@echo "$(COLOR_BLUE)Running security audit...$(COLOR_RESET)"
@cargo audit || (echo "$(COLOR_YELLOW)Install cargo-audit with: cargo install cargo-audit$(COLOR_RESET)" && exit 1)
@echo "$(COLOR_GREEN)✓ Security audit complete$(COLOR_RESET)"
install: release
@echo "$(COLOR_BLUE)Installing pg-api...$(COLOR_RESET)"
@if [ ! -f setup.py ]; then \
echo "$(COLOR_RED)Error: setup.py not found$(COLOR_RESET)"; \
exit 1; \
fi
@sudo python3 setup.py --non-interactive --action install --install-path $(INSTALL_PATH)
@echo "$(COLOR_GREEN)✓ Installation complete$(COLOR_RESET)"
uninstall:
@echo "$(COLOR_BLUE)Uninstalling pg-api...$(COLOR_RESET)"
@if [ ! -f setup.py ]; then \
echo "$(COLOR_RED)Error: setup.py not found$(COLOR_RESET)"; \
exit 1; \
fi
@sudo python3 setup.py --non-interactive --action uninstall --install-path $(INSTALL_PATH)
@echo "$(COLOR_GREEN)✓ Uninstallation complete$(COLOR_RESET)"
package: release
@echo "$(COLOR_BLUE)Creating distribution package...$(COLOR_RESET)"
@mkdir -p $(DIST_DIR)
@ @rm -rf $(DIST_DIR)/pg-api-$(VERSION)
@mkdir -p $(DIST_DIR)/pg-api-$(VERSION)
@ @cp -r src Cargo.toml Cargo.lock setup.py Makefile VERSION LICENSE.md CHANGELOG.md roadmap.md $(DIST_DIR)/pg-api-$(VERSION)/ 2>/dev/null || true
@cp -r config $(DIST_DIR)/pg-api-$(VERSION)/
@mkdir -p $(DIST_DIR)/pg-api-$(VERSION)/target/release
@cp $(RELEASE_DIR)/$(BINARY_NAME) $(DIST_DIR)/pg-api-$(VERSION)/target/release/
@ @cd $(DIST_DIR) && tar -czf pg-api-$(VERSION).tar.gz pg-api-$(VERSION)
@rm -rf $(DIST_DIR)/pg-api-$(VERSION)
@echo "$(COLOR_GREEN)✓ Package created: $(DIST_DIR)/pg-api-$(VERSION).tar.gz$(COLOR_RESET)"
@ls -lh $(DIST_DIR)/pg-api-$(VERSION).tar.gz
dist: package
clean:
@echo "$(COLOR_BLUE)Cleaning build artifacts...$(COLOR_RESET)"
@$(CARGO) clean
@rm -rf $(DIST_DIR)
@echo "$(COLOR_GREEN)✓ Clean complete$(COLOR_RESET)"
version:
@echo "$(COLOR_BOLD)Version Information:$(COLOR_RESET)"
@echo " pg-api: $(VERSION)"
@echo " Git commit: $(GIT_COMMIT)"
@echo " Build date: $(BUILD_DATE)"
@echo " Rust: $(RUST_VERSION)"
setup-dev:
@echo "$(COLOR_BLUE)Setting up development environment...$(COLOR_RESET)"
@ @if ! command -v rustc > /dev/null; then \
echo "$(COLOR_YELLOW)Installing Rust...$(COLOR_RESET)"; \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y; \
. $$HOME/.cargo/env; \
fi
@ @echo "$(COLOR_BLUE)Installing development tools...$(COLOR_RESET)"
@cargo install cargo-watch cargo-audit || true
@ @if [ -d .git ]; then \
echo "#!/bin/sh" > .git/hooks/pre-commit; \
echo "make fmt-check" >> .git/hooks/pre-commit; \
echo "make lint" >> .git/hooks/pre-commit; \
chmod +x .git/hooks/pre-commit; \
echo "$(COLOR_GREEN)✓ Pre-commit hooks installed$(COLOR_RESET)"; \
fi
@echo "$(COLOR_GREEN)✓ Development environment ready$(COLOR_RESET)"
docker-build:
@echo "$(COLOR_BLUE)Building Docker image...$(COLOR_RESET)"
@docker build -t pg-api:$(VERSION) -t pg-api:latest .
@echo "$(COLOR_GREEN)✓ Docker image built: pg-api:$(VERSION)$(COLOR_RESET)"
docker-run:
@echo "$(COLOR_BLUE)Running Docker container...$(COLOR_RESET)"
@docker run -d \
--name pg-api \
-p 8080:8080 \
-v $(PWD)/config:/opt/pg-api/config \
--env-file .env \
pg-api:latest
@echo "$(COLOR_GREEN)✓ Container started: pg-api$(COLOR_RESET)"
db-setup:
@echo "$(COLOR_BLUE)Setting up PostgreSQL database...$(COLOR_RESET)"
@if [ -f setup.py ]; then \
sudo python3 setup.py --action check; \
else \
echo "$(COLOR_RED)Error: setup.py not found$(COLOR_RESET)"; \
exit 1; \
fi
db-migrate:
@echo "$(COLOR_BLUE)Running database migrations...$(COLOR_RESET)"
@if [ -d migrations ]; then \
for file in migrations/*.sql; do \
echo " Applying: $$file"; \
psql -h localhost -U postgres -f $$file; \
done; \
echo "$(COLOR_GREEN)✓ Migrations complete$(COLOR_RESET)"; \
else \
echo "$(COLOR_YELLOW)No migrations found$(COLOR_RESET)"; \
fi
service-start:
@echo "$(COLOR_BLUE)Starting pg-api service...$(COLOR_RESET)"
@sudo systemctl start pg-api
@echo "$(COLOR_GREEN)✓ Service started$(COLOR_RESET)"
service-stop:
@echo "$(COLOR_BLUE)Stopping pg-api service...$(COLOR_RESET)"
@sudo systemctl stop pg-api
@echo "$(COLOR_GREEN)✓ Service stopped$(COLOR_RESET)"
service-restart:
@echo "$(COLOR_BLUE)Restarting pg-api service...$(COLOR_RESET)"
@sudo systemctl restart pg-api
@echo "$(COLOR_GREEN)✓ Service restarted$(COLOR_RESET)"
service-status:
@sudo systemctl status pg-api
service-logs:
@sudo journalctl -u pg-api -f
release-patch:
@echo "$(COLOR_BLUE)Creating patch release...$(COLOR_RESET)"
@./scripts/release.sh patch
release-minor:
@echo "$(COLOR_BLUE)Creating minor release...$(COLOR_RESET)"
@./scripts/release.sh minor
release-major:
@echo "$(COLOR_BLUE)Creating major release...$(COLOR_RESET)"
@./scripts/release.sh major
-include Makefile.local