Skip to content

Commit

Permalink
[#385] Refactor Makefile structure for enhanced modularity and deploy…
Browse files Browse the repository at this point in the history
…ment efficiency

This commit reorganizes the build and deployment scripts by introducing
separate Makefiles for the backend and frontend components, along with
common utilities and informational targets. The new structure aims to
improve modularity, maintainability, and clarity of the deployment
process. Component-specific Makefiles handle Docker image construction
and deployment more effectively, while shared utilities and variables
are centralized for ease of use. Additionally, the update simplifies
Docker tag generation by incorporating it directly into the Makefiles,
eliminating the need for separate versioning scripts. The README has
been updated to guide users through the new deployment process.
  • Loading branch information
placek committed Mar 5, 2024
1 parent ddafe55 commit d7a7fb6
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 204 deletions.
31 changes: 31 additions & 0 deletions govtool/backend/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
common_mk := ../../scripts/govtool/common.mk
ifeq ($(origin $(common_mk)), undefined)
$(eval $(common_mk) := included)
include $(common_mk)
endif

.DEFAULT_GOAL := push-backend

# image tags
base_backend_image_tag := $(shell git hash-object $(root_dir)/govtool/backend/vva-be.cabal)
backend_image_tag := $(shell git log -n 1 --format="%H" -- $(root_dir)/govtool/backend)

.PHONY: build-backend-base
build-backend-base: docker-login
$(call check_image_on_ecr,backend-base,$(base_backend_image_tag)) || \
$(docker) build --file $(root_dir)/govtool/backend/Dockerfile.base --tag "$(repo_url)/backend-base:$(base_backend_image_tag)" $(root_dir)/govtool/backend

.PHONY: push-backend-base
push-backend-base: build-backend-base
$(call check_image_on_ecr,backend-base,$(base_backend_image_tag)) || \
$(docker) push $(repo_url)/backend-base:$(base_backend_image_tag)

.PHONY: build-backend
build-backend: build-backend-base
$(call check_image_on_ecr,backend,$(backend_image_tag)) || \
$(docker) build --build-arg BASE_IMAGE_TAG=$(base_backend_image_tag) --tag "$(repo_url)/backend:$(backend_image_tag)" $(root_dir)/govtool/backend

.PHONY: push-backend
push-backend: push-backend-base build-backend
$(call check_image_on_ecr,backend,$(backend_image_tag)) || \
$(docker) push $(repo_url)/backend:$(backend_image_tag)
33 changes: 33 additions & 0 deletions govtool/frontend/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
common_mk := ../../scripts/govtool/common.mk
ifeq ($(origin $(common_mk)), undefined)
$(eval $(common_mk) := included)
include $(common_mk)
endif

.DEFAULT_GOAL := push-frontend

# environment variables
gtm_id := $(shell echo $${GTM_ID})
sentry_dsn := $(shell echo $${SENTRY_DSN})

# image tags
frontend_image_tag := $(shell git log -n 1 --format="%H" -- $(root_dir)/govtool/frontend)

.PHONY: build-frontend
build-frontend: docker-login
@:$(call check_defined, cardano_network)
@:$(call check_defined, gtm_id)
@:$(call check_defined, sentry_dsn)
if [[ "$(cardano_network)" = "mainnet" ]]; then NETWORK_FLAG=1; else NETWORK_FLAG=0; fi; \
$(call check_image_on_ecr,frontend,$(frontend_image_tag)) || \
$(docker) build --tag "$(repo_url)/frontend:$(frontend_image_tag)" \
--build-arg VITE_BASE_URL="https://$(domain)/api" \
--build-arg VITE_GTM_ID="$(gtm_id)" \
--build-arg VITE_NETWORK_FLAG="$$NETWORK_FLAG" \
--build-arg VITE_SENTRY_DSN="$(sentry_dsn)" \
$(root_dir)/govtool/frontend

.PHONY: push-frontend
push-frontend: build-frontend
$(call check_image_on_ecr,frontend,$(frontend_image_tag)) || \
$(docker) push $(repo_url)/frontend:$(frontend_image_tag)
179 changes: 17 additions & 162 deletions scripts/govtool/Makefile
Original file line number Diff line number Diff line change
@@ -1,77 +1,34 @@
SHELL := bash
ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
include ../../govtool/backend/Makefile
include ../../govtool/frontend/Makefile
include utils.mk
include info.mk

.DEFAULT_GOAL := info

# tools
docker ?= docker
curl ?= curl
rsync ?= rsync
ssh-keyscan ?= ssh-keyscan

# environment variables
env := $(shell echo $${ENVIRONMENT})
cardano_network := $(shell echo $${CARDANO_NETWORK})
grafana_admin_password := $(shell echo $${GRAFANA_ADMIN_PASSWORD})
grafana_slack_recipient := $(shell echo $${GRAFANA_SLACK_RECIPIENT})
grafana_slack_oauth_token := $(shell echo $${GRAFANA_SLACK_OAUTH_TOKEN})
gtm_id := $(shell echo $${GTM_ID})
sentry_dsn := $(shell echo $${SENTRY_DSN})

# git state
commit := $(shell git rev-parse HEAD)
branch := $(shell git rev-parse --abbrev-ref HEAD)

# target addresses
domain := $(shell echo $${DOMAIN:-$(env)-$(cardano_network).govtool.byron.network})
repo_url ?= 733019650473.dkr.ecr.eu-west-1.amazonaws.com
docker_host := $(domain)
docker_user := ubuntu
ssh_url := $(docker_user)@$(docker_host)

# stack configuration
docker_compose_file := docker-compose.$(env).yml
compose_stack_name := govtool-$(env)-$(cardano_network)

# pipeline information
pipeline_url := $(shell echo $${PIPELINE_URL:-})
ifeq ($(PIPELINE_URL),)
pipeline_info := _Deployed from local machine._
else
pipeline_info := _Deployed from <$(pipeline_url)|GitHub>._
endif

# image tags
cardano_node_image_tag := 8.8.0-pre
cardano_db_sync_image_tag := sancho-4-0-0-fix-config
base_backend_image_tag := $(shell ./utils/backend-base-version)
backend_image_tag := $(shell ./utils/backend-version)
frontend_image_tag := $(shell ./utils/frontend-version)

# helper function for checking undefined variables
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))))

# helper function for checking if image exists on ECR
check_image_on_ecr = \
$(docker) manifest inspect "$(repo_url)/$1:$2" > /dev/null 2>&1

.PHONY: all
all: docker-login prepare-config upload-config build-backend push-backend build-frontend push-frontend deploy-stack info notify

.PHONY: check-env-defined
check-env-defined:
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@grep -q "module \"$(compose_stack_name)\"" ../../infra/terraform/main.tf && \
echo "Environment $(env) for network $(cardano_network) is defined in Terraform" || \
{ echo "Environment $(env) for network $(cardano_network) is NOT defined in Terraform, cannot deploy there"; exit 1; }

.PHONY: docker-login
docker-login:
aws ecr get-login-password --region eu-west-1 | $(docker) login --username AWS --password-stdin $(repo_url)/backend
aws ecr get-login-password --region eu-west-1 | $(docker) login --username AWS --password-stdin $(repo_url)/frontend
all: deploy-stack info #notify

.PHONY: prepare-config
prepare-config:
Expand All @@ -84,64 +41,13 @@ prepare-config:
./prepare-config.sh

.PHONY: upload-config
upload-config: prepare-config
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
rsync -av -e 'ssh -o StrictHostKeyChecking=no' config/target/. $(ssh_url):config

.PHONY: build-backend
build-backend: docker-login build-backend-base
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(call check_image_on_ecr,backend,$(backend_image_tag)) || \
$(docker) build --build-arg BASE_IMAGE_TAG=$(base_backend_image_tag) --tag "$(repo_url)/backend:$(backend_image_tag)" ../../govtool/backend

.PHONY: build-backend-base
build-backend-base: docker-login
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(call check_image_on_ecr,backend-base,$(base_backend_image_tag)) || \
$(docker) build --file ../../govtool/backend/Dockerfile.base --tag "$(repo_url)/backend-base:$(base_backend_image_tag)" ../../govtool/backend
@echo "Using backend-base image: $(repo_url)/backend-base:$(base_backend_image_tag)"

.PHONY: push-backend
push-backend: docker-login push-backend-base build-backend
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(call check_image_on_ecr,backend,$(backend_image_tag)) || \
$(docker) push $(repo_url)/backend:$(backend_image_tag)

.PHONY: push-backend-base
push-backend-base: docker-login build-backend-base
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(call check_image_on_ecr,backend-base,$(base_backend_image_tag)) || \
$(docker) push $(repo_url)/backend-base:$(base_backend_image_tag)

.PHONY: build-frontend
build-frontend: docker-login
upload-config: check-env-defined prepare-config
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@:$(call check_defined, gtm_id)
@:$(call check_defined, sentry_dsn)
if [[ "$(cardano_network)" = "mainnet" ]]; then NETWORK_FLAG=1; else NETWORK_FLAG=0; fi; \
$(call check_image_on_ecr,frontend,$(frontend_image_tag)) || \
$(docker) build --tag "$(repo_url)/frontend:$(frontend_image_tag)" \
--build-arg VITE_BASE_URL="https://$(domain)/api" \
--build-arg VITE_GTM_ID="$(gtm_id)" \
--build-arg VITE_NETWORK_FLAG="$$NETWORK_FLAG" \
--build-arg VITE_SENTRY_DSN="$(sentry_dsn)" \
../../govtool/frontend

.PHONY: push-frontend
push-frontend: docker-login build-frontend
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(call check_image_on_ecr,frontend,$(frontend_image_tag)) || \
$(docker) push $(repo_url)/frontend:$(frontend_image_tag)
$(rsync) -av -e 'ssh -o StrictHostKeyChecking=no' config/target/. $(ssh_url):config

.PHONY: deploy-stack
deploy-stack: docker-login
deploy-stack: upload-config push-backend push-frontend
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@:$(call check_defined, grafana_admin_password)
Expand All @@ -153,12 +59,12 @@ deploy-stack: docker-login
export FRONTEND_TAG=$(frontend_image_tag); \
export CARDANO_NODE_TAG=$(cardano_node_image_tag); \
export CARDANO_DB_SYNC_TAG=$(cardano_db_sync_image_tag); \
ssh-keyscan $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
$(ssh-keyscan) $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
$(docker) compose -f $(docker_compose_file) -p $(compose_stack_name) pull; \
$(docker) compose -f $(docker_compose_file) -p $(compose_stack_name) up -d

.PHONY: destroy-cardano-node-and-dbsync
destroy-cardano-node-and-dbsync:
destroy-cardano-node-and-dbsync: check-env-defined
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
export CARDANO_NETWORK=$(cardano_network); \
Expand All @@ -168,15 +74,15 @@ destroy-cardano-node-and-dbsync:
export FRONTEND_TAG=$(frontend_image_tag); \
export CARDANO_NODE_TAG=$(cardano_node_image_tag); \
export CARDANO_DB_SYNC_TAG=$(cardano_db_sync_image_tag); \
ssh-keyscan $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
$(ssh-keyscan) $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
containers="$$(docker container ls --no-trunc --format '{{.Names}}' -f name=cardano-node -f name=cardano-db-sync -f name=postgres)"; \
volumes="$$(docker volume ls --format '{{.Name}}' -f name=db-sync-data -f name=node-db -f name=node-ipc -f name=postgres)"; \
$(docker) container stop $${containers}; \
$(docker) container rm $${containers}; \
$(docker) volume rm $${volumes}

.PHONY: toggle-maintenance
toggle-maintenance:
toggle-maintenance: check-env-defined
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@:$(call check_defined, maintenance)
Expand All @@ -187,57 +93,6 @@ toggle-maintenance:
export FRONTEND_TAG=$(frontend_image_tag); \
export CARDANO_NODE_TAG=$(cardano_node_image_tag); \
export CARDANO_DB_SYNC_TAG=$(cardano_db_sync_image_tag); \
ssh-keyscan $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
$(ssh-keyscan) $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
if [[ "$(maintenance)" = "enable" ]]; then $(docker) compose -f $(docker_compose_file) -p $(compose_stack_name) exec frontend touch /var/run/maintenance_enabled; \
else $(docker) compose -f $(docker_compose_file) -p $(compose_stack_name) exec frontend rm /var/run/maintenance_enabled; fi

.DEFAULT_GOAL := info
.PHONY: info
info:
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@echo "+-----------"
@echo "| TIME $(shell date +'%Y-%m-%d %H:%M:%S%z')"
@echo "| BRANCH $(branch) [$(commit)]"
@echo "| ENV $(env)"
@echo "I NETWORK $(cardano_network)"
@echo "N BACKEND $(repo_url)/backend:$(backend_image_tag)"
@echo "F FRONTEND $(repo_url)/frontend:$(frontend_image_tag)"
@echo "O NODE ghcr.io/intersectmbo/cardano-node:$(cardano_node_image_tag)"
@echo "| DBSYNC ghcr.io/intersectmbo/cardano-db-sync:$(cardano_db_sync_image_tag)"
@echo "| SSH $(ssh_url)"
@echo "| URL https://$(docker_host)"
@echo "+-----------"

.PHONY: notify
notify:
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
$(curl) -X POST https://slack.com/api/chat.postMessage\
-H "Authorization: Bearer $(grafana_slack_oauth_token)" \
-H "Content-Type: application/json; charset=utf-8" \
--data "{ \"channel\":\"$(grafana_slack_recipient)\", \"text\":\":rocket: *Deploy performed on \`$(env)\`*\n- from *branch* \`$(branch)\` (\`$(commit)\`),\n- using *Cardano Node* version \`$(cardano_node_image_tag)\`,\n- using *Cardano DB Sync* version \`$(cardano_db_sync_image_tag)\`,\n- using *GovTool backend* version \`$(backend_image_tag)\`,\n- using *Govtool frontend* version \`$(frontend_image_tag)\`.\n$(pipeline_info)\" }"

.PHONY: ssh
ssh:
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
export TERM=xterm-256color; \
ssh $(ssh_url)

.PHONY: docker
docker:
@:$(call check_defined, cardano_network)
@:$(call check_defined, env)
@:$(call check_defined, grafana_admin_password)
@:$(call check_defined, cmd)
export CARDANO_NETWORK=$(cardano_network); \
export DOCKER_HOST=ssh://$(ssh_url); \
export ENVIRONMENT=$(env); \
export GRAFANA_ADMIN_PASSWORD=$(grafana_admin_password); \
export BACKEND_TAG=$(backend_image_tag); \
export FRONTEND_TAG=$(frontend_image_tag); \
export CARDANO_NODE_TAG=$(cardano_node_image_tag); \
export CARDANO_DB_SYNC_TAG=$(cardano_db_sync_image_tag); \
ssh-keyscan $(docker_host) 2>/dev/null >> ~/.ssh/known_hosts; \
$(docker) compose -f $(docker_compose_file) -p $(compose_stack_name) $(cmd)
Loading

0 comments on commit d7a7fb6

Please sign in to comment.