Makefile
Rama main · réplica de lectura del repositorio original.
# Makefile for the Nvisy runtime: the Rust workspace in `crates/`
# and the Python model services in `packages/`.
#
# Targets are named for what they act on, not which toolchain runs
# them: `lint`/`test`/`doc` cover the crates, `services-*` the
# packages.
# Default to a single recipe shell so a failure inside a piped
# command (e.g. server panics under `tee`) is reported by make.
# GNU make before 3.82, which macOS still ships, ignores .SHELLFLAGS, so the
# loops below also `set -e` themselves.
.SHELLFLAGS := -eu -o pipefail -c
SHELL := /bin/bash
# The BentoML services, by modality.
SERVICES := ner ocr stt
# Timestamped log line, tagged with the running target. Use as `$(call log,msg)`.
define log
printf "[%s] [MAKE] [$(MAKECMDGOALS)] $(1)\n" "$$(date '+%Y-%m-%d %H:%M:%S')"
endef
# ─── Crates ────────────────────────────────────────────────────
.PHONY: lint
lint: ## Format check + clippy over the workspace.
@$(call log,Running format check...)
@cargo fmt --all -- --check
@$(call log,Running clippy...)
@cargo clippy --workspace --all-targets -- -D warnings
@$(call log,Lint passed.)
.PHONY: test
test: ## Run the workspace test suite.
@cargo test --workspace
.PHONY: doc
doc: ## Build rustdoc for every crate with `-D warnings` (nightly, for --cfg docsrs).
@RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo +nightly doc --workspace --no-deps
.PHONY: machete
machete: ## Find dependencies declared but never used.
@cargo machete
.PHONY: deny
deny: ## Run cargo-deny (advisories, bans, licenses, sources).
@cargo deny check
.PHONY: ci
ci: lint test doc machete deny ## Run the crate CI matrix.
@$(call log,Crate CI passed.)
# ─── Services ──────────────────────────────────────────────────
# Each service is its own uv project with its own lock and .venv, so every
# target runs a command in the environment of the project it acts on:
# `uv run --project packages/elide-<s>`. Always from the repository root, never
# from inside a package: `Image.requirements_file()` resolves its path against
# the working directory when a service module is imported.
.PHONY: sync
sync: ## Install the tooling and every service's dependencies into their venvs.
@$(call log,Syncing tooling...)
@uv sync
@set -e; for s in $(SERVICES); do \
$(call log,Syncing elide-$$s...); \
uv sync --project packages/elide-$$s; \
done
.PHONY: lock
lock: ## Relock the tooling and every service after a manifest change.
@uv lock
@set -e; for s in $(SERVICES); do uv lock --project packages/elide-$$s; done
.PHONY: services-lint
services-lint: ## ruff check + format check over the services.
@$(call log,Running ruff check...)
@uv run ruff check .
@$(call log,Running ruff format check...)
@uv run ruff format --check .
.PHONY: services-fmt
services-fmt: ## Auto-format the services with ruff.
@$(call log,Formatting...)
@uv run ruff format .
# Depends on `requirements`: a service module calls
# `Image.requirements_file(...)` at import, which resolves the path
# eagerly, so pytest fails at collection without the exports.
.PHONY: services-test
services-test: requirements ## Run elide-core's tests, then each service's.
@$(call log,Testing elide-core...)
@uv run pytest
@set -e; for s in $(SERVICES); do \
$(call log,Testing elide-$$s...); \
uv run --project packages/elide-$$s pytest packages/elide-$$s; \
done
.PHONY: requirements
requirements: ## Export each service's locked dependencies from its uv.lock.
@$(call log,Regenerating service requirements...)
@python3 scripts/gen_requirements.py $(addprefix elide-,$(SERVICES))
# Two steps rather than `build --containerize`, which accepts no tag. `build`
# tags the bento with its content hash, so `-o tag` captures that (it prints
# the tag prefixed with `__tag__:`, which is stripped) to hand to
# `containerize -t`, which gives the predictable name
# docker/compose.dev.yaml refers to. The tag is captured without a pipe, so a
# failed build fails the assignment rather than hiding behind the pipe's last
# command.
#
# Builds for the host architecture only, which is what a developer wants: the
# image runs natively, and cross-building under emulation is slow enough to be
# useless for these (an emulated PyTorch import does not finish loading). The
# published multi-architecture manifests are assembled in CI from native
# runners per architecture, not here.
.PHONY: services
services: requirements ## Build every Bento from its bentofile.
@set -e; for s in $(SERVICES); do \
$(call log,Building elide-$$s...); \
uv run --project packages/elide-$$s \
bentoml build -f packages/elide-$$s/bentofile.yaml .; \
done
.PHONY: services-image
services-image: requirements ## Build and containerize every Bento into a local Docker image.
@set -e; for s in $(SERVICES); do \
$(call log,Containerizing elide-$$s...); \
bento=$$(uv run --project packages/elide-$$s \
bentoml build -f packages/elide-$$s/bentofile.yaml -o tag .); \
bento=$${bento#__tag__:}; \
uv run --project packages/elide-$$s \
bentoml containerize "$$bento" -t "elide-$$s:latest"; \
done
# Each depends on `requirements` for the same reason as
# `services-test`: `bentoml serve` imports the service module.
.PHONY: serve-ner
serve-ner: requirements ## Serve the NER service locally with reload.
@uv run --project packages/elide-ner bentoml serve elide_ner.service:NerService --reload
.PHONY: serve-ocr
serve-ocr: requirements ## Serve the OCR service locally with reload.
@uv run --project packages/elide-ocr bentoml serve elide_ocr.service:OcrService --reload
.PHONY: serve-stt
serve-stt: requirements ## Serve the speech-to-text service locally with reload.
@uv run --project packages/elide-stt bentoml serve elide_stt.service:SttService --reload
.PHONY: services-ci
services-ci: services-lint services-test ## Run the service CI matrix.
@$(call log,Service CI passed.)
.PHONY: ci-all
ci-all: ci services-ci ## Run both CI matrices.
@$(call log,All CI passed.)
# `help` parses the `## …` doc comment after each target name and
# prints `target description`. Keeping help auto-generated from
# the targets themselves means new targets don't need a manual
# entry to show up.
.PHONY: help
help: ## Show this help.
@awk 'BEGIN { FS = ":.*## " } /^[a-zA-Z0-9_.-]+:.*## / { printf " %-20s %s\n", $$1, $$2 }' $(MAKEFILE_LIST)