-
Notifications
You must be signed in to change notification settings - Fork 251
Expand file tree
/
Copy pathMakefile
More file actions
233 lines (186 loc) · 10.6 KB
/
Makefile
File metadata and controls
233 lines (186 loc) · 10.6 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
230
231
232
233
## Examples:
# make start - runs against main development `.env` file
# make PROD start - runs against `prod.env` config file
# make TEST e2e - runs tests
# make ENV_FILE=custom.env start - runs against parameters in `custom.env` config file
# make build-web-assets - build and extract web assets
SHELL=/bin/bash
E2E_RUN = cd e2e;
define parse_env_value
$(shell grep -e ^$(1) ${ENV_FILE} | awk -F'[=]' '{gsub(/ /,"");print $$2}')
endef
define parse_env_bool
$(if $(filter false,$(1)),false,true)
endef
# Default environment and settings (dev)
export ENV_FILE = .env
# Lazy evaluation of expensive environment parsing - only when needed
define get_env_vars
$(eval export TAG = $(call parse_env_value,TAG))
$(eval export GIT_HASH = $(shell git rev-parse --short HEAD))
$(eval POSTGRES_DOCKER_RAW = $(shell echo $(call parse_env_value,POSTGRES_DOCKER) | tr '[:upper:]' '[:lower:]'))
$(eval export POSTGRES_DOCKER = $(call parse_env_bool,$(POSTGRES_DOCKER_RAW)))
$(eval LOCAL_SERVICES_DOCKER_RAW = $(shell echo $(call parse_env_value,LOCAL_SERVICES_DOCKER) | tr '[:upper:]' '[:lower:]'))
$(eval export LOCAL_SERVICES_DOCKER = $(call parse_env_bool,$(LOCAL_SERVICES_DOCKER_RAW)))
$(eval USE_PRODCLONE_RAW = $(shell echo $(call parse_env_value,USE_PRODCLONE) | tr '[:upper:]' '[:lower:]'))
$(eval USE_PRODCLONE = $(call parse_env_bool,$(USE_PRODCLONE_RAW)))
$(eval export DB_INIT_MODE = $(if $(filter true,$(USE_PRODCLONE)),pdb,db))
$(eval export POSTGRES_VOLUME = $(if $(filter true,$(USE_PRODCLONE)),prodclone_data,postgres_data))
# Only set COMPOSE_FILE_ARGS if not already set by environment-specific targets
$(eval COMPOSE_FILE_ARGS ?= -f docker-compose.yml -f docker-compose.dev.yml)
$(eval COMPOSE_FILE_ARGS += $(if $(POSTGRES_DOCKER),--profile postgres,))
$(eval COMPOSE_FILE_ARGS += $(if $(LOCAL_SERVICES_DOCKER),--profile local-services,))
endef
# Support for detached mode
DETACH ?= false
DETACH_ARG = $(if $(filter true,$(DETACH)),-d,)
# Default compose file args - will be set lazily when needed
# Set up environment-specific values
define setup_env
$(eval ENV_FILE = $(1))
$(eval TAG = $(call parse_env_value,TAG))
$(eval POSTGRES_DOCKER_RAW = $(shell echo $(call parse_env_value,POSTGRES_DOCKER) | tr '[:upper:]' '[:lower:]'))
$(eval POSTGRES_DOCKER = $(call parse_env_bool,$(POSTGRES_DOCKER_RAW)))
$(eval LOCAL_SERVICES_DOCKER_RAW = $(shell echo $(call parse_env_value,LOCAL_SERVICES_DOCKER) | tr '[:upper:]' '[:lower:]'))
$(eval LOCAL_SERVICES_DOCKER = $(call parse_env_bool,$(LOCAL_SERVICES_DOCKER_RAW)))
$(eval USE_PRODCLONE_RAW = $(shell echo $(call parse_env_value,USE_PRODCLONE) | tr '[:upper:]' '[:lower:]'))
$(eval USE_PRODCLONE = $(call parse_env_bool,$(USE_PRODCLONE_RAW)))
$(eval DB_INIT_MODE = $(if $(filter true,$(USE_PRODCLONE)),pdb,db))
$(eval POSTGRES_VOLUME = $(if $(filter true,$(USE_PRODCLONE)),prodclone_data,postgres_data))
$(eval COMPOSE_FILE_ARGS = $(2))
$(eval COMPOSE_FILE_ARGS += $(if $(POSTGRES_DOCKER),--profile postgres,))
$(eval COMPOSE_FILE_ARGS += $(if $(LOCAL_SERVICES_DOCKER),--profile local-services,))
endef
# Function to open psql shell
define psql_shell
@docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} exec postgres \
psql -U $(call parse_env_value,POSTGRES_USER) \
-d $(call parse_env_value,POSTGRES_DB)
endef
PROD:
$(call setup_env,prod.env,-f docker-compose.yml)
TEST:
$(call setup_env,test.env,-f docker-compose.test.yml)
echo_vars:
$(call get_env_vars)
@echo ENV_FILE=${ENV_FILE}
@echo POSTGRES_DOCKER=${POSTGRES_DOCKER}
@echo LOCAL_SERVICES_DOCKER=${LOCAL_SERVICES_DOCKER}
@echo USE_PRODCLONE=${USE_PRODCLONE}
@echo DB_INIT_MODE=${DB_INIT_MODE}
@echo POSTGRES_VOLUME=${POSTGRES_VOLUME}
@echo TAG=${TAG}
pull: echo_vars ## Pull most recent Docker container builds (nightlies)
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} pull
start: echo_vars ## Start all Docker containers
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG}
stop: echo_vars ## Stop all Docker containers
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} down
rm-containers: echo_vars ## Remove Docker containers where (polis_tag="${TAG}")
@echo 'removing filtered containers (polis_tag="${TAG}")'
@-docker rm -f $(shell docker ps -aq --filter "label=polis_tag=${TAG}")
rm-volumes: echo_vars ## Remove Docker volumes where (polis_tag="${TAG}")
@echo 'removing filtered volumes (polis_tag="${TAG}")'
@-docker volume rm -f $(shell docker volume ls -q --filter "label=polis_tag=${TAG}")
rm-images: echo_vars ## Remove Docker images where (polis_tag="${TAG}")
@echo 'removing filtered images (polis_tag="${TAG}")'
@-docker rmi -f $(shell docker images -q --filter "label=polis_tag=${TAG}")
rm-ALL: rm-containers rm-volumes rm-images ## Remove Docker containers, volumes, and images (including db) where (polis_tag="${TAG}")
@echo Done.
hash: ## Show current short hash
@echo Git hash: ${GIT_HASH}
build: echo_vars ## [Re]Build all Docker containers
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} build
build-no-cache: echo_vars ## Build all Docker containers without cache
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} build --no-cache
start-recreate: echo_vars ## Start all Docker containers with recreated environments
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG} --force-recreate
start-rebuild: echo_vars ## Start all Docker containers, [re]building as needed
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG} --build
start-FULL-REBUILD: echo_vars stop rm-ALL ## Remove and restart all Docker containers, volumes, and images (including db), as with rm-ALL
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} build --no-cache
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG}
rebuild-web: echo_vars ## Rebuild and restart just the file-server container and its static assets, and client-participation-alpha
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG} --build --force-recreate file-server client-participation-alpha
rebuild-server: echo_vars ## Rebuild and restart just the server container
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG} --build --force-recreate server
rebuild-delphi: echo_vars ## Rebuild and restart just the delphi container
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG} --build --force-recreate delphi
build-web-assets: ## Build and extract static web assets for cloud deployment to `build` dir
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} create --build --force-recreate file-server
$(MAKE) extract-web-assets
extract-web-assets: ## Extract static web assets from file-server to `build` dir
/bin/rm -rf build
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} cp file-server:/app/build/ build
generate-jwt-keys: ## Generate JWT keys for participant authentication
@echo "Generating JWT keys for participant authentication..."
@if [ -f server/keys/jwt-private.pem ]; then \
echo "JWT keys already exist. Use 'make regenerate-jwt-keys' to overwrite."; \
else \
node server/scripts/generate-jwt-keys.js; \
fi
regenerate-jwt-keys: ## Regenerate JWT keys (overwrites existing)
@echo "Regenerating JWT keys for participant authentication..."
@rm -f server/keys/jwt-private.pem server/keys/jwt-public.pem
@node server/scripts/generate-jwt-keys.js
# Database refresh helpers
refresh-db: echo_vars ## Stop stack, drop current DB volume (${POSTGRES_VOLUME}), and restart (re-inits from migrations or prodclone.dump)
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} down --remove-orphans
@echo 'removing any containers still referencing volume ${POSTGRES_VOLUME}'
@-docker rm -f $$(docker ps -aq --filter "volume=${COMPOSE_PROJECT_NAME}_${POSTGRES_VOLUME}") >/dev/null 2>&1 || true
@echo 'removing database volume ${POSTGRES_VOLUME} (polis_tag=${TAG})'
@-docker volume rm -f $(shell docker volume ls -q --filter "label=polis_tag=${TAG}" --filter "name=${POSTGRES_VOLUME}")
@echo 'rebuilding postgres image using Dockerfile-${DB_INIT_MODE} (USE_PRODCLONE=${USE_PRODCLONE})'
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} build --no-cache postgres
docker compose ${COMPOSE_FILE_ARGS} --env-file ${ENV_FILE} up ${DETACH_ARG}
refresh-prodclone: ## Force prodclone mode, drop prodclone volume, and restart from prodclone.dump
$(MAKE) USE_PRODCLONE=true refresh-db
refresh-devdb: ## Force dev DB mode (migrations), drop postgres_data volume, and restart
$(MAKE) USE_PRODCLONE=false refresh-db
e2e-install: e2e/node_modules ## Install Cypress E2E testing tools
$(E2E_RUN) npm install
e2e-run: ## Run E2E tests except those which require 3rd party services
$(E2E_RUN) npm run test
e2e-run-all: ## Run E2E tests: all
$(E2E_RUN) npm run test:all
e2e-run-interactive: ## Run E2E tests: interactively
$(E2E_RUN) npx cypress open
psql-shell: echo_vars ## Open psql shell for the default environment
@if [ "${POSTGRES_DOCKER}" != "true" ]; then \
echo "PostgreSQL is not running in Docker. Exiting."; \
exit 1; \
fi
$(call psql_shell)
start-prodclone: ## Start with production clone database (USE_PRODCLONE=true)
$(MAKE) USE_PRODCLONE=true start
# Helpful CLI shortcuts
rbs: start-rebuild
%:
@true
.PHONY: help start stop \
build-no-cache build-web-assets \
e2e-install e2e-run e2e-run-all e2e-run-interactive \
extract-web-assets generate-jwt-keys hash psql-shell pull \
rebuild-delphi rebuild-server rebuild-web
refresh-db refresh-devdb refresh-prodclone regenerate-jwt-keys \
rm-ALL rm-containers rm-images rm-volumes \
start-FULL-REBUILD start-prodclone start-rebuild start-recreate
help: ## Show this help message
@echo 'Usage: make <command>'
@echo
@echo 'where <command> can be one or more of the following:'
@echo
@grep -E '^[a-zA-Z0-9_-]+:.*##' $(MAKEFILE_LIST) | \
sed 's/:.*##/|/' | \
awk -F'|' '{printf "\033[36m%-24s\033[0m %s\n", $$1, $$2}'
@echo
@echo 'By default, runs against the configuration specified in `.env` file (see `example.env` for a template).'
@echo
@echo 'As specified above, the config file can be overridden using `PROD` or `TEST` commands, and a custom config file'
@echo 'can also be specified by explicitly setting the `ENV_FILE` variable, like: `make ENV_FILE=custom.env <command>`.'
@echo
@echo 'To run docker compose in detached mode, set DETACH=true, like: `make DETACH=true start`.'
@echo
@echo 'Note that different values of `TAG` specified in your config file will result in different container and asset'
@echo 'builds, which can be useful for (e.g.) testing out features while preserving mainline branch builds.'
.DEFAULT_GOAL := help