.PHONY: run frontend check ruff database lint api start-all stop-all status clean-cache worker worker-start worker-stop worker-restart .PHONY: docker-buildx-prepare docker-buildx-clean docker-buildx-reset .PHONY: docker-push docker-push-latest docker-release tag export-docs # Get version from pyproject.toml VERSION := $(shell grep -m1 version pyproject.toml | cut -d'"' -f2) # Image names for both registries DOCKERHUB_IMAGE := lfnovo/open_notebook GHCR_IMAGE := ghcr.io/lfnovo/open-notebook # Build platforms PLATFORMS := linux/amd64,linux/arm64 database: docker compose up -d surrealdb run: @echo "โš ๏ธ Warning: Starting frontend only. For full functionality, use 'make start-all'" cd frontend && npm run dev frontend: cd frontend && npm run dev lint: uv run python -m mypy . ruff: ruff check . --fix # === Docker Build Setup === docker-buildx-prepare: @docker buildx inspect multi-platform-builder >/dev/null 2>&1 || \ docker buildx create --use --name multi-platform-builder --driver docker-container @docker buildx use multi-platform-builder docker-buildx-clean: @echo "๐Ÿงน Cleaning up buildx builders..." @docker buildx rm multi-platform-builder 2>/dev/null || true @docker ps -a | grep buildx_buildkit | awk '{print $$1}' | xargs -r docker rm -f 2>/dev/null || true @echo "โœ… Buildx cleanup complete!" docker-buildx-reset: docker-buildx-clean docker-buildx-prepare @echo "โœ… Buildx reset complete!" # === Docker Build Targets === # Build and push version tags ONLY (no latest) for both regular and single images docker-push: docker-buildx-prepare @echo "๐Ÿ“ค Building and pushing version $(VERSION) to both registries..." @echo "๐Ÿ”จ Building regular image..." docker buildx build --pull \ --platform $(PLATFORMS) \ --progress=plain \ -t $(DOCKERHUB_IMAGE):$(VERSION) \ -t $(GHCR_IMAGE):$(VERSION) \ --push \ . @echo "๐Ÿ”จ Building single-container image..." docker buildx build --pull \ --platform $(PLATFORMS) \ --progress=plain \ -f Dockerfile.single \ -t $(DOCKERHUB_IMAGE):$(VERSION)-single \ -t $(GHCR_IMAGE):$(VERSION)-single \ --push \ . @echo "โœ… Pushed version $(VERSION) to both registries (latest NOT updated)" @echo " ๐Ÿ“ฆ Docker Hub:" @echo " - $(DOCKERHUB_IMAGE):$(VERSION)" @echo " - $(DOCKERHUB_IMAGE):$(VERSION)-single" @echo " ๐Ÿ“ฆ GHCR:" @echo " - $(GHCR_IMAGE):$(VERSION)" @echo " - $(GHCR_IMAGE):$(VERSION)-single" # Update v1-latest tags to current version (both regular and single images) docker-push-latest: docker-buildx-prepare @echo "๐Ÿ“ค Updating v1-latest tags to version $(VERSION)..." @echo "๐Ÿ”จ Building regular image with latest tag..." docker buildx build --pull \ --platform $(PLATFORMS) \ --progress=plain \ -t $(DOCKERHUB_IMAGE):$(VERSION) \ -t $(DOCKERHUB_IMAGE):v1-latest \ -t $(GHCR_IMAGE):$(VERSION) \ -t $(GHCR_IMAGE):v1-latest \ --push \ . @echo "๐Ÿ”จ Building single-container image with latest tag..." docker buildx build --pull \ --platform $(PLATFORMS) \ --progress=plain \ -f Dockerfile.single \ -t $(DOCKERHUB_IMAGE):$(VERSION)-single \ -t $(DOCKERHUB_IMAGE):v1-latest-single \ -t $(GHCR_IMAGE):$(VERSION)-single \ -t $(GHCR_IMAGE):v1-latest-single \ --push \ . @echo "โœ… Updated v1-latest to version $(VERSION)" @echo " ๐Ÿ“ฆ Docker Hub:" @echo " - $(DOCKERHUB_IMAGE):$(VERSION) โ†’ v1-latest" @echo " - $(DOCKERHUB_IMAGE):$(VERSION)-single โ†’ v1-latest-single" @echo " ๐Ÿ“ฆ GHCR:" @echo " - $(GHCR_IMAGE):$(VERSION) โ†’ v1-latest" @echo " - $(GHCR_IMAGE):$(VERSION)-single โ†’ v1-latest-single" # Full release: push version AND update latest tags docker-release: docker-push-latest @echo "โœ… Full release complete for version $(VERSION)" tag: @version=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \ echo "Creating tag v$$version"; \ git tag "v$$version"; \ git push origin "v$$version" dev: docker compose -f docker-compose.dev.yml up --build full: docker compose -f docker-compose.full.yml up --build api: uv run run_api.py # === Worker Management === .PHONY: worker worker-start worker-stop worker-restart worker: worker-start worker-start: @echo "Starting surreal-commands worker..." uv run --env-file .env surreal-commands-worker --import-modules commands worker-stop: @echo "Stopping surreal-commands worker..." pkill -f "surreal-commands-worker" || true worker-restart: worker-stop @sleep 2 @$(MAKE) worker-start # === Service Management === start-all: @echo "๐Ÿš€ Starting Open Notebook (Database + API + Worker + Frontend)..." @echo "๐Ÿ“Š Starting SurrealDB..." @docker compose up -d surrealdb @sleep 3 @echo "๐Ÿ”ง Starting API backend..." @uv run run_api.py & @sleep 3 @echo "โš™๏ธ Starting background worker..." @uv run --env-file .env surreal-commands-worker --import-modules commands & @sleep 2 @echo "๐ŸŒ Starting Next.js frontend..." @echo "โœ… All services started!" @echo "๐Ÿ“ฑ Frontend: http://localhost:3000" @echo "๐Ÿ”— API: http://localhost:5055" @echo "๐Ÿ“š API Docs: http://localhost:5055/docs" cd frontend && npm run dev stop-all: @echo "๐Ÿ›‘ Stopping all Open Notebook services..." @pkill -f "next dev" || true @pkill -f "surreal-commands-worker" || true @pkill -f "run_api.py" || true @pkill -f "uvicorn api.main:app" || true @docker compose down @echo "โœ… All services stopped!" status: @echo "๐Ÿ“Š Open Notebook Service Status:" @echo "Database (SurrealDB):" @docker compose ps surrealdb 2>/dev/null || echo " โŒ Not running" @echo "API Backend:" @pgrep -f "run_api.py\|uvicorn api.main:app" >/dev/null && echo " โœ… Running" || echo " โŒ Not running" @echo "Background Worker:" @pgrep -f "surreal-commands-worker" >/dev/null && echo " โœ… Running" || echo " โŒ Not running" @echo "Next.js Frontend:" @pgrep -f "next dev" >/dev/null && echo " โœ… Running" || echo " โŒ Not running" # === Documentation Export === export-docs: @echo "๐Ÿ“š Exporting documentation..." @uv run python scripts/export_docs.py @echo "โœ… Documentation export complete!" # === Cleanup === clean-cache: @echo "๐Ÿงน Cleaning cache directories..." @find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true @find . -name ".mypy_cache" -type d -exec rm -rf {} + 2>/dev/null || true @find . -name ".ruff_cache" -type d -exec rm -rf {} + 2>/dev/null || true @find . -name ".pytest_cache" -type d -exec rm -rf {} + 2>/dev/null || true @find . -name "*.pyc" -type f -delete 2>/dev/null || true @find . -name "*.pyo" -type f -delete 2>/dev/null || true @find . -name "*.pyd" -type f -delete 2>/dev/null || true @echo "โœ… Cache directories cleaned!"