Podman relies on systemd timers to schedule automatic healthchecks. On non-systemd systems (e.g., Void Linux with runit), healthchecks never fire, which causes podman-compose to hang forever waiting for service_healthy conditions that never resolve. Add two Make macros to handle this transparently: - compose_up: runs podman compose up -d normally on systemd, but with a 15-second timeout on non-systemd to create containers without hanging. Supports passing compose flags via $(call compose_up,args). - ensure_healthy: on non-systemd systems, waits for the database to accept connections, manually triggers its healthcheck, starts the app container, waits for the app health endpoint, and triggers its healthcheck. On systemd systems, the runtime check is skipped entirely (zero overhead). Both macros use a runtime shell check for /run/systemd/system, so the same Makefile works identically on all systems without parse-time conditionals. Applied to all compose-up targets: up, rebuild, rebuild-force, rebuild-force-db, rebuild-app, rebuild-app-force, test-integration, and test-env-up. Refs: https://github.com/containers/podman/pull/27033
207 lines
7.6 KiB
Makefile
207 lines
7.6 KiB
Makefile
.PHONY: help test test-integration test-all rebuild rebuild-force rebuild-app rebuild-app-force rebuild-force-db clean restart up down logs ps test-env-up test-env-down verify-guidelines verify-quick
|
|
|
|
# Include .env file for environment variables (single source of truth)
|
|
# Ignore if .env doesn't exist yet
|
|
ifneq (,$(wildcard ./.env))
|
|
include .env
|
|
export
|
|
endif
|
|
|
|
# On non-systemd systems (e.g., Void Linux with runit), podman healthchecks are
|
|
# never triggered automatically because podman relies on systemd timers.
|
|
# Additionally, podman-compose up -d blocks forever waiting for service_healthy
|
|
# conditions that never resolve. This macro:
|
|
# 1. Waits for the DB to accept connections, triggers its healthcheck
|
|
# 2. Starts the app container, waits for it, triggers its healthcheck
|
|
# On systemd systems, the runtime check skips everything.
|
|
# See: https://github.com/containers/podman/pull/27033
|
|
define ensure_healthy
|
|
@if [ ! -d /run/systemd/system ]; then \
|
|
echo "Non-systemd: waiting for database..."; \
|
|
i=0; \
|
|
until podman exec bookhoard_db pg_isready -U postgres >/dev/null 2>&1; do \
|
|
i=$$((i+1)); if [ $$i -gt 30 ]; then echo " Database failed to start"; exit 1; fi; \
|
|
sleep 2; \
|
|
done; \
|
|
podman healthcheck run bookhoard_db >/dev/null 2>&1 || true; \
|
|
podman start bookhoard 2>/dev/null || true; \
|
|
echo "Non-systemd: waiting for application..."; \
|
|
i=0; \
|
|
until podman exec bookhoard curl -sf http://localhost:8765/health >/dev/null 2>&1; do \
|
|
i=$$((i+1)); if [ $$i -gt 30 ]; then echo " Application failed to start"; exit 1; fi; \
|
|
sleep 2; \
|
|
done; \
|
|
podman healthcheck run bookhoard >/dev/null 2>&1 || true; \
|
|
echo " Services healthy"; \
|
|
fi
|
|
endef
|
|
|
|
# podman-compose up -d blocks forever on non-systemd waiting for service_healthy.
|
|
# This macro runs compose with a timeout on non-systemd to let it create containers
|
|
# without hanging. Pass compose flags via the COMPOSE_UP_ARGS variable.
|
|
# Usage: $(call compose_up,--build --force-recreate)
|
|
# On systemd systems, the timeout is skipped.
|
|
define compose_up
|
|
@if [ -d /run/systemd/system ]; then \
|
|
podman compose up $1 -d; \
|
|
else \
|
|
timeout 15 podman compose up $1 -d || true; \
|
|
fi
|
|
endef
|
|
|
|
# Default target
|
|
help:
|
|
@echo "Available targets:"
|
|
@echo ""
|
|
@echo "Development:"
|
|
@echo " make up - Start containers (if already built)"
|
|
@echo " make rebuild - Rebuild all containers (database preserved)"
|
|
@echo " make rebuild-force - Rebuild all containers, no cache (database preserved)"
|
|
@echo " make rebuild-app - Rebuild app container only (fast, database preserved)"
|
|
@echo " make rebuild-app-force - Rebuild app container only, no cache (database preserved)"
|
|
@echo " make rebuild-force-db - Rebuild all containers, no cache (DELETES database)"
|
|
@echo " make restart - Restart app container (preserves db)"
|
|
@echo " make down - Stop all containers (preserves volumes)"
|
|
@echo " make clean - Stop and remove all containers and volumes"
|
|
@echo ""
|
|
@echo "Status & Logs:"
|
|
@echo " make ps - Show container status"
|
|
@echo " make logs - Show container logs (follow mode)"
|
|
@echo ""
|
|
@echo "Testing:"
|
|
@echo " make test - Run unit tests (from host, fast)"
|
|
@echo " make test-integration - Run integration tests (in containers, matches prod)"
|
|
@echo " make test-all - Run all tests (unit + integration)"
|
|
@echo " make test-env-up - Start containers with test mode enabled"
|
|
@echo " make test-env-down - Stop test environment"
|
|
@echo ""
|
|
@echo "Verification:"
|
|
@echo " make verify-guidelines - Run comprehensive guidelines check"
|
|
@echo " make verify-quick - Run quick guidelines check"
|
|
|
|
# Run unit tests locally (fast, no containers)
|
|
test:
|
|
go test ./internal/... -v -short
|
|
|
|
# Run integration tests in containers (matches production environment)
|
|
test-integration:
|
|
@echo "Building test containers..."
|
|
podman compose --profile tests build
|
|
@echo "Starting application containers..."
|
|
$(call compose_up,db app)
|
|
$(ensure_healthy)
|
|
@echo "Waiting for services to be healthy..."
|
|
@until podman exec bookhoard_db pg_isready -U postgres > /dev/null 2>&1; do \
|
|
echo " Database not ready yet..."; \
|
|
sleep 2; \
|
|
done; \
|
|
echo " ✓ Database is ready"
|
|
@until podman exec bookhoard curl -sf http://localhost:8765/health > /dev/null 2>&1; do \
|
|
echo " Application not ready yet..."; \
|
|
sleep 2; \
|
|
done; \
|
|
echo " ✓ Application is ready"
|
|
@echo ""
|
|
@echo "Running integration tests in container..."
|
|
podman compose --profile tests run --rm tests
|
|
@echo ""
|
|
@echo "✅ Integration tests completed!"
|
|
@echo "📝 Containers are still running. Use 'make logs' to view logs or 'make clean' to stop."
|
|
|
|
# Run all tests
|
|
test-all: test test-integration
|
|
|
|
# Rebuild app container only (preserve DB, with cache)
|
|
rebuild-app:
|
|
@echo "Rebuilding app container (database stays running)..."
|
|
$(call compose_up,--build --force-recreate app)
|
|
$(ensure_healthy)
|
|
@echo "✓ App container rebuilt and restarted"
|
|
|
|
# Rebuild app container only (preserve DB, no cache)
|
|
rebuild-app-force:
|
|
@echo "Force rebuilding app container (database stays running, no cache)..."
|
|
podman compose build --no-cache app
|
|
$(call compose_up,--force-recreate app)
|
|
$(ensure_healthy)
|
|
@echo "✓ App container rebuilt and restarted"
|
|
|
|
# Rebuild all containers (preserve DB, with cache)
|
|
rebuild:
|
|
@echo "Rebuilding all containers (database preserved)..."
|
|
$(call compose_up,--build --force-recreate)
|
|
$(ensure_healthy)
|
|
@echo "✓ All containers rebuilt and restarted"
|
|
|
|
# Rebuild all containers (preserve DB, no cache)
|
|
rebuild-force:
|
|
@echo "Force rebuilding all containers (database preserved, no cache)..."
|
|
podman compose build --no-cache
|
|
$(call compose_up,--force-recreate)
|
|
$(ensure_healthy)
|
|
@echo "✓ All containers rebuilt and restarted"
|
|
|
|
# Rebuild all containers (remove DB, no cache)
|
|
rebuild-force-db:
|
|
@echo "Force rebuilding all containers (database will be DELETED, no cache)..."
|
|
podman compose down -v
|
|
podman compose build --no-cache
|
|
$(call compose_up,--force-recreate)
|
|
$(ensure_healthy)
|
|
@echo "✓ All containers rebuilt and restarted"
|
|
|
|
# Stop and remove containers
|
|
clean:
|
|
podman compose down -v
|
|
|
|
# Quick start (if already built)
|
|
up:
|
|
$(compose_up)
|
|
$(ensure_healthy)
|
|
|
|
# Stop all containers (alias for clean)
|
|
down:
|
|
podman compose down
|
|
|
|
# Restart app container (preserves database)
|
|
restart:
|
|
@echo "Restarting app container (database stays running)..."
|
|
podman compose restart app
|
|
@echo "✓ App container restarted"
|
|
|
|
# Show container status
|
|
ps:
|
|
podman compose ps
|
|
|
|
# Show container logs
|
|
logs:
|
|
podman compose logs -f
|
|
|
|
# Start containers with test mode enabled for manual testing
|
|
test-env-up:
|
|
@echo "Starting containers with test mode enabled..."
|
|
@if [ -d /run/systemd/system ]; then \
|
|
TEST_MODE=true RATE_LIMIT_ENABLED=false REQUESTS_PER_MINUTE=1000 podman compose up --build --force-recreate -d; \
|
|
else \
|
|
TEST_MODE=true RATE_LIMIT_ENABLED=false REQUESTS_PER_MINUTE=1000 timeout 15 podman compose up --build --force-recreate -d || true; \
|
|
fi
|
|
$(ensure_healthy)
|
|
@echo "Waiting for services to be ready..."
|
|
@until podman exec bookhoard_db pg_isready -U postgres > /dev/null 2>&1; do sleep 1; done
|
|
@until podman exec bookhoard curl -sf http://localhost:8765/health > /dev/null 2>&1; do sleep 1; done
|
|
@echo "✓ Test environment is ready!"
|
|
@echo "Application available at http://localhost:8765"
|
|
|
|
# Stop test environment
|
|
test-env-down:
|
|
podman compose down -v
|
|
|
|
# Verify project guidelines compliance
|
|
verify-guidelines:
|
|
@echo "Running comprehensive project guidelines verification..."
|
|
@./scripts/verify-guidelines.sh
|
|
|
|
verify-quick:
|
|
@echo "Running quick project guidelines verification..."
|
|
@./scripts/verify-quick.sh
|