-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
180 lines (140 loc) · 8.57 KB
/
Copy pathMakefile
File metadata and controls
180 lines (140 loc) · 8.57 KB
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
.PHONY: up down stack-dev stack-prod stack-prod-shaped-local stack-prod-shaped-local-smoke produce api tools test quality lint format build deploy-dev wait-healthy clean setup demo demo-local pipeline flink-local load-test benchmark bench perf-plot trivy-policy
# ── Setup ─────────────────────────────────────────────────────────
setup:
python -m venv .venv
.venv/Scripts/pip install -e ".[dev,cloud]" 2>/dev/null || .venv/bin/pip install -e ".[dev,cloud]"
.venv/Scripts/pip install -e "./sdk" 2>/dev/null || .venv/bin/pip install -e "./sdk"
.venv/Scripts/pip install -e "./integrations[mcp]" 2>/dev/null || .venv/bin/pip install -e "./integrations[mcp]"
@echo "Setup complete. Activate with: source .venv/Scripts/activate (Windows) or source .venv/bin/activate (Unix)"
# ── Local Development ─────────────────────────────────────────────
up:
docker compose up -d
@echo "Starting services... Use 'make wait-healthy' to wait for readiness."
down:
docker compose down -v
stack-dev:
docker compose up -d
@echo "Dev stack is starting from docker-compose.yml"
# Renamed from `stack-prod` (audit F-09): the old name read as "the production
# stack" for a topology that has no production security posture. The stack is
# unchanged; what it calls itself is not.
stack-prod-shaped-local:
docker compose -f docker-compose.prod.yml up -d
@echo "Production-SHAPED LOCAL stack is starting from docker-compose.prod.yml."
@echo "It is a demo, not a production recipe - the production path is Helm"
@echo "with helm/agentflow/values-production.yaml (docs/deployment.md)."
@echo "Prove it works: make stack-prod-shaped-local-smoke"
stack-prod-shaped-local-smoke:
python scripts/wait_for_http.py --url http://localhost:8000/health/ready --timeout 180 --interval 3 --label agentflow-api
python scripts/compose_prod_shaped_smoke.py
stack-prod:
@echo "stack-prod was renamed to stack-prod-shaped-local: that stack is a"
@echo "production-shaped LOCAL demo, and the old name invited operators to"
@echo "read it as a production recipe (audit F-09). The production path is"
@echo "Helm with helm/agentflow/values-production.yaml - see docs/deployment.md."
@exit 1
wait-healthy:
@echo "Waiting for services..."
python scripts/wait_for_http.py --url http://localhost:8081/overview --timeout 60 --interval 2 --label Flink
python scripts/wait_for_http.py --url http://localhost:9000/minio/health/live --timeout 60 --interval 2 --label MinIO
@echo "Service UIs: http://localhost:8081 (Flink), http://localhost:9001 (MinIO console)"
produce:
python -m agentflow_runtime.ingestion.producers.event_producer
api:
docker compose up -d redis
DUCKDB_PATH=agentflow_demo.duckdb uvicorn agentflow_runtime.serving.api.main:app --host 0.0.0.0 --port 8000 --reload
tools:
python scripts/export_openapi.py
# ── End-to-End Demos ─────────────────────────────────────────────
demo-local:
python scripts/demo_local.py
demo:
@echo "=== AgentFlow Demo ==="
@echo "Step 0: Starting Redis + ClickHouse (serving store, ADR 0006)..."
docker compose up -d redis clickhouse
python scripts/wait_for_clickhouse.py
@echo ""
@echo "Step 0.5: Provisioning the serving store (schema + demo rows)..."
@echo " The API does not create or seed a store on boot any more (audit P0-2)."
@echo " A real deployment runs this same command WITHOUT --seed, from a job."
DUCKDB_PATH=agentflow_demo.duckdb python -m agentflow_runtime.serving.provision --schema --seed
@echo ""
@echo "Step 1: Seeding 500 events through the full pipeline..."
python -m agentflow_runtime.processing.local_pipeline --burst 500
@echo ""
@echo "Step 1.5: Seeding benchmark fixture rows into agentflow_demo.duckdb..."
python -c "from pathlib import Path; from scripts.run_benchmark import seed_benchmark_fixtures; seed_benchmark_fixtures(Path('agentflow_demo.duckdb'))"
@echo ""
@echo "Step 2: Starting API server (Ctrl+C to stop)..."
@echo " Open http://localhost:8000/docs"
@echo " Try: curl http://localhost:8000/v1/metrics/revenue?window=24h"
@echo " Try: curl http://localhost:8000/v1/entity/user/USR-10001"
@echo " Try: curl http://localhost:8000/v1/health"
AGENTFLOW_AUTH_DISABLED=true DUCKDB_PATH=agentflow_demo.duckdb uvicorn agentflow_runtime.serving.api.main:app --host 0.0.0.0 --port 8000
pipeline:
python -m agentflow_runtime.processing.local_pipeline --eps 10
flink-local:
ifeq ($(OS),Windows_NT)
powershell -ExecutionPolicy Bypass -File scripts/run_flink_local.ps1
else
bash scripts/run_flink_local.sh
endif
# ── Testing ───────────────────────────────────────────────────────
test:
pytest tests/ -v --tb=short --ignore=tests/load
test-unit:
pytest tests/unit/ -v --tb=short
test-integration:
pytest tests/integration/ -v --tb=short -m integration
quality:
python -m agentflow_runtime.quality.validators.semantic_validator --check-all
# ── Load Testing ──────────────────────────────────────────────────
load-test:
@echo "Starting load test (50 users, 60s). API must be running on :8000"
python tests/load/run_load_test.py --host http://localhost:8000
benchmark:
python scripts/run_benchmark.py
bench:
python scripts/run_benchmark.py
perf-plot:
python -m pip install --quiet "plotly>=5,<7"
python scripts/plot_perf_history.py
# ── Code Quality ──────────────────────────────────────────────────
lint:
ruff check src/ tests/ scripts/ sdk/
ruff format --check src/ tests/ scripts/ sdk/
mypy src/
format:
ruff format src/ tests/ scripts/ sdk/
ruff check --fix src/ tests/ scripts/ sdk/
# ── Build & Deploy ────────────────────────────────────────────────
build:
docker compose build
# Per-environment state keys (audit P2-4): the backend block carries no key,
# so init MUST name the environment's own state object — a bare
# `terraform init` fails instead of silently sharing one state across envs.
deploy-dev:
cd infrastructure/terraform && terraform init -backend-config="key=env/dev/terraform.tfstate" && terraform plan -var-file=dev.tfvars
deploy-prod:
@test -f infrastructure/terraform/environments/prod.tfvars || { \
echo "infrastructure/terraform/environments/prod.tfvars is operator-provided"; \
echo "(copy prod.tfvars.example and fill real values; never commit it)."; \
exit 1; }
cd infrastructure/terraform && terraform init -backend-config="key=env/production/terraform.tfstate" && terraform plan -var-file=environments/prod.tfvars
@echo "Review the plan above. Run 'terraform apply' manually to proceed."
# ── Cleanup ───────────────────────────────────────────────────────
clean:
python -c "import shutil, pathlib; [shutil.rmtree(p) for p in pathlib.Path('.').rglob('__pycache__')]" 2>/dev/null || true
python -c "import shutil, pathlib; [shutil.rmtree(p) for p in pathlib.Path('.').rglob('.pytest_cache')]" 2>/dev/null || true
python -c "import shutil; [shutil.rmtree(p, True) for p in ['.coverage', 'htmlcov', 'dist', 'build']]" 2>/dev/null || true
python -c "import pathlib; [p.unlink() for p in pathlib.Path('.').glob('*.duckdb*')]" 2>/dev/null || true
# ── Image scan policy ─────────────────────────────────────────────
# Evaluate locally generated Trivy JSON reports. This target does not
# build or scan images; a missing report or nonzero evaluator exit fails.
TRIVY_API_REPORT ?= .artifacts/trivy/trivy-api.json
TRIVY_FLINK_REPORT ?= .artifacts/trivy/trivy-flink.json
TRIVY_API_POLICY_SUMMARY ?= .artifacts/trivy/trivy-api-policy.json
TRIVY_FLINK_POLICY_SUMMARY ?= .artifacts/trivy/trivy-flink-policy.json
trivy-policy:
python scripts/evaluate_trivy_policy.py --report $(TRIVY_API_REPORT) --waivers security/trivy-waivers.json --scope api-runtime --output $(TRIVY_API_POLICY_SUMMARY)
python scripts/evaluate_trivy_policy.py --report $(TRIVY_FLINK_REPORT) --waivers security/trivy-waivers.json --scope flink-runtime --output $(TRIVY_FLINK_POLICY_SUMMARY)