133 lines
4.4 KiB
Makefile
133 lines
4.4 KiB
Makefile
# =============================================================================
|
|
# Makefile — Common development targets
|
|
# =============================================================================
|
|
# Reads .ci/config.env for settings. All targets are fail-safe:
|
|
# they skip gracefully if tools or files are not present.
|
|
# =============================================================================
|
|
|
|
SHELL := /bin/bash
|
|
.DEFAULT_GOAL := help
|
|
|
|
# Load config if it exists
|
|
-include .ci/config.env
|
|
export
|
|
|
|
# Defaults if config is missing
|
|
ENABLE_DOCKER ?= false
|
|
DOCKER_PUSH ?= false
|
|
REGISTRY_HOST ?= git.hiddenden.cafe
|
|
IMAGE_OWNER ?= auto
|
|
IMAGE_NAME ?= auto
|
|
|
|
# Derive image owner/name dynamically if set to "auto"
|
|
_OWNER := $(if $(filter auto,$(IMAGE_OWNER)),$(shell basename $$(dirname $$(pwd))),$(IMAGE_OWNER))
|
|
_NAME := $(if $(filter auto,$(IMAGE_NAME)),$(shell basename $$(pwd)),$(IMAGE_NAME))
|
|
_IMAGE := $(REGISTRY_HOST)/$(_OWNER)/$(_NAME)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
|
.PHONY: help
|
|
help: ## Show this help message
|
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
|
|
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Code quality
|
|
# ---------------------------------------------------------------------------
|
|
|
|
.PHONY: fmt
|
|
fmt: ## Format code (Python: black/ruff; JS: prettier)
|
|
@if command -v ruff >/dev/null 2>&1; then \
|
|
echo ">>> ruff format ."; ruff format .; \
|
|
elif command -v black >/dev/null 2>&1; then \
|
|
echo ">>> black ."; black .; \
|
|
else \
|
|
echo "SKIP: no Python formatter found (install ruff or black)"; \
|
|
fi
|
|
@if [ -f package.json ] && command -v npx >/dev/null 2>&1; then \
|
|
if npx --no-install prettier --version >/dev/null 2>&1; then \
|
|
echo ">>> npx prettier --write ."; npx prettier --write .; \
|
|
else \
|
|
echo "SKIP: prettier not installed"; \
|
|
fi \
|
|
fi
|
|
|
|
.PHONY: lint
|
|
lint: ## Run linters (Python: ruff/flake8; JS: eslint)
|
|
@if command -v ruff >/dev/null 2>&1; then \
|
|
echo ">>> ruff check ."; ruff check .; \
|
|
elif command -v flake8 >/dev/null 2>&1; then \
|
|
echo ">>> flake8 ."; flake8 .; \
|
|
else \
|
|
echo "SKIP: no Python linter found (install ruff or flake8)"; \
|
|
fi
|
|
@if [ -f package.json ] && command -v npx >/dev/null 2>&1; then \
|
|
if npx --no-install eslint --version >/dev/null 2>&1; then \
|
|
echo ">>> npx eslint ."; npx eslint .; \
|
|
else \
|
|
echo "SKIP: eslint not installed"; \
|
|
fi \
|
|
fi
|
|
|
|
.PHONY: test
|
|
test: ## Run tests (Python: pytest; JS: npm test)
|
|
@if [ -d tests ] || [ -f pytest.ini ] || [ -f pyproject.toml ]; then \
|
|
if command -v pytest >/dev/null 2>&1; then \
|
|
echo ">>> pytest"; pytest; \
|
|
else \
|
|
echo "SKIP: pytest not installed"; \
|
|
fi \
|
|
else \
|
|
echo "SKIP: no Python tests detected"; \
|
|
fi
|
|
@if [ -f package.json ]; then \
|
|
if grep -q '"test"' package.json 2>/dev/null; then \
|
|
echo ">>> npm test"; npm test; \
|
|
else \
|
|
echo "SKIP: no 'test' script in package.json"; \
|
|
fi \
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build
|
|
# ---------------------------------------------------------------------------
|
|
|
|
.PHONY: build
|
|
build: ## Build the project (JS: npm run build; Python: pip install -e .)
|
|
@if [ -f package.json ] && grep -q '"build"' package.json 2>/dev/null; then \
|
|
echo ">>> npm run build"; npm run build; \
|
|
elif [ -f setup.py ] || [ -f pyproject.toml ]; then \
|
|
echo ">>> pip install -e ."; pip install -e .; \
|
|
else \
|
|
echo "SKIP: no build step detected"; \
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Docker
|
|
# ---------------------------------------------------------------------------
|
|
|
|
.PHONY: docker-build
|
|
docker-build: ## Build Docker image
|
|
@if [ "$(ENABLE_DOCKER)" != "true" ]; then \
|
|
echo "SKIP: ENABLE_DOCKER is not true"; exit 0; \
|
|
fi
|
|
@if [ -f Dockerfile ]; then \
|
|
echo ">>> docker build -t $(_IMAGE):local ."; \
|
|
docker build -t "$(_IMAGE):local" .; \
|
|
elif [ -f docker-compose.yml ]; then \
|
|
echo ">>> docker compose build"; \
|
|
docker compose build; \
|
|
else \
|
|
echo "SKIP: no Dockerfile or docker-compose.yml found"; \
|
|
fi
|
|
|
|
.PHONY: docker-push
|
|
docker-push: ## Push Docker image (requires DOCKER_PUSH=true)
|
|
@if [ "$(DOCKER_PUSH)" != "true" ]; then \
|
|
echo "ABORT: DOCKER_PUSH is not true in .ci/config.env"; \
|
|
echo "Set DOCKER_PUSH=true to enable pushing."; \
|
|
exit 1; \
|
|
fi
|
|
@echo ">>> docker push $(_IMAGE):local"
|
|
docker push "$(_IMAGE):local"
|