NUMBER_OF_PARALLEL_TESTS?=5

BASE_AWS_PROFILE    = gdb-infra-dev
BASE_AWS_ACCOUNT_ID = 483193324480
BASE_AWS_REGION     = us-east-1
BASE_ECR_REGISTRY   = $(BASE_AWS_ACCOUNT_ID).dkr.ecr.$(BASE_AWS_REGION).amazonaws.com

AWS_PROFILE    ?= gdb-apollo-dev
AWS_ACCOUNT_ID ?= 725764004555
AWS_REGION     ?= us-east-1

ECR_REGISTRY        ?= $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com
ECR_REPOSITORY_NAME ?= apollo/ago-pytest
ECR_REGISTRY_URI    ?= $(ECR_REGISTRY)/$(ECR_REPOSITORY_NAME)

REVISION  ?= $(shell git rev-parse --short=8 HEAD)

DEV_IMAGE = ${ECR_REGISTRY}/${ECR_REPOSITORY_NAME}:testing

VENV     := ./venv
PYTHON    = $(VENV)/bin/python
PIP       = $(VENV)/bin/pip
PYTEST    = $(VENV)/bin/pytest
PYLINT    = $(VENV)/bin/pylint
ISORT     = $(VENV)/bin/isort
MYPY      = $(VENV)/bin/mypy
PIP_AUDIT = $(VENV)/bin/pip-audit
FLAKE     = $(VENV)/bin/flake8
BANDIT    = $(VENV)/bin/bandit
BLACK     = $(VENV)/bin/black

## -
## help - this message
.PHONY: help
help: Makefile
	@echo "Application: ${APP}\n"
	@echo "Run command:\n  make <target>\n"
	@grep -E -h '^## .*' $(MAKEFILE_LIST) | sed -n 's/^##//p'  | column -t -s '-' |  sed -e 's/^/ /'

## -
## Local commands:

$(VENV)/bin/activate:
	python -m venv $(VENV)/

##   venv - create local virtual env
venv: $(VENV)/bin/activate
	@echo "Creating virtual environment"
	$(PIP) install -r requirements/base.txt

##   devenv - create local virtual env (dev.txt dependencies)
.PHONY:devenv
devenv: venv
	@echo "Installing dev requirements"
	$(PIP) install -r requirements/dev.txt

##   test - run tests locally
.PHONY:test
test:
	$(PYTEST) --html=report.html --self-contained-html --alluredir=app/src/allure_report app/src/tests/ -n 2 --reruns 2

##   report - make report locally
.PHONY:report
report:
	allure serve app/src/allure_report/

##   clean-up - clean up build artifacts
.PHONY:clean-up
clean-up:
	rm -rf .pytest_cache allure_report automation.log report.html

##   checkstyle - run checkstyle locally
.PHONY:checkstyle
checkstyle: devenv
	@echo "Run checkstyle"
	$(ISORT) -w 300 --check-only --quiet ./app/
	$(FLAKE) ./app/ --max-line-length=300 --ignore=E203,W503 --max-complexity=19

##   dependencies-check - run safety locally
.PHONY:dependencies-check
dependencies-check: devenv
	@echo "Run dependencies check"
	$(PIP_AUDIT) -r requirements/base.txt

##   dependencies-check - run bandit locally
.PHONY:owasp
owasp: devenv
	@echo "Run owasp check"
	$(BANDIT) -sB101,B311 -x ./app/src/tests/ -r ./app/src/

##   static-typing - run mypy locally
.PHONY:static-typing
static-typing: devenv
	@echo "Run static-typing check"
	$(MYPY) ./app/

##   static-typing - run safety and bandit locally
.PHONY:security
security: dependencies-check owasp

##   prettify - run prettify locally
.PHONY:prettify
prettify: devenv
	$(BLACK) ./app/ --exclude='/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|venv|_build|buck-out|build|dist|migrations|.pytest_cache)/' --line-length=300 --target-version=py39
	$(ISORT) -w 300 ./app/

.PHONY:pre-commit
pre-commit: prettify checkstyle security

## -
## Docker commands:

##   docker/login/base - login to AWS ECR registry using docker, aws configuration need to be set first
.PHONY:docker/login/base
docker/login/base:
	@aws ecr get-login \
		--profile ${BASE_AWS_PROFILE} \
		--no-include-email \
		--region ${BASE_AWS_REGION} | awk '{print $$6}' | \
		docker login -u AWS --password-stdin https://$(BASE_ECR_REGISTRY) || aws ecr get-login-password \
			--profile ${BASE_AWS_PROFILE} \
			--region ${BASE_AWS_REGION} | \
			docker login --username AWS --password-stdin https://$(BASE_ECR_REGISTRY)

##   docker/login - login to AWS ECR registry using docker, aws configuration need to be set first
.PHONY:docker/login
docker/login:
	@aws ecr get-login \
		--profile ${AWS_PROFILE} \
		--no-include-email \
		--region ${AWS_REGION} | awk '{print $$6}' | \
		docker login -u AWS --password-stdin https://$(ECR_REGISTRY) || aws ecr get-login-password \
			--profile ${AWS_PROFILE} \
			--region ${AWS_REGION} | \
			docker login --username AWS --password-stdin https://$(ECR_REGISTRY)

##   docker/base/image/pull - pull base image from ECR
docker/base/image/pull: docker/login/base
	docker pull $(BASE_ECR_REGISTRY)/python:3.9-slim-builder

##   docker/image/build - build lambda package for each environment and put all of them into one docker container
.PHONY: docker/image/build
docker/image/build: docker/login/base docker/login
	@echo "Building docker image"
	docker build \
		--cache-from $(ECR_REGISTRY_URI):latest \
		--target main \
		-t $(ECR_REGISTRY_URI):latest \
		-t $(ECR_REGISTRY_URI):$(REVISION) .
	docker build \
		--build-arg VERSION=$(VERSION) \
		--build-arg REVISION=$(REVISION) \
		--build-arg BUILDTIME=$(BUILDTIME) \
		--target dev \
		-t $(DEV_IMAGE) .

##   docker/image/push - push an image to a registry
.PHONY: docker/image/push
docker/image/push: docker/login
	@echo "Push docker image"
	docker push $(ECR_REGISTRY_URI):latest
	docker push $(ECR_REGISTRY_URI):$(REVISION)

##   docker/image/pull - pull an image from a registry
.PHONY: docker/image/pull
docker/image/pull: docker/login
	@echo "Pull docker image"
	docker pull $(ECR_REGISTRY_URI):$(REVISION)

##   docker/
.PHONY:docker/api_test
docker/api_test:
	@docker run \
		-e USER_EMAIL \
		-e USER_PASSWORD \
		-e AUTH0_CLIENT_ID \
		-e AUTH0_CLIENT_SECRET \
		-e AUTH0_CLIENT_ID_DELPHI \
		-e AUTH0_CLIENT_SECRET_DELPHI \
		-e AUTH0_AUDIENCE \
		-e AUTH0_GRANT_TYPE \
		-e AUTH0_REALM \
		-e AUTH0_HOST \
		-e MYSQL_DB_NAME \
		-e MYSQL_DB_USER \
		-e MYSQL_DB_PASS \
		-e MYSQL_DB_HOST \
		-e BROWSER_NAME \
		-e ENV_BASE_URL \
		-e SELENIUM_TIMEOUT \
		-e SELENIUM_ENV \
		-e PYTEST_XDIST_WORKER \
		-e SELENIUM_HEADLESS \
		-e TARGET_API_URL \
		-e CHROMEDRIVER_PATH \
		-e NOTIFICATIONS_EMAIL \
		-e NOTIFICATIONS_PASSWORD \
		-e DELPHI_API_URL \
		-e AUTH0_GRANT_TYPE_DELPHI \
		-e MOCK_USER_EMAIL_1 \
		-e MOCK_USER_EMAIL_2 \
		-e MOCK_USER_EMAIL_3 \
		-e MOCK_USER_EMAIL_4 \
		-e MOCK_USER_EMAIL_5 \
		-i \
		--rm \
		-v $(dir $(abspath $(lastword $(MAKEFILE_LIST))))output/:/usr/src/output/ \
		$(ECR_REGISTRY_URI):$(REVISION) \
			/venv/bin/pytest \
			--html=output/report.html \
			--self-contained-html \
			--alluredir=output/allure_report \
			--reruns 1 \
			app/src/tests/tests_api/

.PHONY:docker/ui_smoke_test
docker/ui_smoke_test:
	@docker run \
		-e USER_EMAIL \
		-e USER_PASSWORD \
		-e AUTH0_CLIENT_ID \
		-e AUTH0_CLIENT_SECRET \
		-e AUTH0_CLIENT_ID_DELPHI \
		-e AUTH0_CLIENT_SECRET_DELPHI \
		-e AUTH0_AUDIENCE \
		-e AUTH0_GRANT_TYPE \
		-e AUTH0_REALM \
		-e AUTH0_HOST \
		-e MYSQL_DB_NAME \
		-e MYSQL_DB_USER \
		-e MYSQL_DB_PASS \
		-e MYSQL_DB_HOST \
		-e BROWSER_NAME \
		-e ENV_BASE_URL \
		-e SELENIUM_TIMEOUT \
		-e SELENIUM_ENV \
		-e SELENIUM_HEADLESS \
		-e PYTEST_XDIST_WORKER \
		-e BROWSERSTACK_APP_USER \
		-e BROWSERSTACK_APP_KEY \
		-e IOS_APP_PATH \
		-e IOS_DEVICE \
		-e IOS_VERSION \
		-e IOS_BUILD \
		-e CHROMEDRIVER_PATH \
		-e APPIUM_VERSION \
		-e NOTIFICATIONS_EMAIL \
		-e NOTIFICATIONS_PASSWORD \
		-e TARGET_API_URL \
		-e DELPHI_API_URL \
		-e AUTH0_GRANT_TYPE_DELPHI \
		-e MOCK_USER_EMAIL_1 \
		-e MOCK_USER_EMAIL_2 \
		-e MOCK_USER_EMAIL_3 \
		-e MOCK_USER_EMAIL_4 \
		-e MOCK_USER_EMAIL_5 \
		-i \
		--rm \
		-v $(dir $(abspath $(lastword $(MAKEFILE_LIST))))output/:/usr/src/output/ \
		$(ECR_REGISTRY_URI):$(REVISION) \
			/venv/bin/pytest \
			--html=output/report.html \
			--self-contained-html \
			--alluredir=output/allure_report \
			-n ${NUMBER_OF_PARALLEL_TESTS} \
			--reruns 2 \
			-m smoke \
			app/src/tests/tests_ui/

.PHONY:docker/ui_full_test
docker/ui_full_test:
	@docker run \
		-e USER_EMAIL \
		-e USER_PASSWORD \
		-e AUTH0_CLIENT_ID \
		-e AUTH0_CLIENT_SECRET \
		-e AUTH0_CLIENT_ID_DELPHI \
		-e AUTH0_CLIENT_SECRET_DELPHI \
		-e AUTH0_AUDIENCE \
		-e AUTH0_GRANT_TYPE \
		-e AUTH0_REALM \
		-e AUTH0_HOST \
		-e MYSQL_DB_NAME \
		-e MYSQL_DB_USER \
		-e MYSQL_DB_PASS \
		-e MYSQL_DB_HOST \
		-e BROWSER_NAME \
		-e ENV_BASE_URL \
		-e SELENIUM_TIMEOUT \
		-e SELENIUM_ENV \
		-e SELENIUM_HEADLESS \
		-e PYTEST_XDIST_WORKER \
		-e BROWSERSTACK_APP_USER \
		-e BROWSERSTACK_APP_KEY \
		-e IOS_APP_PATH \
		-e IOS_DEVICE \
		-e IOS_VERSION \
		-e IOS_BUILD \
		-e CHROMEDRIVER_PATH \
		-e APPIUM_VERSION \
		-e NOTIFICATIONS_EMAIL \
		-e NOTIFICATIONS_PASSWORD \
		-e TARGET_API_URL \
		-e DELPHI_API_URL \
		-e AUTH0_GRANT_TYPE_DELPHI \
		-i \
		--rm \
		-v $(dir $(abspath $(lastword $(MAKEFILE_LIST))))output/:/usr/src/output/ \
		$(ECR_REGISTRY_URI):$(REVISION) \
			/venv/bin/pytest \
			--html=output/report.html \
			--self-contained-html \
			--alluredir=output/allure_report \
			-n ${NUMBER_OF_PARALLEL_TESTS} \
			--reruns 2 \
			app/src/tests/tests_ui/

##   docker/<local target> - universal docker wrapper for local targets
docker/%:
	docker run --rm \
		--env-file .env.sample \
		-v $(PWD):/app \
		$(DEV_IMAGE) make VENV=/venv $*
