Makefile 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. SHELL := /bin/bash
  2. .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
  3. # The name of the virtualenv directory to use
  4. VENV ?= venv
  5. pre-deploy:
  6. ifndef TEMP_BUCKET
  7. $(error TEMP_BUCKET is undefined)
  8. endif
  9. ifndef ADMIN_EMAIL
  10. $(error ADMIN_EMAIL is undefined)
  11. endif
  12. pre-run:
  13. ifndef ROLE_NAME
  14. $(error ROLE_NAME is undefined)
  15. endif
  16. build-frontend:
  17. npm run build --workspace frontend
  18. deploy:
  19. make pre-deploy
  20. make deploy-artefacts
  21. make deploy-cfn
  22. make setup-frontend-local-dev
  23. deploy-vpc:
  24. aws cloudformation create-stack --template-body file://templates/vpc.yaml --stack-name S3F2-VPC
  25. deploy-cfn:
  26. aws cloudformation package --template-file templates/template.yaml --s3-bucket $(TEMP_BUCKET) --output-template-file packaged.yaml
  27. aws cloudformation deploy --template-file ./packaged.yaml --stack-name S3F2 --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
  28. --parameter-overrides CreateCloudFrontDistribution=false EnableContainerInsights=true AdminEmail=$(ADMIN_EMAIL) \
  29. AccessControlAllowOriginOverride=* PreBuiltArtefactsBucketOverride=$(TEMP_BUCKET) KMSKeyArns=$(KMS_KEYARNS)
  30. deploy-artefacts:
  31. $(eval VERSION := $(shell $(MAKE) -s version))
  32. make package-artefacts
  33. aws s3 cp build.zip s3://$(TEMP_BUCKET)/amazon-s3-find-and-forget/$(VERSION)/build.zip
  34. .PHONY: format-cfn
  35. format-cfn:
  36. $(eval VERSION := $(shell $(MAKE) -s version))
  37. TEMP_FILE="$$(mktemp)" ; \
  38. sed -e '3s/.*/Description: Amazon S3 Find and Forget \(uksb-1q2j8beb0\) \(version:$(VERSION)\)/' templates/template.yaml > "$$TEMP_FILE" ; \
  39. mv "$$TEMP_FILE" templates/template.yaml
  40. git add templates/template.yaml
  41. .PHONY: format-docs
  42. format-docs:
  43. npx prettier ./*.md ./docs/*.md --write
  44. git add *.md
  45. git add docs/*.md
  46. .PHONY: format-js
  47. format-js:
  48. npx prettier ./frontend/src/**/*.js --write
  49. git add frontend/src/
  50. .PHONY: format-python
  51. format-python: | $(VENV)
  52. for src in \
  53. tests/ \
  54. backend/ecs_tasks/ \
  55. backend/lambdas/ \
  56. backend/lambda_layers/boto_utils/python/boto_utils.py \
  57. backend/lambda_layers/decorators/python/decorators.py \
  58. ; do \
  59. $(VENV)/bin/black "$$src" \
  60. ; done
  61. generate-api-docs:
  62. TEMP_FILE="$$(mktemp)" ; \
  63. $(VENV)/bin/yq -y .Resources.Api.Properties.DefinitionBody ./templates/api.yaml > "$$TEMP_FILE" ; \
  64. npx openapi-generator generate -i "$$TEMP_FILE" -g markdown -t ./docs/templates/ -o docs/api
  65. git add docs/api
  66. .PHONY: generate-pip-requirements
  67. generate-pip-requirements: $(patsubst %.in,%.txt,$(shell find . -type f -name requirements.in))
  68. .PHONY: lint-cfn
  69. lint-cfn:
  70. $(VENV)/bin/cfn-lint templates/*
  71. package:
  72. make package-artefacts
  73. zip -r packaged.zip \
  74. backend/lambda_layers \
  75. backend/lambdas \
  76. build.zip \
  77. cfn-publish.config \
  78. templates \
  79. -x '**/__pycache*' '*settings.js' @
  80. package-artefacts: backend/ecs_tasks/python_3.9-slim.tar
  81. make build-frontend
  82. zip -r build.zip \
  83. backend/ecs_tasks/ \
  84. backend/lambda_layers/boto_utils/ \
  85. frontend/build \
  86. -x '**/__pycache*' '*settings.js' @
  87. backend/ecs_tasks/python_3.9-slim.tar:
  88. docker pull python:3.9-slim
  89. docker save python:3.9-slim -o "$@"
  90. redeploy-containers:
  91. $(eval ACCOUNT_ID := $(shell aws sts get-caller-identity --query Account --output text))
  92. $(eval API_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`ApiUrl`].OutputValue' --output text))
  93. $(eval REGION := $(shell echo $(API_URL) | cut -d'.' -f3))
  94. $(eval ECR_REPOSITORY := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`ECRRepository`].OutputValue' --output text))
  95. $(eval REPOSITORY_URI := $(shell aws ecr describe-repositories --repository-names $(ECR_REPOSITORY) --query 'repositories[0].repositoryUri' --output text))
  96. $(shell aws ecr get-login --no-include-email --region $(REGION))
  97. docker build -t $(ECR_REPOSITORY) -f backend/ecs_tasks/delete_files/Dockerfile .
  98. docker tag $(ECR_REPOSITORY):latest $(REPOSITORY_URI):latest
  99. docker push $(REPOSITORY_URI):latest
  100. redeploy-frontend:
  101. $(eval WEBUI_BUCKET := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIBucket`].OutputValue' --output text))
  102. make build-frontend
  103. cd frontend/build && aws s3 cp --recursive . s3://$(WEBUI_BUCKET) --acl public-read --exclude *settings.js
  104. run-local-container:
  105. make pre-run
  106. ./docker_run_with_creds.sh
  107. setup: | $(VENV) lambda-layer-deps
  108. (! [[ -d .git ]] || $(VENV)/bin/pre-commit install)
  109. npm i
  110. gem install cfn-nag
  111. # virtualenv setup
  112. .PHONY: $(VENV)
  113. $(VENV): $(VENV)/pip-sync.sentinel
  114. $(VENV)/pip-sync.sentinel: requirements.txt | $(VENV)/bin/pip-sync
  115. $(VENV)/bin/pip-sync $<
  116. touch $@
  117. $(VENV)/bin/activate:
  118. test -d $(VENV) || virtualenv $(VENV)
  119. $(VENV)/bin/pip-compile $(VENV)/bin/pip-sync: $(VENV)/bin/activate
  120. $(VENV)/bin/pip install pip-tools
  121. # Lambda layers
  122. .PHONY: lambda-layer-deps
  123. lambda-layer-deps: \
  124. backend/lambda_layers/aws_sdk/requirements-installed.sentinel \
  125. backend/lambda_layers/cr_helper/requirements-installed.sentinel \
  126. backend/lambda_layers/decorators/requirements-installed.sentinel \
  127. ;
  128. backend/lambda_layers/%/requirements-installed.sentinel: backend/lambda_layers/%/requirements.txt | $(VENV)
  129. @# pip-sync only works with virtualenv, so we can't use it here.
  130. $(VENV)/bin/pip install -r $< -t $(subst requirements-installed.sentinel,python,$@)
  131. touch $@
  132. setup-frontend-local-dev:
  133. $(eval WEBUI_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIUrl`].OutputValue' --output text))
  134. $(eval WEBUI_BUCKET := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIBucket`].OutputValue' --output text))
  135. $(if $(filter none, $(WEBUI_URL)), @echo "WebUI not deployed.", aws s3 cp s3://$(WEBUI_BUCKET)/settings.js frontend/public/settings.js)
  136. setup-predeploy:
  137. virtualenv venv
  138. source venv/bin/activate && pip install cfn-flip==1.2.2
  139. start-frontend-local:
  140. npm start --workspace frontend
  141. start-frontend-remote:
  142. $(eval WEBUI_URL := $(shell aws cloudformation describe-stacks --stack-name S3F2 --query 'Stacks[0].Outputs[?OutputKey==`WebUIUrl`].OutputValue' --output text))
  143. $(if $(filter none, $(WEBUI_URL)), @echo "WebUI not deployed.", open $(WEBUI_URL))
  144. test-cfn:
  145. cfn_nag templates/*.yaml --blacklist-path ci/cfn_nag_blacklist.yaml
  146. test-frontend:
  147. npm t --workspace frontend
  148. test-unit: | $(VENV)
  149. $(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
  150. test-ci: | $(VENV)
  151. $(VENV)/bin/pytest -m unit --log-cli-level info --cov=backend.lambdas --cov=decorators --cov=boto_utils --cov=backend.ecs_tasks --cov-report xml
  152. test-acceptance-cognito: | $(VENV)
  153. $(VENV)/bin/pytest -m acceptance_cognito --log-cli-level info
  154. test-acceptance-iam: | $(VENV)
  155. $(VENV)/bin/pytest -m acceptance_iam --log-cli-level info
  156. test-no-state-machine: | $(VENV)
  157. $(VENV)/bin/pytest -m "not state_machine" --log-cli-level info --cov=backend.lambdas --cov=boto_utils --cov=decorators --cov=backend.ecs_tasks
  158. test: | $(VENV)
  159. make test-cfn
  160. $(VENV)/bin/pytest --log-cli-level info --cov=backend.lambdas --cov=decorators --cov=boto_utils --cov=backend.ecs_tasks
  161. make test-frontend
  162. version:
  163. @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"])')
  164. %/requirements.txt: %/requirements.in | $(VENV)/bin/pip-compile
  165. $(VENV)/bin/pip-compile -q -o $@ $<
  166. requirements.txt: requirements.in $(shell awk '/^-r / { print $$2 }' requirements.in) | $(VENV)/bin/pip-compile
  167. $(VENV)/bin/pip-compile -q -o $@ $<