forked from alphagov/notifications-admin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile
196 lines (153 loc) · 7.01 KB
/
Makefile
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
.DEFAULT_GOAL := help
SHELL := /bin/bash
DATE = $(shell date +%Y-%m-%dT%H:%M:%S)
APP_VERSION_FILE = app/version.py
GIT_BRANCH ?= $(shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached")
GIT_COMMIT ?= $(shell git rev-parse HEAD 2> /dev/null || echo "")
CF_API ?= api.cloud.service.gov.uk
CF_ORG ?= govuk-notify
CF_SPACE ?= ${DEPLOY_ENV}
CF_HOME ?= ${HOME}
CF_APP ?= notify-admin
CF_MANIFEST_PATH ?= /tmp/manifest.yml
$(eval export CF_HOME)
NOTIFY_CREDENTIALS ?= ~/.notify-credentials
VIRTUALENV_ROOT := $(shell [ -z $$VIRTUAL_ENV ] && echo $$(pwd)/venv || echo $$VIRTUAL_ENV)
PYTHON_EXECUTABLE_PREFIX := $(shell test -d "$${VIRTUALENV_ROOT}" && echo "$${VIRTUALENV_ROOT}/bin/" || echo "")
## DEVELOPMENT
.PHONY: bootstrap
bootstrap: generate-version-file ## Set up everything to run the app
${PYTHON_EXECUTABLE_PREFIX}pip3 install -r requirements_for_test.txt
source $(HOME)/.nvm/nvm.sh && nvm install && npm ci --no-audit
. environment.sh; source $(HOME)/.nvm/nvm.sh && npm run build
.PHONY: bootstrap-with-asdf
bootstrap-with-asdf: generate-version-file ## Set up everything to run the app without nvm
${PYTHON_EXECUTABLE_PREFIX}pip3 install -r requirements_for_test.txt
npm ci --no-audit
. environment.sh; npm run build
.PHONY: bootstrap-with-docker
bootstrap-with-docker: generate-version-file ## Build the image to run the app in Docker
docker build -f docker/Dockerfile --target test -t notifications-admin .
.PHONY: watch-frontend
watch-frontend: ## Build frontend and watch for changes
. environment.sh; npm run watch
.PHONY: run-flask
run-flask: ## Run flask
. environment.sh && flask run -p 6012
.PHONY: npm-audit
npm-audit: ## Check for vulnerabilities in NPM packages
source $(HOME)/.nvm/nvm.sh && npm run audit
.PHONY: help
help:
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: virtualenv
virtualenv:
[ -z $$VIRTUAL_ENV ] && [ ! -d venv ] && python3 -m venv venv || true
.PHONY: upgrade-pip
upgrade-pip: virtualenv
${PYTHON_EXECUTABLE_PREFIX}pip3 install --upgrade pip
.PHONY: generate-version-file
generate-version-file: ## Generates the app version file
@echo -e "__git_commit__ = \"${GIT_COMMIT}\"\n__time__ = \"${DATE}\"" > ${APP_VERSION_FILE}
.PHONY: test
test: ## Run tests
ruff check .
black --check .
source $(HOME)/.nvm/nvm.sh && npm test
py.test -n auto --maxfail=10 tests/
.PHONY: fix-imports
fix-imports: ## Fix imports using ruff
ruff --fix --select=I .
.PHONY: freeze-requirements
freeze-requirements: ## create static requirements.txt
${PYTHON_EXECUTABLE_PREFIX}pip3 install --upgrade pip-tools
${PYTHON_EXECUTABLE_PREFIX}pip-compile requirements.in
.PHONY: bump-utils
bump-utils: # Bump notifications-utils package to latest version
${PYTHON_EXECUTABLE_PREFIX}python -c "from notifications_utils.version_tools import upgrade_version; upgrade_version()"
.PHONY: clean
clean:
rm -rf node_modules cache target ${CF_MANIFEST_PATH}
## DEPLOYMENT
.PHONY: check-env-vars
check-env-vars: ## Check mandatory environment variables
$(if ${DEPLOY_ENV},,$(error Must specify DEPLOY_ENV))
$(if ${DNS_NAME},,$(error Must specify DNS_NAME))
.PHONY: tst
tst: ## Set environment to test
$(eval export DEPLOY_ENV=preview)
$(eval export DNS_NAME="admin.test.notifynl.nl")
@true
.PHONY: acc
acc: ## Set environment to acc
$(eval export DEPLOY_ENV=staging)
$(eval export DNS_NAME="admin.acc.notifynl.nl")
@true
.PHONY: prod
prod: ## Set environment to production
$(eval export DEPLOY_ENV=production)
$(eval export DNS_NAME="admin.notifynl.nl")
@true
.PHONY: cf-login
cf-login: ## Log in to Cloud Foundry
$(if ${CF_USERNAME},,$(error Must specify CF_USERNAME))
$(if ${CF_PASSWORD},,$(error Must specify CF_PASSWORD))
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
@echo "Logging in to Cloud Foundry on ${CF_API}"
@cf login -a "${CF_API}" -u ${CF_USERNAME} -p "${CF_PASSWORD}" -o "${CF_ORG}" -s "${CF_SPACE}"
.PHONY: generate-manifest
generate-manifest:
$(if ${CF_APP},,$(error Must specify CF_APP))
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
$(if $(shell which gpg2), $(eval export GPG=gpg2), $(eval export GPG=gpg))
$(if ${GPG_PASSPHRASE_TXT}, $(eval export DECRYPT_CMD=echo -n $$$${GPG_PASSPHRASE_TXT} | ${GPG} --quiet --batch --passphrase-fd 0 --pinentry-mode loopback -d), $(eval export DECRYPT_CMD=${GPG} --quiet --batch -d))
@jinja2 --strict manifest.yml.j2 \
-D environment=${CF_SPACE} \
-D CF_APP=${CF_APP} \
--format=yaml \
<(${DECRYPT_CMD} ${NOTIFY_CREDENTIALS}/credentials/${CF_SPACE}/paas/environment-variables.gpg) 2>&1
.PHONY: upload-static ## Upload the static files to be served from S3
upload-static:
aws s3 cp --region eu-central-1 --recursive --cache-control max-age=315360000,immutable ./app/static s3://${DNS_NAME}-static
.PHONY: cf-deploy
cf-deploy: cf-target ## Deploys the app to Cloud Foundry
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
@cf app --guid notify-admin || exit 1
# cancel any existing deploys to ensure we can apply manifest (if a deploy is in progress you'll see ScaleDisabledDuringDeployment)
cf cancel-deployment ${CF_APP} || true
# generate manifest (including secrets) and write it to CF_MANIFEST_PATH (in /tmp/)
make -s CF_APP=${CF_APP} generate-manifest > ${CF_MANIFEST_PATH}
# reads manifest from CF_MANIFEST_PATH
$(if ${USE_DROPLETS},CF_APP=${CF_APP} CF_MANIFEST_PATH=${CF_MANIFEST_PATH} ./scripts/deploy.sh,CF_STARTUP_TIMEOUT=10 cf push ${CF_APP} --strategy=rolling -f ${CF_MANIFEST_PATH})
# delete old manifest file
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-deploy-prototype
cf-deploy-prototype: cf-target ## Deploys the first prototype to Cloud Foundry
make -s CF_APP=notify-admin-prototype generate-manifest > ${CF_MANIFEST_PATH}
cf push notify-admin-prototype --strategy=rolling -f ${CF_MANIFEST_PATH}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-deploy-prototype-2
cf-deploy-prototype-2: cf-target ## Deploys the second prototype to Cloud Foundry
make -s CF_APP=notify-admin-prototype-2 generate-manifest > ${CF_MANIFEST_PATH}
cf push notify-admin-prototype-2 --strategy=rolling -f ${CF_MANIFEST_PATH}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-rollback
cf-rollback: cf-target ## Rollbacks the app to the previous release
cf cancel-deployment ${CF_APP}
rm -f ${CF_MANIFEST_PATH}
.PHONY: cf-target
cf-target: check-env-vars
@cf target -o ${CF_ORG} -s ${CF_SPACE}
.PHONY: cf-failwhale-deployed
cf-failwhale-deployed:
@cf app notify-admin-failwhale --guid || (echo "notify-admin-failwhale is not deployed on ${CF_SPACE}" && exit 1)
.PHONY: enable-failwhale
enable-failwhale: cf-target cf-failwhale-deployed ## Enable the failwhale app and disable admin
@cf map-route notify-admin-failwhale ${DNS_NAME} --hostname www
@cf unmap-route notify-admin ${DNS_NAME} --hostname www
@echo "Failwhale is enabled"
.PHONY: disable-failwhale
disable-failwhale: cf-target cf-failwhale-deployed ## Disable the failwhale app and enable admin
@cf map-route notify-admin ${DNS_NAME} --hostname www
@cf unmap-route notify-admin-failwhale ${DNS_NAME} --hostname www
@echo "Failwhale is disabled"