2016-08-12 11:23:50 +01:00
.DEFAULT_GOAL := help
SHELL := /bin/bash
2018-08-09 13:46:43 +01:00
DATE = $( shell date +%Y-%m-%dT%H:%M:%S)
2016-08-12 11:23:50 +01:00
APP_VERSION_FILE = app/version.py
2016-08-26 16:18:13 +01:00
GIT_BRANCH ?= $( shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached" )
2017-02-01 15:44:10 +00:00
GIT_COMMIT ?= $( shell git rev-parse HEAD 2> /dev/null || echo "" )
2016-08-12 11:23:50 +01:00
2016-12-08 16:50:37 +00:00
DOCKER_IMAGE_TAG := $( shell cat docker/VERSION)
DOCKER_BUILDER_IMAGE_NAME = govuk/notify-admin-builder:${ DOCKER_IMAGE_TAG }
2016-08-12 11:23:50 +01:00
BUILD_TAG ?= notifications-admin-manual
BUILD_NUMBER ?= 0
DEPLOY_BUILD_NUMBER ?= ${ BUILD_NUMBER }
BUILD_URL ?=
DOCKER_CONTAINER_PREFIX = ${ USER } -${ BUILD_TAG }
2016-12-08 16:50:37 +00:00
CF_API ?= api.cloud.service.gov.uk
CF_ORG ?= govuk-notify
CF_SPACE ?= ${ DEPLOY_ENV }
2017-02-28 12:31:56 +00:00
CF_HOME ?= ${ HOME }
2019-04-18 14:48:23 +01:00
CF_APP ?= notify-admin
2017-02-28 12:31:56 +00:00
$( eval export CF_HOME )
2016-12-08 16:50:37 +00:00
2018-01-09 14:14:47 +00:00
NOTIFY_CREDENTIALS ?= ~/.notify-credentials
2020-03-03 12:05:56 +00:00
## DEVELOPMENT
2016-08-12 11:23:50 +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 : dependencies
2019-12-24 15:24:07 +00:00
dependencies : ## Install build dependencies
2016-08-12 11:23:50 +01:00
npm set progress = false
npm install
npm rebuild node-sass
2019-12-24 15:24:07 +00:00
pip install -r requirements_for_test.txt
2016-08-12 11:23:50 +01:00
.PHONY : generate -version -file
generate-version-file : ## Generates the app version file
2020-04-21 17:00:38 +01:00
@echo -e "__git_commit__ = \" ${ GIT_COMMIT } \"\n__time__ = \" ${ DATE } \"" > ${ APP_VERSION_FILE }
2016-08-12 11:23:50 +01:00
.PHONY : build
build : dependencies generate -version -file ## Build project
npm run build
2019-12-24 15:24:07 +00:00
pip install -r requirements.txt
2016-08-12 11:23:50 +01:00
.PHONY : test
2019-12-24 15:24:07 +00:00
test : ## Run tests
2016-08-12 11:23:50 +01:00
./scripts/run_tests.sh
2020-01-13 10:26:11 +00:00
.PHONY : fix -imports
fix-imports :
isort -rc ./app ./tests
2018-07-10 15:16:14 +01:00
.PHONY : freeze -requirements
freeze-requirements :
rm -rf venv-freeze
virtualenv -p python3 venv-freeze
$$ ( pwd ) /venv-freeze/bin/pip install -r requirements-app.txt
2018-07-30 16:43:44 +01:00
echo '# pyup: ignore file' > requirements.txt
echo '# This file is autogenerated. Do not edit it manually.' >> requirements.txt
2018-07-10 15:16:14 +01:00
cat requirements-app.txt >> requirements.txt
echo '' >> requirements.txt
$$ ( pwd ) /venv-freeze/bin/pip freeze -r <( sed '/^--/d' requirements-app.txt) | sed -n '/The following requirements were added by pip freeze/,$$p' >> requirements.txt
rm -rf venv-freeze
.PHONY : test -requirements
test-requirements :
@diff requirements-app.txt requirements.txt | grep '<' \
&& { echo "requirements.txt doesn't match requirements-app.txt." ; \
echo "Run 'make freeze-requirements' to update." ; exit 1; } \
|| { echo "requirements.txt is up to date" ; exit 0; }
2016-08-12 11:23:50 +01:00
.PHONY : prepare -docker -build -image
prepare-docker-build-image : ## Prepare the Docker builder image
2016-12-08 16:50:37 +00:00
make -C docker build
2016-08-12 11:23:50 +01:00
2016-12-08 16:50:37 +00:00
define run_docker_container
2020-03-03 12:04:32 +00:00
@docker run -it --rm \
2016-12-08 16:50:37 +00:00
--name "${DOCKER_CONTAINER_PREFIX}-${1}" \
2017-01-09 10:31:20 +00:00
-v "`pwd` : /var /project " \
2017-01-11 14:02:10 +00:00
-e UID =$( shell id -u ) \
-e GID =$( shell id -g ) \
2016-08-23 13:35:21 +01:00
-e GIT_COMMIT =${GIT_COMMIT } \
-e BUILD_NUMBER =${BUILD_NUMBER } \
-e BUILD_URL =${BUILD_URL } \
2016-11-30 15:57:20 +00:00
-e http_proxy ="${HTTP_PROXY }" \
-e HTTP_PROXY ="${HTTP_PROXY }" \
-e https_proxy ="${HTTPS_PROXY }" \
-e HTTPS_PROXY ="${HTTPS_PROXY }" \
-e NO_PROXY ="${NO_PROXY }" \
2016-08-26 16:18:13 +01:00
-e CI_NAME =${CI_NAME } \
-e CI_BUILD_NUMBER =${BUILD_NUMBER } \
-e CI_BUILD_URL =${BUILD_URL } \
-e CI_BRANCH =${GIT_BRANCH } \
-e CI_PULL_REQUEST =${CI_PULL_REQUEST } \
2016-12-08 16:50:37 +00:00
-e CF_API ="${CF_API }" \
-e CF_USERNAME ="${CF_USERNAME }" \
-e CF_PASSWORD ="${CF_PASSWORD }" \
-e CF_ORG ="${CF_ORG }" \
-e CF_SPACE ="${CF_SPACE }" \
2016-08-12 11:23:50 +01:00
${DOCKER_BUILDER_IMAGE_NAME } \
2016-12-08 16:50:37 +00:00
${2}
endef
.PHONY : build -with -docker
build-with-docker : prepare -docker -build -image ## Build inside a Docker container
2017-01-11 14:02:10 +00:00
$( call run_docker_container,build,gosu hostuser make build)
2016-12-08 16:50:37 +00:00
.PHONY : test -with -docker
test-with-docker : prepare -docker -build -image ## Run tests inside a Docker container
2017-01-11 14:02:10 +00:00
$( call run_docker_container,test,gosu hostuser make test )
2016-12-08 16:50:37 +00:00
2016-08-12 11:23:50 +01:00
.PHONY : clean -docker -containers
clean-docker-containers : ## Clean up any remaining docker containers
docker rm -f $( shell docker ps -q -f "name= ${ DOCKER_CONTAINER_PREFIX } " ) 2> /dev/null || true
2016-12-08 16:50:37 +00:00
.PHONY : clean
2016-08-12 11:23:50 +01:00
clean :
2019-12-24 15:25:34 +00:00
rm -rf node_modules cache target
2016-12-08 16:50:37 +00:00
2020-03-03 12:05:56 +00:00
## 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 : preview
preview : ## Set environment to preview
$( eval export DEPLOY_ENV = preview)
$( eval export DNS_NAME = "notify.works" )
@true
.PHONY : staging
staging : ## Set environment to staging
$( eval export DEPLOY_ENV = staging)
$( eval export DNS_NAME = "staging-notify.works" )
@true
.PHONY : production
production : ## Set environment to production
$( eval export DEPLOY_ENV = production)
$( eval export DNS_NAME = "notifications.service.gov.uk" )
@true
2016-12-08 16:50:37 +00:00
.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 } "
2018-01-09 14:14:47 +00:00
.PHONY : generate -manifest
generate-manifest :
2019-04-12 11:05:45 +01:00
$(if ${ CF_APP } ,,$( error Must specify CF_APP))
2018-01-09 14:14:47 +00:00
$(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))
2019-04-12 11:05:45 +01:00
@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
2018-01-09 14:14:47 +00:00
2020-03-03 12:05:15 +00:00
.PHONY : upload -static ## Upload the static files to be served from S3
upload-static :
aws s3 cp --region eu-west-1 --recursive --cache-control max-age= 315360000,immutable ./app/static s3://${ DNS_NAME } -static
2016-12-08 16:50:37 +00:00
.PHONY : cf -deploy
2018-12-18 15:48:14 +00:00
cf-deploy : ## Deploys the app to Cloud Foundry
2017-02-14 16:17:30 +00:00
$(if ${ CF_SPACE } ,,$( error Must specify CF_SPACE))
@cf app --guid notify-admin || exit 1
2019-05-09 16:11:26 +01:00
# cancel any existing deploys to ensure we can apply manifest (if a deploy is in progress you'll see ScaleDisabledDuringDeployment)
cf v3-cancel-zdt-push ${ CF_APP } || true
cf v3-apply-manifest ${ CF_APP } -f <( make -s generate-manifest)
2020-03-23 14:38:01 +00:00
CF_STARTUP_TIMEOUT = 10 cf v3-zdt-push ${ CF_APP } --wait-for-deploy-complete # fails after 5 mins if deploy doesn't work
2017-02-14 16:17:30 +00:00
2017-05-05 08:41:55 +01:00
.PHONY : cf -deploy -prototype
2019-04-12 11:05:45 +01:00
cf-deploy-prototype : cf -target ## Deploys the first prototype to Cloud Foundry
cf push -f <( CF_APP = notify-admin-prototype make -s generate-manifest)
2017-05-05 08:41:55 +01:00
2018-02-07 17:28:04 +00:00
.PHONY : cf -deploy -prototype -2
2019-04-12 11:05:45 +01:00
cf-deploy-prototype-2 : cf -target ## Deploys the second prototype to Cloud Foundry
cf push -f <( CF_APP = notify-admin-prototype-2 make -s generate-manifest)
2018-02-07 17:28:04 +00:00
2017-02-14 16:17:30 +00:00
.PHONY : cf -rollback
2019-05-09 16:11:26 +01:00
cf-rollback : cf -target ## Rollbacks the app to the previous release
cf v3-cancel-zdt-push ${ CF_APP }
2016-12-08 16:50:37 +00:00
2018-01-03 17:17:26 +00:00
.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"