123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- SHELL := /bin/bash
- .PHONY : deploy deploy-containers pre-deploy setup test test-cov test-acceptance test-acceptance-cov test-no-state-machine test-no-state-machine-cov test-unit test-unit-cov
- # The name of the virtualenv directory to use
- VENV ?= venv
- pre-deploy:
- ifndef TEMP_BUCKET
- $(error TEMP_BUCKET is undefined)
- endif
- ifndef ADMIN_EMAIL
- $(error ADMIN_EMAIL is undefined)
- endif
- pre-run:
- ifndef ROLE_NAME
- $(error ROLE_NAME is undefined)
- endif
- build-frontend:
- npm run build --workspace frontend
- deploy:
- make pre-deploy
- make deploy-artefacts
- make deploy-cfn
- make setup-frontend-local-dev
- deploy-vpc:
- aws cloudformation create-stack --template-body file://templates/vpc.yaml --stack-name S3F2-VPC
- deploy-cfn:
- aws cloudformation package --template-file templates/template.yaml --s3-bucket $(TEMP_BUCKET) --output-template-file packaged.yaml
- aws cloudformation deploy --template-file ./packaged.yaml --stack-name S3F2 --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
- --parameter-overrides CreateCloudFrontDistribution=false EnableContainerInsights=true AdminEmail=$(ADMIN_EMAIL) \
- AccessControlAllowOriginOverride=* PreBuiltArtefactsBucketOverride=$(TEMP_BUCKET) KMSKeyArns=$(KMS_KEYARNS)
- deploy-artefacts:
- $(eval VERSION := $(shell $(MAKE) -s version))
- make package-artefacts
- aws s3 cp build.zip s3://$(TEMP_BUCKET)/amazon-s3-find-and-forget/$(VERSION)/build.zip
- .PHONY: format-cfn
- format-cfn:
- $(eval VERSION := $(shell $(MAKE) -s version))
- TEMP_FILE="$$(mktemp)" ; \
- sed -e '3s/.*/Description: Amazon S3 Find and Forget \(uksb-1q2j8beb0\) \(version:$(VERSION)\)/' templates/template.yaml > "$$TEMP_FILE" ; \
- mv "$$TEMP_FILE" templates/template.yaml
- git add templates/template.yaml
- .PHONY: format-docs
- format-docs:
- npx prettier ./*.md ./docs/*.md --write
- git add *.md
- git add docs/*.md
- .PHONY: format-js
- format-js:
- npx prettier ./frontend/src/**/*.js --write
- git add frontend/src/
- .PHONY: format-python
- format-python: | $(VENV)
- for src in \
- tests/ \
- backend/ecs_tasks/ \
- backend/lambdas/ \
- backend/lambda_layers/boto_utils/python/boto_utils.py \
- backend/lambda_layers/decorators/python/decorators.py \
- ; do \
- $(VENV)/bin/black "$$src" \
- ; done
- generate-api-docs:
- TEMP_FILE="$$(mktemp)" ; \
- $(VENV)/bin/yq -y .Resources.Api.Properties.DefinitionBody ./templates/api.yaml > "$$TEMP_FILE" ; \
- npx openapi-generator generate -i "$$TEMP_FILE" -g markdown -t ./docs/templates/ -o docs/api
- git add docs/api
- .PHONY: generate-pip-requirements
- generate-pip-requirements: $(patsubst %.in,%.txt,$(shell find . -type f -name requirements.in))
- .PHONY: lint-cfn
- lint-cfn:
- $(VENV)/bin/cfn-lint templates/*
- package:
- make package-artefacts
- zip -r packaged.zip \
- backend/lambda_layers \
- backend/lambdas \
- build.zip \
- cfn-publish.config \
- templates \
- -x '**/__pycache*' '*settings.js' @
- package-artefacts: backend/ecs_tasks/python_3.9-slim.tar
- make build-frontend
- zip -r build.zip \
- backend/ecs_tasks/ \
- backend/lambda_layers/boto_utils/ \
- frontend/build \
- -x '**/__pycache*' '*settings.js' @
- backend/ecs_tasks/python_3.9-slim.tar:
- docker pull python:3.9-slim
- docker save python:3.9-slim -o "$@"
- redeploy-containers:
- $(eval ACCOUNT_ID := $(shell aws sts get-caller-identity --query Account --output text))
- $(eval API_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`ApiUrl`].OutputValue' --output text))
- $(eval REGION := $(shell echo $(API_URL) | cut -d'.' -f3))
- $(eval ECR_REPOSITORY := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`ECRRepository`].OutputValue' --output text))
- $(eval REPOSITORY_URI := $(shell aws ecr describe-repositories --repository-names $(ECR_REPOSITORY) --query 'repositories[0].repositoryUri' --output text))
- $(shell aws ecr get-login --no-include-email --region $(REGION))
- docker build -t $(ECR_REPOSITORY) -f backend/ecs_tasks/delete_files/Dockerfile .
- docker tag $(ECR_REPOSITORY):latest $(REPOSITORY_URI):latest
- docker push $(REPOSITORY_URI):latest
- redeploy-frontend:
- $(eval WEBUI_BUCKET := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIBucket`].OutputValue' --output text))
- make build-frontend
- cd frontend/build && aws s3 cp --recursive . s3://$(WEBUI_BUCKET) --acl public-read --exclude *settings.js
- run-local-container:
- make pre-run
- ./docker_run_with_creds.sh
- setup: | $(VENV) lambda-layer-deps
- (! [[ -d .git ]] || $(VENV)/bin/pre-commit install)
- npm i
- gem install cfn-nag
- # virtualenv setup
- .PHONY: $(VENV)
- $(VENV): $(VENV)/pip-sync.sentinel
- $(VENV)/pip-sync.sentinel: requirements.txt | $(VENV)/bin/pip-sync
- $(VENV)/bin/pip-sync $<
- touch $@
- $(VENV)/bin/activate:
- test -d $(VENV) || virtualenv $(VENV)
- $(VENV)/bin/pip-compile $(VENV)/bin/pip-sync: $(VENV)/bin/activate
- $(VENV)/bin/pip install pip-tools
- # Lambda layers
- .PHONY: lambda-layer-deps
- lambda-layer-deps: \
- backend/lambda_layers/aws_sdk/requirements-installed.sentinel \
- backend/lambda_layers/cr_helper/requirements-installed.sentinel \
- backend/lambda_layers/decorators/requirements-installed.sentinel \
- ;
- backend/lambda_layers/%/requirements-installed.sentinel: backend/lambda_layers/%/requirements.txt | $(VENV)
- @# pip-sync only works with virtualenv, so we can't use it here.
- $(VENV)/bin/pip install -r $< -t $(subst requirements-installed.sentinel,python,$@)
- touch $@
- setup-frontend-local-dev:
- $(eval WEBUI_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIUrl`].OutputValue' --output text))
- $(eval WEBUI_BUCKET := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIBucket`].OutputValue' --output text))
- $(if $(filter none, $(WEBUI_URL)), @echo "WebUI not deployed.", aws s3 cp s3://$(WEBUI_BUCKET)/settings.js frontend/public/settings.js)
- setup-predeploy:
- virtualenv venv
- source venv/bin/activate && pip install cfn-flip==1.2.2
- start-frontend-local:
- npm start --workspace frontend
- start-frontend-remote:
- $(eval WEBUI_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIUrl`].OutputValue' --output text))
- $(if $(filter none, $(WEBUI_URL)), @echo "WebUI not deployed.", open $(WEBUI_URL))
- test-cfn:
- cfn_nag templates/*.yaml --blacklist-path ci/cfn_nag_blacklist.yaml
- test-frontend:
- npm t --workspace frontend
- test-unit: | $(VENV)
- $(VENV)/bin/pytest -m unit --log-cli-level info --cov=backend.lambdas --cov=decorators --cov=boto_utils --cov=backend.ecs_tasks --cov-report term-missing
- test-ci: | $(VENV)
- $(VENV)/bin/pytest -m unit --log-cli-level info --cov=backend.lambdas --cov=decorators --cov=boto_utils --cov=backend.ecs_tasks --cov-report xml
- test-acceptance-cognito: | $(VENV)
- $(VENV)/bin/pytest -m acceptance_cognito --log-cli-level info
- test-acceptance-iam: | $(VENV)
- $(VENV)/bin/pytest -m acceptance_iam --log-cli-level info
- test-no-state-machine: | $(VENV)
- $(VENV)/bin/pytest -m "not state_machine" --log-cli-level info --cov=backend.lambdas --cov=boto_utils --cov=decorators --cov=backend.ecs_tasks
- test: | $(VENV)
- make test-cfn
- $(VENV)/bin/pytest --log-cli-level info --cov=backend.lambdas --cov=decorators --cov=boto_utils --cov=backend.ecs_tasks
- make test-frontend
- version:
- @echo $(shell $(VENV)/bin/cfn-flip templates/template.yaml | $(VENV)/bin/python -c 'import sys, json; print(json.load(sys.stdin)["Mappings"]["Solution"]["Constants"]["Version"])')
- %/requirements.txt: %/requirements.in | $(VENV)/bin/pip-compile
- $(VENV)/bin/pip-compile -q -o $@ $<
- requirements.txt: requirements.in $(shell awk '/^-r / { print $$2 }' requirements.in) | $(VENV)/bin/pip-compile
- $(VENV)/bin/pip-compile -q -o $@ $<
|