2016-08-16 17:51:52 +01:00
|
|
|
.DEFAULT_GOAL := help
|
|
|
|
|
SHELL := /bin/bash
|
|
|
|
|
DATE = $(shell date +%Y-%m-%d:%H:%M:%S)
|
|
|
|
|
|
|
|
|
|
APP_VERSION_FILE = app/version.py
|
|
|
|
|
|
2016-08-26 16:18:04 +01:00
|
|
|
GIT_BRANCH ?= $(shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached")
|
2025-04-14 15:45:03 -04:00
|
|
|
GIT_COMMIT ?= $(shell git rev-parse HEAD 2> /dev/null || echo "")
|
|
|
|
|
GIT_HOOKS_PATH ?= $(shell git config --global core.hooksPath || echo "")
|
2016-08-16 17:51:52 +01:00
|
|
|
|
2020-03-03 11:51:50 +00:00
|
|
|
## DEVELOPMENT
|
|
|
|
|
|
2025-01-06 07:37:21 -08:00
|
|
|
## TODO this line should go under `make generate-version-file`
|
|
|
|
|
## poetry self update
|
|
|
|
|
|
2021-02-17 17:22:45 +00:00
|
|
|
.PHONY: bootstrap
|
2022-10-26 14:05:37 +00:00
|
|
|
bootstrap: ## Set up everything to run the app
|
2022-10-26 15:26:53 -04:00
|
|
|
make generate-version-file
|
2025-05-29 11:14:00 -07:00
|
|
|
poetry sync --no-root
|
2023-11-17 09:14:12 -05:00
|
|
|
poetry run pre-commit install
|
2021-02-18 15:19:40 +00:00
|
|
|
createdb notification_api || true
|
2024-04-24 16:11:03 -04:00
|
|
|
createdb test_notification_api || true
|
2023-08-31 11:00:55 -07:00
|
|
|
(poetry run flask db upgrade) || true
|
2021-02-17 17:22:45 +00:00
|
|
|
|
2025-04-14 16:16:56 -04:00
|
|
|
.PHONY: bootstrap-with-git-hooks
|
|
|
|
|
bootstrap-with-git-hooks: ## Sets everything up and accounts for pre-existing git hooks
|
2022-10-26 15:26:53 -04:00
|
|
|
make generate-version-file
|
2025-05-29 11:13:36 -07:00
|
|
|
poetry sync --no-root
|
2025-04-14 15:45:03 -04:00
|
|
|
git config --global --unset-all core.hooksPath
|
2023-11-17 09:14:12 -05:00
|
|
|
poetry run pre-commit install
|
2025-04-14 15:45:03 -04:00
|
|
|
git config --global core.hookspath "${GIT_HOOKS_PATH}"
|
2021-02-18 15:19:40 +00:00
|
|
|
createdb notification_api || true
|
2024-04-24 16:11:03 -04:00
|
|
|
createdb test_notification_api || true
|
2023-08-31 11:00:55 -07:00
|
|
|
(poetry run flask db upgrade) || true
|
2021-02-17 17:22:45 +00:00
|
|
|
|
2022-02-24 17:11:46 +00:00
|
|
|
.PHONY: bootstrap-with-docker
|
|
|
|
|
bootstrap-with-docker: ## Build the image to run the app in Docker
|
|
|
|
|
docker build -f docker/Dockerfile -t notifications-api .
|
|
|
|
|
|
2022-11-01 09:54:31 -04:00
|
|
|
.PHONY: run-procfile
|
|
|
|
|
run-procfile:
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run honcho start -f Procfile.dev
|
2022-11-01 09:54:31 -04:00
|
|
|
|
2025-01-23 13:41:13 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
.PHONY: tada
|
|
|
|
|
tada:
|
|
|
|
|
poetry run isort .
|
|
|
|
|
poetry run black .
|
|
|
|
|
poetry run flake8 .
|
|
|
|
|
|
2023-08-07 10:11:24 -07:00
|
|
|
.PHONY: avg-complexity
|
|
|
|
|
avg-complexity:
|
|
|
|
|
echo "*** Shows average complexity in radon of all code ***"
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run radon cc ./app -a -na
|
2023-08-07 10:11:24 -07:00
|
|
|
|
|
|
|
|
.PHONY: too-complex
|
|
|
|
|
too-complex:
|
2023-08-07 10:59:51 -07:00
|
|
|
echo "*** Shows code that got a rating of C, D or F in radon ***"
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run radon cc ./app -a -nc
|
2023-08-07 10:11:24 -07:00
|
|
|
|
2021-02-17 16:49:05 +00:00
|
|
|
.PHONY: run-flask
|
2025-04-09 16:56:42 -07:00
|
|
|
run-flask:
|
2025-04-16 17:43:10 -04:00
|
|
|
poetry run newrelic-admin run-program flask run -p 6011 --host=0.0.0.0
|
2021-02-17 16:49:05 +00:00
|
|
|
|
|
|
|
|
.PHONY: run-celery
|
2022-06-13 13:45:07 -07:00
|
|
|
run-celery: ## Run celery, TODO remove purge for staging/prod
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run celery -A run_celery.notify_celery purge -f
|
|
|
|
|
poetry run newrelic-admin run-program celery \
|
2021-02-17 16:49:05 +00:00
|
|
|
-A run_celery.notify_celery worker \
|
|
|
|
|
--pidfile="/tmp/celery.pid" \
|
|
|
|
|
--loglevel=INFO \
|
2025-07-29 16:28:00 -04:00
|
|
|
--pool=gevent
|
|
|
|
|
--concurrency=20
|
2021-02-17 16:49:05 +00:00
|
|
|
|
2023-08-08 11:03:50 -07:00
|
|
|
|
|
|
|
|
.PHONY: dead-code
|
2024-06-19 13:00:54 -07:00
|
|
|
dead-code: ## Use 60 to look for suspected dead code
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run vulture ./app --min-confidence=100
|
2023-08-08 11:03:50 -07:00
|
|
|
|
2021-02-17 16:49:05 +00:00
|
|
|
.PHONY: run-celery-beat
|
2021-04-27 12:00:53 +01:00
|
|
|
run-celery-beat: ## Run celery beat
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run celery \
|
2022-06-13 13:45:07 -07:00
|
|
|
-A run_celery.notify_celery beat \
|
|
|
|
|
--loglevel=INFO
|
2021-02-17 16:49:05 +00:00
|
|
|
|
2023-05-09 21:54:22 -04:00
|
|
|
.PHONY: cloudgov-user-report
|
2023-05-09 21:44:15 -04:00
|
|
|
cloudgov-user-report:
|
2023-08-31 11:00:55 -07:00
|
|
|
@poetry run python -m terraform.ops.cloudgov_user_report
|
2023-05-09 21:44:15 -04:00
|
|
|
|
2016-08-16 17:51:52 +01:00
|
|
|
.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: generate-version-file
|
|
|
|
|
generate-version-file: ## Generates the app version file
|
2020-04-21 15:57:01 +01:00
|
|
|
@echo -e "__git_commit__ = \"${GIT_COMMIT}\"\n__time__ = \"${DATE}\"" > ${APP_VERSION_FILE}
|
2016-08-16 17:51:52 +01:00
|
|
|
|
|
|
|
|
.PHONY: test
|
2023-01-17 14:08:17 -05:00
|
|
|
test: export NEW_RELIC_ENVIRONMENT=test
|
2023-04-17 15:56:08 -06:00
|
|
|
test: ## Run tests and create coverage report
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run black .
|
|
|
|
|
poetry run flake8 .
|
2025-01-07 07:13:32 -08:00
|
|
|
poetry run isort ./app ./tests
|
2024-10-01 13:21:05 -07:00
|
|
|
poetry run coverage run --omit=*/migrations/*,*/tests/* -m pytest --maxfail=10
|
2024-05-31 07:38:27 -07:00
|
|
|
|
2025-07-08 10:44:02 -07:00
|
|
|
|
|
|
|
|
poetry run coverage report -m --fail-under=95
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run coverage html -d .coverage_cache
|
2016-08-16 17:51:52 +01:00
|
|
|
|
2025-05-02 14:56:46 -04:00
|
|
|
.PHONY: test-debug
|
|
|
|
|
test-debug:
|
|
|
|
|
poetry run pytest --pdb -x
|
|
|
|
|
|
2023-10-30 15:40:22 -04:00
|
|
|
.PHONY: py-lock
|
|
|
|
|
py-lock: ## Syncs dependencies and updates lock file without performing recursive internal updates
|
2025-05-29 11:14:29 -07:00
|
|
|
poetry sync --no-root
|
2025-05-27 14:14:44 -07:00
|
|
|
poetry lock
|
2023-11-01 12:15:53 -04:00
|
|
|
|
Pin all application requirements in requirements.txt
The list of top-level dependencies is moved to requirements-app.txt,
which is used by `make freeze-requirements` to generate the full
list of requirements in requirements.txt.
This is based on alphagov/digitalmarketplace-api#615, so rationale
from that PR applies here.
We had a problem with unpinned packages on new deployments leading
to failed tests (e.g. alphagov/notifications-admin#2144) which is
why we're implementing this now.
After re-evaluating pipenv again, this still seems like the least
disruptive approach:
* pyup.io has experimental support for Pipfile, but doesn't respect
version ranges or updating hashes in the lock file
* CloudFoundry buildpack recognizes and supports Pipfiles out of the
box, but the support is relatively new. For example until recently
CF would install dev packages during deployment. It's also based on
generating a requirements file from the Pipfile, which doesn't
properly support pinning VCS dependencies (eg it doesn't set the
#egg= version, meaning pip will not upgrade the package if it's
already installed).
* pipenv has a strict dependency resolution algorithm, which doesn't
appear to be well documented and can cause some unexpected failures.
For example, pipenv doesn't seem to be able to install `awscli-cwlogs`
package at all, believing it to have a version conflict for `botocore`
(which it doesn't list as a direct dependency) while neither `pip` nor
`pip-tools` highlight any issues with it.
* While trying out `pipenv install` on our list of dependencies it would
regularly fail to install utils with a "Will try again." message.
While the installation succeeds after a retry, this doesn't inspire
confidence.
* The switch to Pipfile and pipenv-managed virtualenvs requires a series
of changes to `make` targets and scripts - replacing `pip install` with
`pipenv`, removing references to requirements files and prefixing
commands with `pipenv run`. While it's likely to simplify the overall
process of managing dependencies, it would require time to properly
implement across our applications and environments (Jenkins, PaaS,
docker containers, and dev machines).
2018-07-10 14:50:30 +01:00
|
|
|
.PHONY: freeze-requirements
|
2019-10-28 11:26:55 +00:00
|
|
|
freeze-requirements: ## Pin all requirements including sub dependencies into requirements.txt
|
2025-05-28 08:10:28 -07:00
|
|
|
poetry export --output > requirements.txt
|
Pin all application requirements in requirements.txt
The list of top-level dependencies is moved to requirements-app.txt,
which is used by `make freeze-requirements` to generate the full
list of requirements in requirements.txt.
This is based on alphagov/digitalmarketplace-api#615, so rationale
from that PR applies here.
We had a problem with unpinned packages on new deployments leading
to failed tests (e.g. alphagov/notifications-admin#2144) which is
why we're implementing this now.
After re-evaluating pipenv again, this still seems like the least
disruptive approach:
* pyup.io has experimental support for Pipfile, but doesn't respect
version ranges or updating hashes in the lock file
* CloudFoundry buildpack recognizes and supports Pipfiles out of the
box, but the support is relatively new. For example until recently
CF would install dev packages during deployment. It's also based on
generating a requirements file from the Pipfile, which doesn't
properly support pinning VCS dependencies (eg it doesn't set the
#egg= version, meaning pip will not upgrade the package if it's
already installed).
* pipenv has a strict dependency resolution algorithm, which doesn't
appear to be well documented and can cause some unexpected failures.
For example, pipenv doesn't seem to be able to install `awscli-cwlogs`
package at all, believing it to have a version conflict for `botocore`
(which it doesn't list as a direct dependency) while neither `pip` nor
`pip-tools` highlight any issues with it.
* While trying out `pipenv install` on our list of dependencies it would
regularly fail to install utils with a "Will try again." message.
While the installation succeeds after a retry, this doesn't inspire
confidence.
* The switch to Pipfile and pipenv-managed virtualenvs requires a series
of changes to `make` targets and scripts - replacing `pip install` with
`pipenv`, removing references to requirements files and prefixing
commands with `pipenv run`. While it's likely to simplify the overall
process of managing dependencies, it would require time to properly
implement across our applications and environments (Jenkins, PaaS,
docker containers, and dev machines).
2018-07-10 14:50:30 +01:00
|
|
|
|
2022-08-12 15:12:07 +00:00
|
|
|
.PHONY: audit
|
|
|
|
|
audit:
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry requirements > requirements.txt
|
|
|
|
|
poetry requirements --dev > requirements_for_test.txt
|
2025-05-28 07:35:47 -07:00
|
|
|
poetry run pip-audit -r requirements.txt --skip-editable
|
|
|
|
|
poetry run pip-audit -r requirements_for_test.txt --skip-editable
|
2022-08-12 15:12:07 +00:00
|
|
|
|
2022-08-12 17:19:28 -04:00
|
|
|
.PHONY: static-scan
|
|
|
|
|
static-scan:
|
2023-08-31 11:00:55 -07:00
|
|
|
poetry run bandit -r app/
|
2022-08-12 17:19:28 -04:00
|
|
|
|
2016-12-08 12:12:45 +00:00
|
|
|
.PHONY: clean
|
2016-08-16 17:51:52 +01:00
|
|
|
clean:
|
2020-12-07 17:51:15 +00:00
|
|
|
rm -rf node_modules cache target venv .coverage build tests/.cache ${CF_MANIFEST_PATH}
|
2016-12-08 12:12:45 +00:00
|
|
|
|
2020-03-03 11:51:50 +00:00
|
|
|
|
|
|
|
|
## DEPLOYMENT
|
|
|
|
|
|
2022-10-20 14:04:10 -04:00
|
|
|
# .PHONY: cf-deploy-failwhale
|
|
|
|
|
# cf-deploy-failwhale:
|
|
|
|
|
# $(if ${CF_SPACE},,$(error Must target space, eg `make preview cf-deploy-failwhale`))
|
|
|
|
|
# cd ./paas-failwhale; cf push notify-api-failwhale -f manifest.yml
|
|
|
|
|
|
|
|
|
|
# .PHONY: enable-failwhale
|
|
|
|
|
# enable-failwhale: ## Enable the failwhale app and disable api
|
|
|
|
|
# $(if ${DNS_NAME},,$(error Must target space, eg `make preview enable-failwhale`))
|
|
|
|
|
# # make sure failwhale is running first
|
|
|
|
|
# cf start notify-api-failwhale
|
|
|
|
|
|
|
|
|
|
# cf map-route notify-api-failwhale ${DNS_NAME} --hostname api
|
|
|
|
|
# cf unmap-route notify-api ${DNS_NAME} --hostname api
|
|
|
|
|
# @echo "Failwhale is enabled"
|
|
|
|
|
|
|
|
|
|
# .PHONY: disable-failwhale
|
|
|
|
|
# disable-failwhale: ## Disable the failwhale app and enable api
|
|
|
|
|
# $(if ${DNS_NAME},,$(error Must target space, eg `make preview disable-failwhale`))
|
|
|
|
|
|
|
|
|
|
# cf map-route notify-api ${DNS_NAME} --hostname api
|
|
|
|
|
# cf unmap-route notify-api-failwhale ${DNS_NAME} --hostname api
|
|
|
|
|
# cf stop notify-api-failwhale
|
|
|
|
|
# @echo "Failwhale is disabled"
|
2025-02-24 12:26:22 -05:00
|
|
|
|
|
|
|
|
.PHONY: test-single
|
|
|
|
|
test-single: export NEW_RELIC_ENVIRONMENT=test
|
|
|
|
|
test-single: ## Run a single test file
|
2025-02-27 16:09:49 -05:00
|
|
|
poetry run pytest -s $(TEST_FILE)
|