mirror of
https://github.com/reconurge/flowsint.git
synced 2026-11-08 14:35:41 -06:00
make lint was Python-only (PY_SRC never included flowsint-app) — frontend prettier/eslint lived solely in flowsint-app's own yarn scripts, disconnected from the repo's single lint entry point. Both are 0-errors clean today (eslint's ~130 findings are all warnings), same bar the Python side is already held to, so added as blocking rather than a separate opt-in step. CONTRIBUTING.md updated to match.
274 lines
9.1 KiB
Makefile
274 lines
9.1 KiB
Makefile
PROJECT_ROOT := $(shell pwd)
|
|
|
|
COMPOSE_DEV := docker compose -f docker-compose.dev.yml
|
|
COMPOSE_PROD := docker compose -f docker-compose.prod.yml
|
|
|
|
.PHONY: \
|
|
dev prod \
|
|
build-dev \
|
|
up-dev up-prod down \
|
|
infra-dev infra-prod infra-stop-dev infra-stop-prod \
|
|
migrate-dev migrate-prod \
|
|
alembic-upgrade alembic-downgrade alembic-revision \
|
|
api frontend celery \
|
|
test install clean check-env open-browser-dev open-browser-prod \
|
|
logs-dev logs-prod status \
|
|
regenerate-router \
|
|
lint lint-fix typecheck
|
|
|
|
ENV_DIRS := . flowsint-api flowsint-core flowsint-app
|
|
|
|
check-env:
|
|
@echo "Checking .env files..."
|
|
@for dir in $(ENV_DIRS); do \
|
|
env_file="$$dir/.env"; \
|
|
env_example="$(PROJECT_ROOT)/.env.example"; \
|
|
if [ ! -f "$$env_file" ]; then \
|
|
cp "$$env_example" "$$env_file"; \
|
|
echo "Created $$env_file"; \
|
|
fi; \
|
|
done
|
|
|
|
dev:
|
|
@echo "Starting DEV environment..."
|
|
$(MAKE) check-env
|
|
$(MAKE) build-dev
|
|
$(MAKE) up-dev
|
|
$(MAKE) open-browser-dev
|
|
$(COMPOSE_DEV) logs -f
|
|
|
|
build-dev:
|
|
@echo "Building DEV images..."
|
|
$(COMPOSE_DEV) build
|
|
|
|
up-dev:
|
|
$(COMPOSE_DEV) up -d
|
|
|
|
infra-dev:
|
|
@echo "Starting DEV infra (postgres / redis / neo4j)..."
|
|
$(COMPOSE_DEV) up -d postgres redis neo4j
|
|
|
|
infra-stop-dev:
|
|
@echo "Stopping DEV infra..."
|
|
$(COMPOSE_DEV) stop postgres redis neo4j
|
|
|
|
logs-dev:
|
|
$(COMPOSE_DEV) logs -f
|
|
|
|
open-browser-dev:
|
|
@echo "Waiting for frontend on port 5173..."
|
|
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 1; done'
|
|
@open http://localhost:5173 2>/dev/null || \
|
|
xdg-open http://localhost:5173 2>/dev/null || \
|
|
echo "Frontend ready at http://localhost:5173"
|
|
|
|
prod:
|
|
@echo "Starting PROD environment (pre-built images)..."
|
|
$(MAKE) check-env
|
|
$(COMPOSE_PROD) pull
|
|
$(MAKE) up-prod
|
|
@echo ""
|
|
@echo "Production started!"
|
|
@echo " Frontend: http://localhost:5173"
|
|
@echo " API: http://localhost:5173/api (proxied)"
|
|
|
|
up-prod:
|
|
$(COMPOSE_PROD) up -d
|
|
|
|
infra-prod:
|
|
@echo "Starting PROD infra (postgres / redis / neo4j)..."
|
|
$(COMPOSE_PROD) up -d postgres redis neo4j
|
|
|
|
infra-stop-prod:
|
|
@echo "Stopping PROD infra..."
|
|
$(COMPOSE_PROD) stop postgres redis neo4j
|
|
|
|
logs-prod:
|
|
$(COMPOSE_PROD) logs -f
|
|
|
|
open-browser-prod:
|
|
@echo "Waiting for frontend on port 5173..."
|
|
@bash -c 'until curl -s http://localhost:5173 > /dev/null 2>&1; do sleep 2; done'
|
|
@open http://localhost:5173 2>/dev/null || \
|
|
xdg-open http://localhost:5173 2>/dev/null || \
|
|
echo "Frontend ready at http://localhost:5173"
|
|
|
|
migrate-dev:
|
|
@echo "Running DEV migrations..."
|
|
@if ! $(COMPOSE_DEV) ps -q neo4j | grep -q .; then \
|
|
echo "Neo4j not running → starting DEV infra"; \
|
|
$(COMPOSE_DEV) up -d --wait neo4j; \
|
|
fi
|
|
yarn migrate
|
|
|
|
migrate-prod:
|
|
@echo "⚠️ Running PROD migrations"
|
|
@echo "This will ALTER production data."
|
|
@read -p "Type 'prod' to continue: " confirm; \
|
|
if [ "$$confirm" != "prod" ]; then \
|
|
echo "Aborted."; exit 1; \
|
|
fi
|
|
yarn migrate
|
|
|
|
alembic-upgrade:
|
|
@echo "Running Alembic migrations (upgrade head)..."
|
|
cd $(PROJECT_ROOT)/flowsint-api && uv run alembic upgrade head
|
|
|
|
alembic-downgrade:
|
|
@echo "Rolling back last Alembic migration..."
|
|
cd $(PROJECT_ROOT)/flowsint-api && uv run alembic downgrade -1
|
|
|
|
alembic-revision:
|
|
@if [ -z "$(m)" ]; then \
|
|
echo "Usage: make alembic-revision m=\"your migration message\""; exit 1; \
|
|
fi
|
|
@echo "Creating new Alembic migration: $(m)"
|
|
cd $(PROJECT_ROOT)/flowsint-api && uv run alembic revision --autogenerate -m "$(m)"
|
|
|
|
api:
|
|
cd $(PROJECT_ROOT)/flowsint-api && \
|
|
uv run uvicorn app.main:app --host 0.0.0.0 --port 5001 --reload
|
|
|
|
frontend:
|
|
cd $(PROJECT_ROOT)/flowsint-app && yarn dev
|
|
|
|
celery:
|
|
cd $(PROJECT_ROOT)/flowsint-api && \
|
|
uv run celery -A flowsint_core.core.celery \
|
|
worker --loglevel=info --pool=threads --concurrency=10
|
|
|
|
test:
|
|
cd flowsint-types && uv run pytest
|
|
cd flowsint-core && uv run pytest
|
|
cd flowsint-enrichers && uv run pytest
|
|
cd flowsint-api && uv run pytest
|
|
|
|
PY_SRC := flowsint-core/src flowsint-core/tests \
|
|
flowsint-api/app flowsint-api/tests flowsint-api/alembic \
|
|
flowsint-enrichers/src flowsint-enrichers/tests \
|
|
flowsint-types/src flowsint-types/tests
|
|
|
|
# Full-repo, blocking: formatting and lint are 100% clean today, so any
|
|
# regression here is new debt — no reason to let it in. ruff replaces
|
|
# black+isort+flake8 (one tool, one config — see [tool.ruff] in the root
|
|
# pyproject.toml, which every package's ruff invocation inherits by walking
|
|
# up the directory tree to find it). Frontend prettier/eslint are just as
|
|
# clean today (0 errors — eslint's ~130 remaining findings are all
|
|
# warnings, e.g. no-explicit-any, not failures), so they're blocking here
|
|
# too rather than living only in flowsint-app's own yarn scripts.
|
|
lint:
|
|
uv run ruff format --check $(PY_SRC)
|
|
uv run ruff check $(PY_SRC)
|
|
cd flowsint-app && yarn format:check && yarn lint:check
|
|
|
|
lint-fix:
|
|
uv run ruff format $(PY_SRC)
|
|
uv run ruff check --fix $(PY_SRC)
|
|
cd flowsint-app && yarn format && yarn lint
|
|
|
|
# mypy has ~2200 pre-existing errors across the workspace (real, not fixed
|
|
# blindly in one pass — see CI notes). Gating full-repo would be a
|
|
# lie from day one. Ratchet instead: block only on files this branch touches,
|
|
# so new code is held to the strict config and the backlog shrinks as files
|
|
# get touched, without a red CI on every unrelated PR.
|
|
#
|
|
# "Touches" means semantically, not cosmetically: a repo-wide `ruff format`
|
|
# adoption (or any future bulk reformat) diffs every file against BASE_REF
|
|
# without changing what any of them mean — if that gets counted as "changed",
|
|
# the ratchet degrades into gating the whole backlog on whichever PR happens
|
|
# to run the formatter first. A file only counts if re-running ruff on the
|
|
# BASE_REF version doesn't reproduce today's content byte-for-byte. Resolve
|
|
# the ruff binary once up front and call it directly in the loop below —
|
|
# invoking `uv run ruff` per file (up to ~2x per changed file) was flaky,
|
|
# occasionally producing a spurious empty result that made a purely
|
|
# reformatted file look "meaningful".
|
|
BASE_REF ?= origin/main
|
|
typecheck:
|
|
@ruff_bin=$$(uv run which ruff); \
|
|
changed=$$(git diff --name-only --diff-filter=ACMR $(BASE_REF)...HEAD -- '*.py' 2>/dev/null); \
|
|
meaningful=""; \
|
|
for f in $$changed; do \
|
|
if git cat-file -e $(BASE_REF):$$f 2>/dev/null; then \
|
|
old_reformatted=$$(git show $(BASE_REF):$$f | "$$ruff_bin" format --stdin-filename "$$f" - 2>/dev/null | "$$ruff_bin" check --fix --stdin-filename "$$f" - 2>/dev/null); \
|
|
if [ "$$old_reformatted" = "$$(cat "$$f")" ]; then continue; fi; \
|
|
fi; \
|
|
meaningful="$$meaningful $$f"; \
|
|
done; \
|
|
changed=$$(printf '%s\n' $$meaningful); \
|
|
if [ -z "$$changed" ]; then \
|
|
echo "No semantically changed Python files vs $(BASE_REF) — skipping mypy."; \
|
|
exit 0; \
|
|
fi; \
|
|
echo "$$changed"; \
|
|
mypy_status=0; \
|
|
for pkg in flowsint-core flowsint-api flowsint-enrichers flowsint-types; do \
|
|
files=$$(echo "$$changed" | grep "^$$pkg/" | sed "s|^$$pkg/||"); \
|
|
[ -z "$$files" ] && continue; \
|
|
echo "== mypy: $$pkg =="; \
|
|
(cd $$pkg && echo "$$files" | xargs -r uv run mypy) || mypy_status=1; \
|
|
done; \
|
|
exit $$mypy_status
|
|
|
|
install:
|
|
$(MAKE) infra-dev
|
|
uv sync
|
|
cd flowsint-api && uv run alembic upgrade head
|
|
|
|
status:
|
|
@echo "=== DEV Containers ==="
|
|
@$(COMPOSE_DEV) ps 2>/dev/null || echo "No DEV containers"
|
|
@echo ""
|
|
@echo "=== PROD Containers ==="
|
|
@$(COMPOSE_PROD) ps 2>/dev/null || echo "No PROD containers"
|
|
|
|
down:
|
|
-$(COMPOSE_DEV) down
|
|
-$(COMPOSE_PROD) down
|
|
|
|
clean:
|
|
@echo "This will remove ALL Docker data. Continue? [y/N]"
|
|
@read confirm; \
|
|
if [ "$$confirm" != "y" ]; then exit 1; fi
|
|
-$(COMPOSE_DEV) down -v --rmi all --remove-orphans
|
|
-$(COMPOSE_PROD) down -v --rmi all --remove-orphans
|
|
rm -rf flowsint-app/node_modules
|
|
rm -rf .venv
|
|
|
|
regenerate-router:
|
|
@echo "Regenerating flowsint-app/src/routeTree.gen.ts"
|
|
cd $(PROJECT_ROOT)/flowsint-app && npx tsr generate
|
|
|
|
help:
|
|
@echo "Flowsint Makefile"
|
|
@echo ""
|
|
@echo "Development:"
|
|
@echo " make dev - Start DEV environment (local build, hot-reload)"
|
|
@echo " make build-dev - Build DEV images"
|
|
@echo " make up-dev - Start DEV containers"
|
|
@echo " make logs-dev - Follow DEV logs"
|
|
@echo " make infra-dev - Start only infra (postgres/redis/neo4j)"
|
|
@echo ""
|
|
@echo "Production (pre-built GHCR images):"
|
|
@echo " make prod - Pull images and start PROD environment"
|
|
@echo " make up-prod - Start PROD containers"
|
|
@echo " make logs-prod - Follow PROD logs"
|
|
@echo ""
|
|
@echo "Local (no Docker):"
|
|
@echo " make api - Run API locally"
|
|
@echo " make frontend - Run frontend locally"
|
|
@echo " make celery - Run Celery worker locally"
|
|
@echo ""
|
|
@echo "Migrations:"
|
|
@echo " make migrate-dev - Run Neo4j DEV migrations"
|
|
@echo " make migrate-prod - Run Neo4j PROD migrations"
|
|
@echo " make alembic-upgrade - Run Alembic migrations (upgrade head)"
|
|
@echo " make alembic-downgrade - Rollback last Alembic migration"
|
|
@echo " make alembic-revision m=.. - Create new Alembic migration"
|
|
@echo ""
|
|
@echo "Utilities:"
|
|
@echo " make status - Show container status"
|
|
@echo " make down - Stop all containers"
|
|
@echo " make clean - Remove all Docker data"
|
|
@echo " make install - Install dependencies locally"
|
|
@echo " make test - Run tests"
|