.PHONY: all build doc machete test examples validate-deps smoke-test smoke-test-constrained smoke-test-memory
.PHONY: show-docs
.PHONY: build-qrusty publish publish-docker
.PHONY: traceability traceability-report
.PHONY: fmt fmt-check lint
.PHONY: fmt-rust fmt-check-rust lint-rust
.PHONY: fmt-py fmt-check-py lint-py
.PHONY: fmt-node fmt-check-node lint-node
.PHONY: fmt-yaml fmt-check-yaml lint-yaml
.PHONY: fmt-md fmt-check-md lint-md
.PHONY: fmt-toml fmt-check-toml lint-toml
.PHONY: coverage coverage-missing coverage-html coverage-summary-json coverage-clean
.PHONY: bench bench-storage bench-http bench-smoke bench-smoke-storage bench-smoke-http
.PHONY: bench-memory bench-http-memory bench-ws-memory
.PHONY: bench-smoke-memory bench-smoke-http-memory bench-smoke-ws-memory
.PHONY: test-live-pyclient test-selenium test-live-nodeclient test-integration-all
PY_RUFF ?= uv tool run ruff
PY_MYPY ?= uv tool run --with types-requests mypy
NODE_PRETTIER ?= npx -y prettier@3.3.3
TAPLO ?= taplo
YAMLLINT ?= uv tool run yamllint
MARKDOWNLINT ?= npx -y markdownlint-cli2
NPM_PUBLISH_ARGS :=
ifdef NPM_OTP
NPM_PUBLISH_ARGS += --otp=$(NPM_OTP)
endif
DOCKER_PLATFORMS := linux/amd64,linux/arm64
all: build doc machete test examples
build:
cargo build
doc:
cargo doc
machete:
cargo machete
test:
cargo test
coverage:
cargo llvm-cov --workspace --all-features
coverage-missing:
@mkdir -p target/llvm-cov
cargo llvm-cov --workspace --all-features --text --show-missing-lines --output-path target/llvm-cov/missing.txt
@echo "Saved: target/llvm-cov/missing.txt"
coverage-html:
cargo llvm-cov --workspace --all-features --html
@echo "Open: target/llvm-cov/html/index.html"
coverage-summary-json:
@mkdir -p target/llvm-cov
cargo llvm-cov --workspace --all-features --json --summary-only --output-path target/llvm-cov/summary.json
@echo "Saved: target/llvm-cov/summary.json"
coverage-clean:
cargo llvm-cov clean
bench: bench-storage bench-http bench-memory bench-http-memory bench-ws-memory
bench-storage:
cargo bench --bench storage_benchmarks
bench-http:
cargo bench --bench http_benchmarks
bench-memory:
cargo bench --bench memory_benchmarks
bench-http-memory:
cargo bench --bench http_memory_benchmarks
bench-ws-memory:
cargo bench --bench ws_memory_benchmarks
bench-smoke: bench-smoke-storage bench-smoke-http bench-smoke-memory bench-smoke-http-memory bench-smoke-ws-memory
bench-smoke-storage:
cargo bench --bench storage_benchmarks -- --test
bench-smoke-http:
cargo bench --bench http_benchmarks -- --test
bench-smoke-memory:
cargo bench --bench memory_benchmarks -- --test
bench-smoke-http-memory:
cargo bench --bench http_memory_benchmarks -- --test
bench-smoke-ws-memory:
cargo bench --bench ws_memory_benchmarks -- --test
fmt: fmt-rust fmt-py fmt-node fmt-yaml fmt-md fmt-toml
fmt-check: fmt-check-rust fmt-check-py fmt-check-node fmt-check-yaml fmt-check-md fmt-check-toml
lint: lint-rust lint-py lint-node lint-yaml lint-md lint-toml
fmt-rust:
cargo fmt --all
fmt-check-rust:
cargo fmt --all -- --check
lint-rust:
cargo clippy --all-targets --all-features -- -D warnings
fmt-py:
@$(PY_RUFF) format scripts integrations/python integrations/examples integrations/pyclient
fmt-check-py:
@$(PY_RUFF) format --check scripts integrations/python integrations/examples integrations/pyclient
lint-py:
@$(PY_RUFF) check scripts integrations/python integrations/examples integrations/pyclient
@$(PY_MYPY) --config-file mypy.ini scripts/traceability.py scripts/smoke_test.py scripts/live_client_tests.py scripts/selenium_ui_tests.py integrations/python integrations/examples integrations/pyclient
fmt-node:
@$(NODE_PRETTIER) --write --ignore-unknown --ignore-path .gitignore \
"web_ui/**/*.{ts,tsx,js,jsx,json,css,md,html}" \
"integrations/nodeclient/**/*.{js,json,md}" \
"integrations/node-red/**/*.{js,json,md}"
fmt-check-node:
@$(NODE_PRETTIER) --check --ignore-unknown --ignore-path .gitignore \
"web_ui/**/*.{ts,tsx,js,jsx,json,css,md,html}" \
"integrations/nodeclient/**/*.{js,json,md}" \
"integrations/node-red/**/*.{js,json,md}"
lint-node:
@ @find integrations/nodeclient integrations/node-red -type f -name '*.js' -not -path '*/node_modules/*' -print0 | xargs -0 -r -n 1 node --check
@ @if [ -d webui/node_modules ]; then \
npx -y --package=typescript@5.4.5 tsc -p webui/tsconfig.json --noEmit; \
else \
echo "Skipping webui typecheck (run 'make build-webui' or 'cd webui && npm install')"; \
fi
YAML_GLOB := $(shell find . -name "*.yml" -o -name "*.yaml" 2>/dev/null \
| grep -v "^\./\.venv" | grep -v "^\./target" \
| grep -v "^\./\.git" | grep -v "/node_modules/")
fmt-yaml:
@$(NODE_PRETTIER) --write --ignore-unknown --ignore-path .gitignore \
"**/*.yml" "**/*.yaml"
fmt-check-yaml:
@$(NODE_PRETTIER) --check --ignore-unknown --ignore-path .gitignore \
"**/*.yml" "**/*.yaml"
lint-yaml:
@$(YAMLLINT) --config-file .yamllint.yml $(YAML_GLOB)
fmt-md:
@$(NODE_PRETTIER) --write --ignore-unknown --ignore-path .gitignore \
"**/*.md"
fmt-check-md:
@$(NODE_PRETTIER) --check --ignore-unknown --ignore-path .gitignore \
"**/*.md"
lint-md:
@$(MARKDOWNLINT) "**/*.md" "!.venv/**" "!target/**" "!**/node_modules/**" "!.git/**"
fmt-toml:
@$(TAPLO) fmt Cargo.toml crates/*/Cargo.toml integrations/pyclient/pyproject.toml
fmt-check-toml:
@$(TAPLO) fmt --check Cargo.toml crates/*/Cargo.toml integrations/pyclient/pyproject.toml
lint-toml:
@$(TAPLO) lint Cargo.toml crates/*/Cargo.toml integrations/pyclient/pyproject.toml
examples:
@echo "Testing Python integration example..."
@cd integrations/python && python3 -m py_compile qrusty_publish.py
@cd integrations/python && python3 -m py_compile qrusty_consume.py
@cd integrations/python && python3 -m py_compile qrusty_demo.py
@cd integrations/python && test -f requirements.txt && echo "Python requirements file exists" || echo "Python requirements missing"
@echo "Testing Python queue management examples..."
@cd integrations/examples && python3 -m py_compile queue_management_examples.py
@echo "Validating Node-RED integration..."
@cd integrations/node-red && (command -v node >/dev/null 2>&1 && node -e "JSON.parse(require('fs').readFileSync('package.json', 'utf8'))" || echo "Node.js not available, skipping Node-RED validation")
@cd integrations/node-red && test -f qrusty-publish.js && echo "Node-RED publish example exists" || echo "Node-RED publish example missing"
@cd integrations/node-red && test -f qrusty-consume.js && echo "Node-RED consume example exists" || echo "Node-RED consume example missing"
@echo "Validating environment example..."
@test -f example.env && echo "Environment example exists" || echo "Environment example missing"
@echo "Validating documentation examples..."
@test -f integrations/examples/priority_examples.md && echo "Priority examples documentation exists" || echo "Priority examples documentation missing"
@test -f integrations/examples/api_usage_examples.md && echo "API usage examples documentation exists" || echo "API usage examples documentation missing"
@test -f integrations/examples/queue_management_guide.md && echo "Queue management guide exists" || echo "Queue management guide missing"
@echo "All available integration examples validated successfully!"
show-docs:
cargo doc --no-deps --open
traceability:
@echo "Generating traceability report..."
@if command -v uv >/dev/null 2>&1; then \
uv run --python .venv/bin/python scripts/traceability.py; \
else \
. .venv/bin/activate && python scripts/traceability.py; \
fi
traceability-report:
@echo "Generating traceability report to docs/traceability_report.md..."
@if command -v uv >/dev/null 2>&1; then \
uv run --python .venv/bin/python scripts/traceability.py > docs/traceability_report.md; \
else \
. .venv/bin/activate && python scripts/traceability.py > docs/traceability_report.md; \
fi
@echo "Report saved to docs/traceability_report.md"
publish:
@bash scripts/publish.sh
build-qrusty:
docker buildx build --no-cache --pull --platform $(DOCKER_PLATFORMS) -t greeng340or/qrusty -f Dockerfile --push .
publish-docker:
$(eval VERSION := $(shell grep '^version' Cargo.toml | head -n1 | sed 's/.*"\(.*\)".*/\1/'))
docker buildx build --no-cache --pull --platform $(DOCKER_PLATFORMS) \
-t greeng340or/qrusty:$(VERSION) \
-t greeng340or/qrusty:latest \
-f Dockerfile --push .
publish-client:
cd crates/qrusty_client && cargo publish
build-pyclient:
rm -rf integrations/pyclient/dist
cd integrations/pyclient && python3 -m build
test-pyclient:
cd integrations/pyclient && python3 -m unittest discover -s tests
doc-pyclient:
cd integrations/pyclient && pdoc qrusty_pyclient.py -o docs
publish-pyclient:
cd integrations/pyclient && python3 -m twine upload dist/*
build-nodeclient:
cd integrations/nodeclient && npm install
test-nodeclient:
cd integrations/nodeclient && npm test
doc-nodeclient:
cd integrations/nodeclient && npm run docs
publish-nodeclient:
@cd integrations/nodeclient && (set -e; \
trap 'rm -f .npmrc' EXIT; \
printf "%s\n" "//registry.npmjs.org/:_authToken=$$NPM_TOKEN" > .npmrc; \
npm publish $(NPM_PUBLISH_ARGS))
publish-node-red:
@cd integrations/node-red && (set -e; \
trap 'rm -f .npmrc' EXIT; \
printf "%s\n" "//registry.npmjs.org/:_authToken=$$NPM_TOKEN" > .npmrc; \
npm publish $(NPM_PUBLISH_ARGS))
build-node-red:
@echo "Node-RED integration has no build step (JS snippets only)"
test-node-red:
@ @cd integrations/node-red && node -e "JSON.parse(require('fs').readFileSync('package.json', 'utf8'))"
@find integrations/node-red -type f -name '*.js' -not -path '*/node_modules/*' -print0 | xargs -0 -r -n 1 node --check
pack-node-red:
@cd integrations/node-red && npm pack --dry-run
build-webui:
cd web_ui && npm install && npm run build
clean-webui:
rm -rf static_webui
run-dev:
make build
make build-webui
echo "Starting qrusty server..."
echo "Access the UI at: http://localhost:6784/ui"
DATA_PATH=/tmp/qrusty/data WEBUI_DIR=static_webui cargo run
validate-deps:
@if test -f scripts/validate_dependencies.sh; then \
chmod +x scripts/validate_dependencies.sh && ./scripts/validate_dependencies.sh; \
else \
echo "Dependency validation script not found"; \
fi
CARGO_HOST_TARGET := $(shell rustc -vV 2>/dev/null | awk '/^host:/{print $$2}')
QRUSTY_DEBUG_BIN := target/$(CARGO_HOST_TARGET)/debug/qrusty
smoke-test: build
@echo "Running live smoke test (Implements: SYS-0011) ..."
@if command -v uv >/dev/null 2>&1; then \
QRUSTY_MEMORY_PRESSURE_THRESHOLD=0.99 uv run --python .venv/bin/python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS); \
else \
QRUSTY_MEMORY_PRESSURE_THRESHOLD=0.99 . .venv/bin/activate && python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS); \
fi
smoke-test-constrained: build
@echo "Running smoke test with constrained memory (256 MB) ..."
@echo "This validates memory pressure detection and load shedding."
@QRUSTY_MEMORY_LIMIT_MB=256 \
QRUSTY_HOT_TIER_SIZE=100 \
QRUSTY_REFILL_THRESHOLD=25 \
ROCKSDB_CACHE_MB=16 \
ROCKSDB_WRITE_BUFFER_MB=8 \
$(if $(shell command -v uv 2>/dev/null), \
uv run --python .venv/bin/python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS), \
. .venv/bin/activate && python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS))
smoke-test-memory: build
@echo "Running live smoke test with in-memory storage (Implements: SYS-0013) ..."
@if command -v uv >/dev/null 2>&1; then \
STORAGE_MODE=memory QRUSTY_MEMORY_PRESSURE_THRESHOLD=0.99 uv run --python .venv/bin/python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS); \
else \
STORAGE_MODE=memory QRUSTY_MEMORY_PRESSURE_THRESHOLD=0.99 . .venv/bin/activate && python scripts/smoke_test.py --binary $(QRUSTY_DEBUG_BIN) $(SMOKE_ARGS); \
fi
LIVE_TEST_PORT ?= 17785
SELENIUM_PORT ?= 17786
NODE_LIVE_PORT ?= 17787
SELENIUM_HUB ?= http://172.17.0.1:4444
QRUSTY_HOST ?= $(shell hostname -I | awk '{print $$1}')
test-live-pyclient: build
@echo "Running Python live client tests ..."
@if command -v uv >/dev/null 2>&1; then \
uv run --python .venv/bin/python scripts/live_client_tests.py \
--binary $(QRUSTY_DEBUG_BIN) --port $(LIVE_TEST_PORT); \
else \
. .venv/bin/activate && python scripts/live_client_tests.py \
--binary $(QRUSTY_DEBUG_BIN) --port $(LIVE_TEST_PORT); \
fi
test-selenium: build
@echo "Running Selenium UI tests (hub: $(SELENIUM_HUB)) ..."
@if command -v uv >/dev/null 2>&1; then \
uv run --python .venv/bin/python scripts/selenium_ui_tests.py \
--binary $(QRUSTY_DEBUG_BIN) --port $(SELENIUM_PORT) \
--selenium-hub $(SELENIUM_HUB) --qrusty-host $(QRUSTY_HOST); \
else \
. .venv/bin/activate && python scripts/selenium_ui_tests.py \
--binary $(QRUSTY_DEBUG_BIN) --port $(SELENIUM_PORT) \
--selenium-hub $(SELENIUM_HUB) --qrusty-host $(QRUSTY_HOST); \
fi
test-live-nodeclient: build
@echo "Running Node.js live client tests ..."
@node integrations/nodeclient/live_test.js \
--binary $(QRUSTY_DEBUG_BIN) --port $(NODE_LIVE_PORT)
test-integration-all: test test-live-pyclient test-live-nodeclient test-selenium smoke-test
@echo "All integration tests complete."