Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
119 lines (97 loc) · 5.55 KB
/
Copy pathMakefile
File metadata and controls
119 lines (97 loc) · 5.55 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
# Default configuration
.DEFAULT_GOAL := build
IMAGE_NAME ?= vulnerability-tool
REGION ?= us-west-1
ACCOUNT_ID ?= 499665620971
ECR_REGISTRY = $(ACCOUNT_ID).dkr.ecr.$(REGION).amazonaws.com
ECR_URI = $(ECR_REGISTRY)/$(IMAGE_NAME)
CLF_COMPOSE = docker compose -f docker-compose.classifier.yml
INF_COMPOSE = docker compose -f docker-compose.inference.yml
# Allow `make test-split-e2e VI_INFERENCE_API_KEY=...` and an optional URL
# override without echoing the secret in the recipe itself.
export VI_INFERENCE_API_KEY
export VI_INFERENCE_API_URL
export AWS_PROFILE
export AWS_REGION
export GROQ_API_KEY
export OPENROUTER_API_KEY
.PHONY: build push build-test test test-api test-lambda test-split-e2e run-local-dashboard run-local-dashboard-with-lambda-remote-inference run-local-dashboard-with-lambda-local-inference help smoke-api results reset verify db down clean-test
# Credential-free dashboard gate: build, catalogues, full suite and real browser.
run-local-dashboard:
./scripts/test-local.sh
run-local-dashboard-with-lambda-remote-inference:
@VI_E2E_INFERENCE_MODE=remote ./scripts/test-split-e2e.sh
run-local-dashboard-with-lambda-local-inference:
@VI_E2E_INFERENCE_MODE=local ./scripts/test-split-e2e.sh
help:
@printf '%s\n' \
'make run-local-dashboard Dashboard build, French catalogue, full tests and browser/PDF checks; no models.' \
' Optional AWS_PROFILE=<profile> and/or exported OPENROUTER_API_KEY enable live provider checks; AWS_REGION defaults to eu-west-1.' \
' GitHub runs this same gate with controlled providers; live provider credentials are optional, never a release requirement.' \
'make run-local-dashboard-with-lambda-remote-inference Dashboard + Lambda locally; deployed HTTPS inference; requires VI_INFERENCE_API_KEY.' \
'make run-local-dashboard-with-lambda-local-inference Entire stack locally; Git LFS models (~13 GB) and >=20 GB Docker memory.' \
'All three are verification runs: they exit and clean up their isolated test data. Nothing is deployed.'
# Build the web image
build:
docker build -t $(IMAGE_NAME):latest .
# Login to ECR and push the image (deploy path - needs ECR access)
push:
aws ecr get-login-password --region $(REGION) | docker login --username AWS --password-stdin $(ECR_REGISTRY)
docker tag $(IMAGE_NAME):latest $(ECR_URI):latest
docker push $(ECR_URI):latest
# --- Local classification-split test (docker-compose.classifier.yml) ---
# All local: the classifier image is built from Dockerfile.classifier on the
# machine running the test. No ECR access required.
# Build the classifier image locally.
build-test:
$(CLF_COMPOSE) build
# Full local end-to-end in one command: build locally, migrate, seed the
# 10-article fixture (fixtures/test_articles.json) as unclassified rows, check
# Groq, classify, print results. Exits when the classifier finishes.
test: build-test
$(CLF_COMPOSE) up --abort-on-container-exit
# Run the inference-API contract test suite (inference_api/tests.py). Runs in
# the classifier container so no local Python setup is needed. Contract-level:
# no models are loaded, so it is fast. The tests_settings module is deliberately
# light (Django + requests + bs4 only), so it also runs in any local venv via:
# python manage.py test inference_api --settings=inference_api.tests_settings
test-api:
$(CLF_COMPOSE) run --rm classifier python manage.py test inference_api --settings=inference_api.tests_settings
# Run the ingestion Lambda test suite (inference client + drain loop + handler).
# Plain unittest with a fake DB and fake client - no Postgres/AWS/MediaCloud.
# Also runs in any local venv with requests installed:
# python -m unittest test_inference_client test_lambda_function
test-lambda:
$(CLF_COMPOSE) run --rm classifier python -m unittest test_inference_client test_lambda_function
# One command with two modes. With no key, run the entire stack locally. When
# VI_INFERENCE_API_KEY is supplied, keep Lambda/Postgres local and call the
# deployed HTTPS inference API (or VI_INFERENCE_API_URL when explicitly set).
test-split-e2e:
@printf '%s\n' 'Deprecated name: use make help to choose an explicit local/remote-inference command. Existing key-based selection is retained for compatibility.'
./scripts/test-split-e2e.sh
# Boot smoke: gunicorn-boot config.inference_wsgi under the real settings and
# assert the HTTP contract (/healthz, /readyz, auth, readiness gating). Warmup
# is skipped, so no models/GPU/DB are needed. Exits non-zero if the smoke fails.
smoke-api:
$(INF_COMPOSE) up --build --abort-on-container-exit --exit-code-from smoke; \
code=$$?; $(INF_COMPOSE) down; exit $$code
# Print the current classification state of every row.
results:
$(CLF_COMPOSE) run --rm classifier python manage.py show_results
# Reset the sample rows back to unclassified (reloads the fixture by pk).
reset:
$(CLF_COMPOSE) run --rm classifier python manage.py loaddata fixtures/test_articles.json
# Prove the blank-intent fix: count rows the classifier would still reprocess.
# Expect 0 after a run - genuine-Neutral rows are marked processed and settle.
verify:
$(CLF_COMPOSE) up -d db
$(CLF_COMPOSE) exec -T db psql -U vi -d vulnerability -c "SELECT count(*) AS would_reprocess FROM dashboard_medianarrative WHERE (strategic_intent IS NULL OR strategic_intent='') AND article_text IS NOT NULL AND article_text <> '' AND lower(article_text) <> 'no content available' AND ml_processed_at IS NULL;"
# Bring up just the local db.
db:
$(CLF_COMPOSE) up -d db
# Stop the test containers (keep the db data).
down:
$(CLF_COMPOSE) down
# Stop and wipe the test db.
clean-test:
$(CLF_COMPOSE) down -v