-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
229 lines (187 loc) · 10.4 KB
/
Copy pathMakefile
File metadata and controls
229 lines (187 loc) · 10.4 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
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
#!make
# An empty `include` is a silent no-op, so without this every target still runs,
# with every variable blank -- including the host paths of the database and the
# object storage.
ifeq ($(strip $(ENV_FILE_PATH)),)
$(error ENV_FILE_PATH is not set. Pass one, e.g. make ENV_FILE_PATH=local.env <target>. On the production host see Makefile.infra)
endif
ifeq ($(wildcard $(ENV_FILE_PATH)),)
$(error ENV_FILE_PATH=$(ENV_FILE_PATH) does not exist)
endif
include ${ENV_FILE_PATH}
export $(shell sed 's/=.*//' ${ENV_FILE_PATH})
export BUILD_COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
# Reset
Color_Off=\033[0m # Text Reset
# Regular Colors
Black=\033[0;30m # Black
Red=\033[0;31m # Red
Green=\033[0;32m # Green
Yellow=\033[0;33m # Yellow
Blue=\033[0;34m # Blue
Purple=\033[0;35m # Purple
Cyan=\033[0;36m # Cyan
White=\033[0;37m # White
# Background
On_Black=\033[40m # Black
On_Red=\033[41m # Red
On_Green=\033[42m # Green
On_Yellow=\033[43m # Yellow
On_Blue=\033[44m # Blue
On_Purple=\033[45m # Purple
On_Cyan=\033[46m # Cyan
On_White=\033[47m # White
# Docker commands
docker-build:
time docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml build
docker-run:
@echo "${On_Green}Starting docker containers${Color_Off}"
time docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml up -d
docker-run-db:
@echo "${On_Green}Starting docker containers${Color_Off}"
time docker compose -f docker-compose-database.yaml up -d
docker-stop:
@echo "${On_Green}Stoping docker containers${Color_Off}"
time docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml stop
docker-down:
@echo "${On_Green}Downing docker containers${Color_Off}"
time docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml down
docker-prune:
@echo "${On_Green}Images prune${Color_Off}"
time docker image prune -a -f
observability-run: # Usage: make ENV_FILE_PATH=<decrypted-env> observability-run
@echo "${On_Green}Starting Prometheus and Grafana${Color_Off}"
docker compose -f docker-compose-observability.yaml up -d
observability-down:
@echo "${On_Green}Stopping Prometheus and Grafana${Color_Off}"
docker compose -f docker-compose-observability.yaml down
observability-check:
@echo "${On_Green}Validating the Prometheus configuration and alert rules${Color_Off}"
docker run --rm -v $(PWD)/infrastructure/prometheus:/etc/prometheus \
-w /etc/prometheus --entrypoint promtool prom/prometheus:v2.53.0 \
check config prometheus.yml
docker run --rm -v $(PWD)/infrastructure/prometheus:/etc/prometheus \
-w /etc/prometheus --entrypoint promtool prom/prometheus:v2.53.0 \
test rules alerts_test.yml
docker-deployment: docker-build docker-stop docker-down docker-run docker-prune
docker-deployment-no-prune: docker-build docker-stop docker-down docker-run
# One instance at a time, and without touching the database, the object storage
# or TUSd. `--wait` returns the moment the healthcheck passes — the timeout is a
# ceiling, not a duration — which is about two seconds.
#
# UPSTREAM_RECOVERY is not waiting for the container. nginx ejects an instance
# for `fail_timeout` after a failure, so replacing the second one before the
# first is retried leaves it with nowhere to send. Measured with a request every
# 200ms: 10 failures without this pause, 0 with it. It must stay above the
# fail_timeout in infrastructure/nginx/datamap.conf.
UPSTREAM_RECOVERY ?= 7
docker-deployment-rolling: docker-build
@echo "${On_Green}Replacing the first instance${Color_Off}"
docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml \
up -d --no-deps --force-recreate --wait --wait-timeout 180 gatekeeper
@echo "${On_Green}Waiting ${UPSTREAM_RECOVERY}s for nginx to retry it${Color_Off}"
sleep ${UPSTREAM_RECOVERY}
@echo "${On_Green}Replacing the second instance${Color_Off}"
docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml \
up -d --no-deps --force-recreate --wait --wait-timeout 180 gatekeeper_b
@echo "${On_Green}Bringing up anything else that changed${Color_Off}"
docker compose -f docker-compose-infrastructure.yaml -f docker-compose-database.yaml \
up -d --wait --wait-timeout 180
# Python commands
python-env:
@echo "${On_White}\rAtention!${Color_Off}"
@echo "Use vscode and create the environment locall to run the application"
@echo "Check more about it on https://code.visualstudio.com/docs/python/environments#_creating-environments"
python-pip-install:
pip3 install -r requirements.txt
python-pip-freeze:
pip3 freeze > requirements.txt
python-run:
uvicorn app.main:fastAPIApp --host 0.0.0.0 --port 9092 --reload --no-access-log
# Database commands
db-upgrade:
python3 -m alembic upgrade head
db-create-migration: # Usage: make MESSAGE="Add tenancy column to datasets" db-create-migration
python3 -m alembic revision --autogenerate -m "$(MESSAGE)"
db-downgrade:
python3 -m alembic downgrade -1
# Integration Test commands
integration-test-build:
@echo "${On_Green}Building integration test containers${Color_Off}"
docker compose -f docker-compose-integration-test.yaml build
integration-test-up:
@echo "${On_Green}Starting integration test containers${Color_Off}"
docker compose -f docker-compose-integration-test.yaml up -d
@echo "Waiting for services to be ready..."
@timeout 60 bash -c 'until curl -s http://localhost:9094/api/v1/health-check/ > /dev/null; do sleep 2; done' || echo "Gatekeeper may not be ready"
@timeout 30 bash -c 'until curl -s http://localhost:8083/__admin/health > /dev/null; do sleep 1; done' || echo "WireMock may not be ready"
@echo "${On_Green}Integration test containers ready${Color_Off}"
@echo "Services available:"
@echo " - Gatekeeper API: http://localhost:9094"
@echo " - WireMock (DOI): http://localhost:8083"
@echo " - MinIO Console: http://localhost:9003"
@echo " - MinIO API: http://localhost:9002"
@echo " - PostgreSQL: localhost:5433"
@echo " - PGAdmin: http://localhost:5051"
@echo " - TUSd: http://localhost:1081"
integration-test-down: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-down
@echo "${On_Green}Stopping integration test containers${Color_Off}"
docker compose -f docker-compose-integration-test.yaml down
@echo "${On_Green}Integration test containers stopped${Color_Off}"
integration-test-clean: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-clean
@echo "${On_Green}Cleaning integration test containers and volumes${Color_Off}"
docker compose -f docker-compose-integration-test.yaml down -v
@echo "${On_Green}Integration test containers and volumes cleaned${Color_Off}"
# No --tail: 50 lines is under a second of a 250-test run.
integration-test-logs: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-logs
@echo "${On_Green}Showing integration test container logs${Color_Off}"
docker compose -f docker-compose-integration-test.yaml logs --timestamps --no-color
integration-test-restart: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-restart
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-down
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-up
integration-test-run: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-run
@echo "${On_Green}Running integration tests${Color_Off}"
pytest tests/integration/ -v
integration-test-run-specific: # Usage: make ENV_FILE_PATH=integration-test.env TEST_PATH=tests/integration/test_dataset_snapshot.py integration-test-run-specific
@echo "${On_Green}Running specific integration test: ${TEST_PATH}${Color_Off}"
pytest ${TEST_PATH} -v
# Complete integration test workflow
# Unit test commands
unit-test: # Usage: make ENV_FILE_PATH=local.env unit-test (fast unit tests, minimal env needed)
@echo "${On_Green}Running unit tests (service/adapter layers only)${Color_Off}"
@export $$(cat $(ENV_FILE_PATH) | xargs) && pytest -c pytest-unit.ini
unit-test-file: # Usage: make ENV_FILE_PATH=local.env TEST_FILE=app/service/doi_test.py unit-test-file
@echo "${On_Green}Running specific unit test file: ${TEST_FILE}${Color_Off}"
@export $$(cat $(ENV_FILE_PATH) | xargs) && pytest ${TEST_FILE} -v
integration-test-full: # Usage: make ENV_FILE_PATH=integration-test.env integration-test-full
@echo "${On_Green}Running complete integration test workflow${Color_Off}"
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-down
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-build
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-up
@echo "Running database migrations inside container..."
@docker exec datamap_gatekeeper_test_integration python3 -m alembic upgrade head || echo "Migration may have failed - continuing with tests"
@echo "Seeding test data..."
@docker exec datamap_postgres_test_integration psql -U gk_admin -d gatekeeper_db -f /tmp/seed_clients.sql || echo "Seed may have failed - continuing with tests"
@echo "Running integration tests..."
@$(MAKE) ENV_FILE_PATH=$(ENV_FILE_PATH) integration-test-run
@$(MAKE) integration-test-down
# Script commands
run-script: # Usage: make ENV_FILE_PATH=local.env SCRIPT=generate_legacy_snapshots run-script
@echo "${On_Green}Running script: ${SCRIPT}${Color_Off}"
python -m scripts.$(SCRIPT)
run-script-dry: # Usage: make ENV_FILE_PATH=local.env SCRIPT=generate_legacy_snapshots run-script-dry
@echo "${On_Green}Running script (dry run): ${SCRIPT}${Color_Off}"
python -m scripts.$(SCRIPT) --dry-run
# Legacy snapshot generation shortcuts
generate-snapshots: # Usage: make ENV_FILE_PATH=local.env generate-snapshots
@echo "${On_Green}Generating all legacy snapshots${Color_Off}"
python -m scripts.generate_legacy_snapshots
generate-snapshots-dry: # Usage: make ENV_FILE_PATH=local.env generate-snapshots-dry
@echo "${On_Green}Generating all legacy snapshots (dry run)${Color_Off}"
python -m scripts.generate_legacy_snapshots --dry-run
generate-snapshot-single: # Usage: make ENV_FILE_PATH=local.env DATASET_ID=<uuid> generate-snapshot-single
@echo "${On_Green}Generating snapshot for dataset: ${DATASET_ID}${Color_Off}"
python -m scripts.generate_legacy_snapshots --dataset-id $(DATASET_ID)
generate-snapshot-single-dry: # Usage: make ENV_FILE_PATH=local.env DATASET_ID=<uuid> generate-snapshot-single-dry
@echo "${On_Green}Generating snapshot for dataset (dry run): ${DATASET_ID}${Color_Off}"
python -m scripts.generate_legacy_snapshots --dry-run --dataset-id $(DATASET_ID)