392 lines
11 KiB
Makefile
392 lines
11 KiB
Makefile
# Kandev Root Makefile
|
|
# Orchestrates both backend (Go) and web app (Next.js)
|
|
|
|
# Directories
|
|
BACKEND_DIR := apps/backend
|
|
WEB_DIR := apps/web
|
|
APPS_DIR := apps
|
|
|
|
# Tools
|
|
PNPM := pnpm
|
|
MAKE := make
|
|
|
|
# Cross-platform commands
|
|
ifeq ($(OS),Windows_NT)
|
|
RM = cmd /c del /s /q
|
|
RMDIR = cmd /c rmdir /s /q
|
|
else
|
|
RM = rm -f
|
|
RMDIR = rm -rf
|
|
endif
|
|
|
|
# Colors for terminal output
|
|
RESET := \033[0m
|
|
BOLD := \033[1m
|
|
DIM := \033[2m
|
|
GREEN := \033[32m
|
|
BLUE := \033[34m
|
|
CYAN := \033[36m
|
|
YELLOW := \033[33m
|
|
MAGENTA := \033[35m
|
|
|
|
VERBOSE ?= 0
|
|
|
|
# Phase headers
|
|
define phase
|
|
@printf "\n$(BOLD)$(BLUE)━━━ $(1) ━━━$(RESET)\n\n"
|
|
endef
|
|
|
|
# Success message
|
|
define success
|
|
@printf "$(GREEN)✓$(RESET) $(1)\n"
|
|
endef
|
|
|
|
# Default target
|
|
.DEFAULT_GOAL := help
|
|
|
|
#
|
|
# Help
|
|
#
|
|
|
|
.PHONY: help
|
|
help:
|
|
@echo "Kandev - AI Agent Kanban Board"
|
|
@echo ""
|
|
@echo "Development Commands:"
|
|
@echo " dev Run backend + web via CLI (auto ports)"
|
|
@echo " dev-prod-db Run dev mode against the production db at ~/.kandev"
|
|
@echo " dev-backend Run backend in development mode (port 38429)"
|
|
@echo " dev-web Run web app in development mode (port 37429)"
|
|
@echo " dev Note: Uses apps/cli launcher (auto ports)"
|
|
@echo ""
|
|
@echo "Production Commands:"
|
|
@echo " start Install deps, build, and start backend + web in production mode"
|
|
@echo " start-verbose Start in production mode with info logs from backend + web"
|
|
@echo " start VERBOSE=1 Same as start-verbose"
|
|
@echo ""
|
|
@echo "Build Commands:"
|
|
@echo " build Build backend and web app"
|
|
@echo " build-backend Build backend binary"
|
|
@echo " build-web Build web app for production"
|
|
@echo ""
|
|
@echo "Installation:"
|
|
@echo " install Install all dependencies (backend + web)"
|
|
@echo " install-backend Install backend dependencies"
|
|
@echo " install-web Install web dependencies (uses pnpm workspace)"
|
|
@echo ""
|
|
@echo "Testing:"
|
|
@echo " test Run all tests (backend + web + cli)"
|
|
@echo " test-windows Run Windows-clean subset (curated backend + web + cli)"
|
|
@echo " test-backend Run backend tests"
|
|
@echo " test-web Run web app tests"
|
|
@echo " test-cli Run CLI tests"
|
|
@echo " test-e2e Run E2E tests (headless, parallel)"
|
|
@echo " test-e2e-headed Run E2E tests with visible browser"
|
|
@echo " test-e2e-ui Run E2E tests in Playwright UI mode"
|
|
@echo " test-e2e-ci Run E2E tests in Docker with CI-like Linux + resource limits"
|
|
@echo " test-e2e-report Open Playwright HTML report"
|
|
@echo ""
|
|
@echo "Code Quality:"
|
|
@echo " lint Run linters for both components"
|
|
@echo " lint-backend Run Go linters"
|
|
@echo " lint-web Run ESLint"
|
|
@echo " lint-format Check formatting with Prettier (web/cli/packages)"
|
|
@echo " fmt Format all code"
|
|
@echo " fmt-backend Format Go code"
|
|
@echo " fmt-web Format web/cli/packages with Prettier, then ESLint --fix (web)"
|
|
@echo ""
|
|
@echo "Cleanup:"
|
|
@echo " clean Remove all build artifacts"
|
|
@echo " clean-backend Remove backend build artifacts"
|
|
@echo " clean-web Remove web build artifacts"
|
|
@echo " clean-db Remove local SQLite database"
|
|
|
|
#
|
|
# Development
|
|
#
|
|
|
|
# Build the linux/amd64 agentctl on every host except Linux/x86_64 (where the
|
|
# host build IS already linux/amd64). Computed up here, OS-conditionally, so
|
|
# the recipe doesn't shell out to `uname` — that fails on Windows under cmd
|
|
# and produces spurious "CreateProcess(NULL, uname -s, ...) failed" warnings
|
|
# on every Make invocation.
|
|
ifeq ($(OS),Windows_NT)
|
|
HOST_IS_LINUX_AMD64 := 0
|
|
else
|
|
ifeq ($(shell uname -s)/$(shell uname -m),Linux/x86_64)
|
|
HOST_IS_LINUX_AMD64 := 1
|
|
else
|
|
HOST_IS_LINUX_AMD64 := 0
|
|
endif
|
|
endif
|
|
|
|
.PHONY: dev
|
|
dev:
|
|
ifneq ($(HOST_IS_LINUX_AMD64),1)
|
|
@echo "Building Linux agentctl for remote executors..."
|
|
@$(MAKE) -C $(BACKEND_DIR) build-agentctl-linux
|
|
endif
|
|
ifeq ($(OS),Windows_NT)
|
|
@echo "Building winjob (Ctrl-C-safe wrapper for Windows)..."
|
|
@$(MAKE) -C $(BACKEND_DIR) build-winjob
|
|
endif
|
|
@echo "Launching via CLI (auto ports)..."
|
|
@cd $(APPS_DIR) && $(PNPM) -C cli dev -- dev
|
|
|
|
.PHONY: dev-prod-db
|
|
dev-prod-db: export KANDEV_DATABASE_PATH := $(HOME)/.kandev/data/kandev.db
|
|
dev-prod-db:
|
|
@echo "⚠ dev mode against PRODUCTION db at $(KANDEV_DATABASE_PATH)"
|
|
@echo " back it up first; dev binary may run unmigrated schema changes"
|
|
@$(MAKE) dev
|
|
|
|
.PHONY: dev-backend
|
|
dev-backend:
|
|
@echo "Starting backend on http://localhost:38429"
|
|
@trap 'stty sane 2>/dev/null || true' EXIT INT TERM; \
|
|
$(MAKE) -C $(BACKEND_DIR) run; \
|
|
stty sane 2>/dev/null || true
|
|
|
|
.PHONY: dev-web
|
|
dev-web:
|
|
@echo "Starting web app on http://localhost:37429"
|
|
@cd $(APPS_DIR) && PORT=37429 $(PNPM) --filter @kandev/web dev
|
|
|
|
#
|
|
# Build
|
|
#
|
|
|
|
.PHONY: build
|
|
build: build-backend build-web
|
|
@printf "\n$(GREEN)$(BOLD)✓ Build complete!$(RESET)\n"
|
|
|
|
#
|
|
# Production Start
|
|
#
|
|
|
|
.PHONY: start
|
|
start:
|
|
$(call phase,Installing Dependencies)
|
|
@$(MAKE) -s install-backend
|
|
@$(MAKE) -s install-web
|
|
$(call success,Dependencies installed)
|
|
$(call phase,Building)
|
|
@$(MAKE) -s build-backend-quiet
|
|
@$(MAKE) -s build-web-quiet
|
|
$(call success,Build complete)
|
|
$(call phase,Starting Server)
|
|
@cd $(APPS_DIR) && $(PNPM) -C cli dev -- start $(if $(filter 1 true yes,$(VERBOSE)),--verbose,) $(if $(filter 1 true yes,$(DEBUG)),--debug,)
|
|
|
|
.PHONY: start-verbose
|
|
start-verbose:
|
|
@$(MAKE) start VERBOSE=1
|
|
|
|
.PHONY: start-debug
|
|
start-debug:
|
|
@$(MAKE) start DEBUG=1
|
|
|
|
.PHONY: build-backend
|
|
build-backend:
|
|
@printf "$(CYAN)Building backend...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) build
|
|
|
|
.PHONY: build-backend-linux-helpers
|
|
build-backend-linux-helpers:
|
|
@printf "$(CYAN)Building linux/amd64 helper binaries (agentctl + mock-agent) for Docker E2E...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) build-agentctl-linux build-mock-agent-linux
|
|
|
|
.PHONY: acpdbg
|
|
acpdbg:
|
|
@$(MAKE) -s -C $(BACKEND_DIR) acpdbg ARGS="$(ARGS)"
|
|
|
|
.PHONY: build-backend-quiet
|
|
build-backend-quiet:
|
|
@printf " $(DIM)Backend$(RESET)\n"
|
|
@$(MAKE) -s -C $(BACKEND_DIR) build >/dev/null 2>&1
|
|
|
|
.PHONY: build-web
|
|
build-web:
|
|
@printf "$(CYAN)Building web app...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web build
|
|
|
|
.PHONY: build-web-quiet
|
|
build-web-quiet:
|
|
@printf " $(DIM)Web app$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web build 2>&1 | grep -v "Warning:" | grep -v "parseLineType" | grep -v "^$$" || true
|
|
|
|
#
|
|
# Installation
|
|
#
|
|
|
|
.PHONY: install
|
|
install: install-backend install-web
|
|
@printf "\n$(GREEN)$(BOLD)✓ All dependencies installed!$(RESET)\n"
|
|
|
|
.PHONY: install-backend
|
|
install-backend:
|
|
@printf "$(CYAN)Installing backend dependencies...$(RESET)\n"
|
|
@$(MAKE) -s -C $(BACKEND_DIR) deps
|
|
|
|
.PHONY: install-web
|
|
install-web:
|
|
@printf "$(CYAN)Installing web dependencies...$(RESET)\n"
|
|
@(cd $(APPS_DIR) && $(PNPM) install --silent 2>/dev/null) || (cd $(APPS_DIR) && $(PNPM) install)
|
|
@printf "$(CYAN)Installing Playwright browsers...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web exec playwright install chromium
|
|
|
|
#
|
|
# Testing
|
|
#
|
|
|
|
.PHONY: test
|
|
test: test-backend test-web test-cli
|
|
@printf "\n$(GREEN)$(BOLD)✓ All tests complete!$(RESET)\n"
|
|
|
|
# Curated Windows-clean test run. Mirrors the test-windows job in
|
|
# .github/workflows/backend-tests.yml: the backend portion skips ~24 tests
|
|
# with Unix-only fixtures (sleep/cat/echo in test inputs, POSIX symlinks,
|
|
# delete-while-open). Web and CLI use vitest, which is cross-platform.
|
|
# Shrink the backend skip list as fixtures get cleaned up.
|
|
#
|
|
# Deliberately uses plain `echo` and inlines pnpm invocations (rather than
|
|
# depending on test-backend/test-web/test-cli) so it does not pull in the
|
|
# `@printf` and `$(shell uname ...)` calls used by other targets — those
|
|
# fail on cmd.exe (no printf.exe, no uname.exe) and would break the run on
|
|
# Windows even though they are cosmetic on Unix.
|
|
.PHONY: test-windows
|
|
test-windows:
|
|
@echo "[backend] Running Windows-clean subset..."
|
|
@$(MAKE) -C $(BACKEND_DIR) test-windows
|
|
@echo "[web] Running tests..."
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web test
|
|
@echo "[cli] Running tests..."
|
|
@cd $(APPS_DIR) && $(PNPM) --filter kandev test
|
|
@echo "Windows-clean test subset complete."
|
|
|
|
.PHONY: test-sprites-e2e
|
|
test-sprites-e2e:
|
|
@$(MAKE) -C $(BACKEND_DIR) test-sprites-e2e
|
|
|
|
.PHONY: test-backend
|
|
test-backend:
|
|
@printf "$(CYAN)Running backend tests...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) test
|
|
|
|
.PHONY: test-web
|
|
test-web:
|
|
@printf "$(CYAN)Running web app tests...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web test
|
|
|
|
.PHONY: test-cli
|
|
test-cli:
|
|
@printf "$(CYAN)Running CLI tests...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter kandev test
|
|
|
|
.PHONY: test-e2e
|
|
test-e2e: build-backend build-web
|
|
@printf "$(CYAN)Running E2E tests (headless, parallel)...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web e2e
|
|
|
|
.PHONY: test-e2e-headed
|
|
test-e2e-headed: build-backend build-web
|
|
@printf "$(CYAN)Running E2E tests (headed)...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web e2e:headed
|
|
|
|
.PHONY: test-e2e-ui
|
|
test-e2e-ui: build-backend build-web
|
|
@printf "$(CYAN)Opening Playwright UI mode...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web e2e:ui
|
|
|
|
.PHONY: test-e2e-report
|
|
test-e2e-report:
|
|
@cd $(WEB_DIR) && npx playwright show-report e2e/playwright-report
|
|
|
|
# Run E2E tests inside Docker to simulate CI conditions (Linux + resource limits).
|
|
# Configurable via env vars; defaults match GitHub Actions ubuntu-latest runners.
|
|
E2E_CI_CPUS ?= 4
|
|
E2E_CI_MEMORY ?= 16g
|
|
E2E_CI_SHM_SIZE ?= 1g
|
|
E2E_CI_IMAGE ?= kandev-e2e
|
|
|
|
.PHONY: test-e2e-ci
|
|
test-e2e-ci:
|
|
@printf "$(CYAN)Building E2E Docker image...$(RESET)\n"
|
|
@docker build -f e2e.Dockerfile -t $(E2E_CI_IMAGE) .
|
|
@printf "$(CYAN)Running E2E tests in Docker (cpus=$(E2E_CI_CPUS), memory=$(E2E_CI_MEMORY))...$(RESET)\n"
|
|
@docker run --rm \
|
|
--cpus=$(E2E_CI_CPUS) \
|
|
--memory=$(E2E_CI_MEMORY) \
|
|
--shm-size=$(E2E_CI_SHM_SIZE) \
|
|
$(E2E_CI_IMAGE) $(E2E_ARGS)
|
|
|
|
#
|
|
# Code Quality
|
|
#
|
|
|
|
.PHONY: lint
|
|
lint: lint-backend lint-web
|
|
@printf "\n$(GREEN)$(BOLD)✓ Linting complete!$(RESET)\n"
|
|
|
|
.PHONY: lint-backend
|
|
lint-backend:
|
|
@printf "$(CYAN)Linting backend...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) lint
|
|
|
|
.PHONY: lint-web
|
|
lint-web:
|
|
@printf "$(CYAN)Linting web app...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web lint
|
|
|
|
.PHONY: lint-format
|
|
lint-format:
|
|
@printf "$(CYAN)Checking formatting...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) run format:check
|
|
|
|
.PHONY: fmt
|
|
fmt: fmt-backend fmt-web
|
|
@printf "\n$(GREEN)$(BOLD)✓ Code formatting complete!$(RESET)\n"
|
|
|
|
.PHONY: fmt-backend
|
|
fmt-backend:
|
|
@printf "$(CYAN)Formatting backend code...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) fmt
|
|
|
|
.PHONY: fmt-web
|
|
fmt-web:
|
|
@printf "$(CYAN)Formatting web code...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) run format
|
|
|
|
.PHONY: typecheck-web
|
|
typecheck-web:
|
|
@printf "$(CYAN)Type-checking web app...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) --filter @kandev/web exec tsc -p tsconfig.json --noEmit
|
|
|
|
.PHONY: typecheck
|
|
typecheck:
|
|
@printf "$(CYAN)Type-checking all apps...$(RESET)\n"
|
|
@cd $(APPS_DIR) && $(PNPM) -r exec tsc -p tsconfig.json --noEmit
|
|
|
|
#
|
|
# Cleanup
|
|
#
|
|
|
|
.PHONY: clean
|
|
clean: clean-backend clean-web
|
|
@printf "\n$(GREEN)$(BOLD)✓ Cleanup complete!$(RESET)\n"
|
|
|
|
.PHONY: clean-backend
|
|
clean-backend:
|
|
@printf "$(CYAN)Cleaning backend artifacts...$(RESET)\n"
|
|
@$(MAKE) -C $(BACKEND_DIR) clean
|
|
|
|
.PHONY: clean-web
|
|
clean-web:
|
|
@printf "$(CYAN)Cleaning web artifacts...$(RESET)\n"
|
|
@$(RMDIR) $(WEB_DIR)/.next $(APPS_DIR)/node_modules
|
|
@$(RMDIR) $(APPS_DIR)/packages/*/node_modules
|
|
|
|
.PHONY: clean-db
|
|
clean-db:
|
|
@printf "$(CYAN)Removing dev database (.kandev-dev/)...$(RESET)\n"
|
|
@$(RMDIR) .kandev-dev
|