Spaces:
Running
Running
File size: 12,824 Bytes
d202ada |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
.PHONY: all init format lint build build_frontend install_frontend run_frontend run_backend dev help tests coverage clean_python_cache clean_npm_cache clean_all
# Configurations
VERSION=$(shell grep "^version" pyproject.toml | sed 's/.*\"\(.*\)\"$$/\1/')
DOCKERFILE=docker/build_and_push.Dockerfile
DOCKERFILE_BACKEND=docker/build_and_push_backend.Dockerfile
DOCKERFILE_FRONTEND=docker/frontend/build_and_push_frontend.Dockerfile
DOCKER_COMPOSE=docker_example/docker-compose.yml
PYTHON_REQUIRED=$(shell grep '^requires-python[[:space:]]*=' pyproject.toml | sed -n 's/.*"\([^"]*\)".*/\1/p')
RED=\033[0;31m
NC=\033[0m # No Color
GREEN=\033[0;32m
log_level ?= debug
host ?= 0.0.0.0
port ?= 7860
env ?= .env
open_browser ?= true
path = src/backend/base/langflow/frontend
workers ?= 1
async ?= true
lf ?= false
ff ?= true
all: help
######################
# UTILITIES
######################
# increment the patch version of the current package
patch: ## bump the version in langflow and langflow-base
@echo 'Patching the version'
@poetry version patch
@echo 'Patching the version in langflow-base'
@cd src/backend/base && poetry version patch
@make lock
# check for required tools
check_tools:
@command -v uv >/dev/null 2>&1 || { echo >&2 "$(RED)uv is not installed. Aborting.$(NC)"; exit 1; }
@command -v npm >/dev/null 2>&1 || { echo >&2 "$(RED)NPM is not installed. Aborting.$(NC)"; exit 1; }
@echo "$(GREEN)All required tools are installed.$(NC)"
help: ## show this help message
@echo '----'
@grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | \
awk -F ':.*##' '{printf "\033[36mmake %s\033[0m: %s\n", $$1, $$2}' | \
column -c2 -t -s :
@echo '----'
######################
# INSTALL PROJECT
######################
reinstall_backend: ## forces reinstall all dependencies (no caching)
@echo 'Installing backend dependencies'
@uv sync -n --reinstall --frozen
install_backend: ## install the backend dependencies
@echo 'Installing backend dependencies'
@uv sync --frozen
install_frontend: ## install the frontend dependencies
@echo 'Installing frontend dependencies'
@cd src/frontend && npm install > /dev/null 2>&1
build_frontend: ## build the frontend static files
@echo 'Building frontend static files'
@cd src/frontend && CI='' npm run build > /dev/null 2>&1
@rm -rf src/backend/base/langflow/frontend
@cp -r src/frontend/build src/backend/base/langflow/frontend
init: check_tools clean_python_cache clean_npm_cache ## initialize the project
@make install_backend
@make install_frontend
@make build_frontend
@echo "$(GREEN)All requirements are installed.$(NC)"
@uv run langflow run
######################
# CLEAN PROJECT
######################
clean_python_cache:
@echo "Cleaning Python cache..."
find . -type d -name '__pycache__' -exec rm -r {} +
find . -type f -name '*.py[cod]' -exec rm -f {} +
find . -type f -name '*~' -exec rm -f {} +
find . -type f -name '.*~' -exec rm -f {} +
find . -type d -empty -delete
@echo "$(GREEN)Python cache cleaned.$(NC)"
clean_npm_cache:
@echo "Cleaning npm cache..."
cd src/frontend && npm cache clean --force
rm -rf src/frontend/node_modules src/frontend/build src/backend/base/langflow/frontend src/frontend/package-lock.json
@echo "$(GREEN)NPM cache and frontend directories cleaned.$(NC)"
clean_all: clean_python_cache clean_npm_cache # clean all caches and temporary directories
@echo "$(GREEN)All caches and temporary directories cleaned.$(NC)"
setup_uv: ## install poetry using pipx
pipx install uv
add:
@echo 'Adding dependencies'
ifdef devel
@cd src/backend/base && uv add --group dev $(devel)
endif
ifdef main
@uv add $(main)
endif
ifdef base
@cd src/backend/base && uv add $(base)
endif
######################
# CODE TESTS
######################
coverage: ## run the tests and generate a coverage report
@uv run coverage run
@uv run coverage erase
unit_tests: ## run unit tests
@uv sync --extra dev --frozen
@EXTRA_ARGS=""
@if [ "$(async)" = "true" ]; then \
EXTRA_ARGS="$$EXTRA_ARGS --instafail -n auto"; \
fi; \
if [ "$(lf)" = "true" ]; then \
EXTRA_ARGS="$$EXTRA_ARGS --lf"; \
fi; \
if [ "$(ff)" = "true" ]; then \
EXTRA_ARGS="$$EXTRA_ARGS --ff"; \
fi; \
uv run pytest src/backend/tests --ignore=src/backend/tests/integration $$EXTRA_ARGS --instafail -ra -m 'not api_key_required' --durations-path src/backend/tests/.test_durations --splitting-algorithm least_duration $(args)
unit_tests_looponfail:
@make unit_tests args="-f"
integration_tests:
uv run pytest src/backend/tests/integration \
--instafail -ra \
$(args)
integration_tests_no_api_keys:
uv run pytest src/backend/tests/integration \
--instafail -ra -m "not api_key_required" \
$(args)
integration_tests_api_keys:
uv run pytest src/backend/tests/integration \
--instafail -ra -m "api_key_required" \
$(args)
tests: ## run unit, integration, coverage tests
@echo 'Running Unit Tests...'
make unit_tests
@echo 'Running Integration Tests...'
make integration_tests
@echo 'Running Coverage Tests...'
make coverage
######################
# CODE QUALITY
######################
codespell: ## run codespell to check spelling
@poetry install --with spelling
poetry run codespell --toml pyproject.toml
fix_codespell: ## run codespell to fix spelling errors
@poetry install --with spelling
poetry run codespell --toml pyproject.toml --write
format: ## run code formatters
@uv run ruff check . --fix
@uv run ruff format . --config pyproject.toml
@cd src/frontend && npm run format
unsafe_fix:
@uv run ruff check . --fix --unsafe-fixes
lint: install_backend ## run linters
@uv run mypy --namespace-packages -p "langflow"
install_frontendci:
@cd src/frontend && npm ci > /dev/null 2>&1
install_frontendc:
@cd src/frontend && rm -rf node_modules package-lock.json && npm install > /dev/null 2>&1
run_frontend: ## run the frontend
@-kill -9 `lsof -t -i:3000`
@cd src/frontend && npm start
tests_frontend: ## run frontend tests
ifeq ($(UI), true)
@cd src/frontend && npx playwright test --ui --project=chromium
else
@cd src/frontend && npx playwright test --project=chromium
endif
run_cli: install_frontend install_backend build_frontend ## run the CLI
@echo 'Running the CLI'
@uv run langflow run \
--frontend-path $(path) \
--log-level $(log_level) \
--host $(host) \
--port $(port) \
$(if $(env),--env-file $(env),) \
$(if $(filter false,$(open_browser)),--no-open-browser)
run_cli_debug:
@echo 'Running the CLI in debug mode'
@make install_frontend > /dev/null
@echo 'Building the frontend'
@make build_frontend > /dev/null
@echo 'Install backend dependencies'
@make install_backend > /dev/null
ifdef env
@make start env=$(env) host=$(host) port=$(port) log_level=debug
else
@make start host=$(host) port=$(port) log_level=debug
endif
setup_devcontainer: ## set up the development container
make install_backend
make install_frontend
make build_frontend
uv run langflow --frontend-path src/frontend/build
setup_env: ## set up the environment
@sh ./scripts/setup/setup_env.sh
frontend: install_frontend ## run the frontend in development mode
make run_frontend
frontendc: install_frontendc
make run_frontend
backend: setup_env install_backend ## run the backend in development mode
@-kill -9 $$(lsof -t -i:7860) || true
ifdef login
@echo "Running backend autologin is $(login)";
LANGFLOW_AUTO_LOGIN=$(login) uv run uvicorn \
--factory langflow.main:create_app \
--host 0.0.0.0 \
--port $(port) \
$(if $(filter-out 1,$(workers)),, --reload) \
--env-file $(env) \
--loop asyncio \
$(if $(workers),--workers $(workers),)
else
@echo "Running backend respecting the $(env) file";
uv run uvicorn \
--factory langflow.main:create_app \
--host 0.0.0.0 \
--port $(port) \
$(if $(filter-out 1,$(workers)),, --reload) \
--env-file $(env) \
--loop asyncio \
$(if $(workers),--workers $(workers),)
endif
build_and_run: setup_env ## build the project and run it
rm -rf dist
rm -rf src/backend/base/dist
make build
uv run pip install dist/*.tar.gz
uv run langflow run
build_and_install: ## build the project and install it
@echo 'Removing dist folder'
rm -rf dist
rm -rf src/backend/base/dist
make build && uv run pip install dist/*.whl && pip install src/backend/base/dist/*.whl --force-reinstall
build: setup_env ## build the frontend static files and package the project
ifdef base
make install_frontendci
make build_frontend
make build_langflow_base args="$(args)"
endif
ifdef main
make install_frontendci
make build_frontend
make build_langflow_base args="$(args)"
make build_langflow args="$(args)"
endif
build_langflow_base:
cd src/backend/base && uv build $(args)
rm -rf src/backend/base/langflow/frontend
build_langflow_backup:
uv lock && uv build
build_langflow:
uv lock --no-upgrade
uv build $(args)
ifdef restore
mv pyproject.toml.bak pyproject.toml
mv uv.lock.bak uv.lock
endif
docker_build: dockerfile_build clear_dockerimage ## build DockerFile
docker_build_backend: dockerfile_build_be clear_dockerimage ## build Backend DockerFile
docker_build_frontend: dockerfile_build_fe clear_dockerimage ## build Frontend Dockerfile
dockerfile_build:
@echo 'BUILDING DOCKER IMAGE: ${DOCKERFILE}'
@docker build --rm \
-f ${DOCKERFILE} \
-t langflow:${VERSION} .
dockerfile_build_be: dockerfile_build
@echo 'BUILDING DOCKER IMAGE BACKEND: ${DOCKERFILE_BACKEND}'
@docker build --rm \
--build-arg LANGFLOW_IMAGE=langflow:${VERSION} \
-f ${DOCKERFILE_BACKEND} \
-t langflow_backend:${VERSION} .
dockerfile_build_fe: dockerfile_build
@echo 'BUILDING DOCKER IMAGE FRONTEND: ${DOCKERFILE_FRONTEND}'
@docker build --rm \
--build-arg LANGFLOW_IMAGE=langflow:${VERSION} \
-f ${DOCKERFILE_FRONTEND} \
-t langflow_frontend:${VERSION} .
clear_dockerimage:
@echo 'Clearing the docker build'
@if docker images -f "dangling=true" -q | grep -q '.*'; then \
docker rmi $$(docker images -f "dangling=true" -q); \
fi
docker_compose_up: docker_build docker_compose_down
@echo 'Running docker compose up'
docker compose -f $(DOCKER_COMPOSE) up --remove-orphans
docker_compose_down:
@echo 'Running docker compose down'
docker compose -f $(DOCKER_COMPOSE) down || true
dcdev_up:
@echo 'Running docker compose up'
docker compose -f docker/dev.docker-compose.yml down || true
docker compose -f docker/dev.docker-compose.yml up --remove-orphans
lock_base:
cd src/backend/base && uv lock
lock_langflow:
uv lock
lock: ## lock dependencies
@echo 'Locking dependencies'
cd src/backend/base && uv lock
uv lock
update: ## update dependencies
@echo 'Updating dependencies'
cd src/backend/base && uv sync --upgrade
uv sync --upgrade
publish_base:
cd src/backend/base && uv publish
publish_langflow:
uv publish
publish_base_testpypi:
# TODO: update this to use the test-pypi repository
cd src/backend/base && uv publish -r test-pypi
publish_langflow_testpypi:
# TODO: update this to use the test-pypi repository
uv publish -r test-pypi
publish: ## build the frontend static files and package the project and publish it to PyPI
@echo 'Publishing the project'
ifdef base
make publish_base
endif
ifdef main
make publish_langflow
endif
publish_testpypi: ## build the frontend static files and package the project and publish it to PyPI
@echo 'Publishing the project'
ifdef base
#TODO: replace with uvx twine upload dist/*
poetry config repositories.test-pypi https://test.pypi.org/legacy/
make publish_base_testpypi
endif
ifdef main
#TODO: replace with uvx twine upload dist/*
poetry config repositories.test-pypi https://test.pypi.org/legacy/
make publish_langflow_testpypi
endif
# example make alembic-revision message="Add user table"
alembic-revision: ## generate a new migration
@echo 'Generating a new Alembic revision'
cd src/backend/base/langflow/ && uv run alembic revision --autogenerate -m "$(message)"
alembic-upgrade: ## upgrade database to the latest version
@echo 'Upgrading database to the latest version'
cd src/backend/base/langflow/ && uv run alembic upgrade head
alembic-downgrade: ## downgrade database by one version
@echo 'Downgrading database by one version'
cd src/backend/base/langflow/ && uv run alembic downgrade -1
alembic-current: ## show current revision
@echo 'Showing current Alembic revision'
cd src/backend/base/langflow/ && uv run alembic current
alembic-history: ## show migration history
@echo 'Showing Alembic migration history'
cd src/backend/base/langflow/ && uv run alembic history --verbose
alembic-check: ## check migration status
@echo 'Running alembic check'
cd src/backend/base/langflow/ && uv run alembic check
alembic-stamp: ## stamp the database with a specific revision
@echo 'Stamping the database with revision $(revision)'
cd src/backend/base/langflow/ && uv run alembic stamp $(revision)
|