Deployment
To make deployment a easy process, I created a Makefile with different commands allowing user to deploy application with almost Zero Downtime
dpl ?= .env
include $(dpl)
export $(shell sed 's/=.*//' $(dpl))
TAG_COMMIT := $(shell git rev-list --abbrev-commit --tags --max-count=1)
TAG := $(shell git describe --abbrev=0 --tags ${TAG_COMMIT} 2>/dev/null || true)
COMMIT := $(shell git rev-parse --short HEAD)
DATE := $(shell git log -1 --format=%cd --date=format:"%Y%m%d%H%M%S")
VERSION := v$(TAG:v%=%)-$(DATE)-$(COMMIT)
BLACK := $(shell tput -Txterm setaf 0)
RED := $(shell tput -Txterm setaf 1)
GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
LIGHTPURPLE := $(shell tput -Txterm setaf 4)
PURPLE := $(shell tput -Txterm setaf 5)
BLUE := $(shell tput -Txterm setaf 6)
WHITE := $(shell tput -Txterm setaf 7)
RESET := $(shell tput -Txterm sgr0)
APPLICATION_NAME := $(shell echo $(APP_NAME) | sed -e 's/[^[:alnum:]]/-/g' | tr -s '-' | tr A-Z a-z)
ifneq ($(shell git status --porcelain),)
VERSION := $(VERSION)-dirty
endif
FLAGS := -ldflags "-X github.com/sujit-baniya/fiber-boilerplate/app.Version=$(VERSION)"
BUILD_PATH := $(shell pwd)/build
PID := $(shell lsof -t -i:$(APP_PORT))
RELEASE_PATH := $(BUILD_PATH)/releases
SHARED_PATH := $(BUILD_PATH)/shared
CURRENT_PATH := $(BUILD_PATH)/current
CURRENT_RELEASE := "dev"
PREVIOUS_RELEASE := "dev"
ifneq ("$(wildcard $(CURRENT_PATH)/CURRENT-RELEASE)","")
CURRENT_RELEASE := $(shell cat $(CURRENT_PATH)/CURRENT-RELEASE)
endif
ifneq ("$(wildcard $(CURRENT_PATH)/PREVIOUS-RELEASE)","")
PREVIOUS_RELEASE := $(shell cat $(CURRENT_PATH)/PREVIOUS-RELEASE)
endif
ROLLBACK_RELEASE := $(RELEASE_PATH)/$(RELEASE_TAG)
LATEST_RELEASE := $(APPLICATION_NAME)-$(VERSION)
LATEST_RELEASE_PATH := $(RELEASE_PATH)/$(LATEST_RELEASE)
create-folder:
$(info $(GREEN)Create Release Folder: $(LATEST_RELEASE)$(RESET))
$(shell mkdir -p $(RELEASE_PATH)/$(LATEST_RELEASE))
$(shell mkdir -p $(SHARED_PATH)/$(STORAGE_PATH))
$(shell mkdir -p $(SHARED_PATH)/$(UPLOAD_PATH))
git-stash:
$(info $(GREEN)Stashing current changes$(RESET))
cd $(LATEST_RELEASE_PATH) && git stash
git-checkout:
$(info $(GREEN)Checkingout Master branch$(RESET))
cd $(LATEST_RELEASE_PATH) && git checkout master && git pull origin master
git-push:
$(info $(GREEN)Adding all changed files and push $(RESET))
cd $(LATEST_RELEASE_PATH) && git add . && git commit -m $(COMMIT_MESSAGE) && git push origin master
dev-push:
$(info $(GREEN)Adding all changed files and push for dev $(RESET))
git add . && git commit -m "$(COMMIT_MESSAGE)" && git push origin master
build-app:
$(info $(GREEN)Building the application: $(APPLICATION_NAME)$(RESET))
$(shell go build $(FLAGS) -o $(RELEASE_PATH)/$(LATEST_RELEASE)/$(APPLICATION_NAME) main.go)
copy-config:
$(info $(GREEN)Copying config, assets and .env file$(RESET))
$(shell cp .env $(RELEASE_PATH)/$(LATEST_RELEASE)/ && \
cp config.yml $(RELEASE_PATH)/$(LATEST_RELEASE)/ && \
cp -R assets $(RELEASE_PATH)/$(LATEST_RELEASE)/ \
)
install-fe-dependencies:
$(info $(GREEN)Installing Frontend dependencies$(RESET))
$(shell yarn install >/dev/null)
compile-fe:
$(info $(GREEN)Compiling Frontend assets$(RESET))
$(shell yarn install >/dev/null && \
yarn run prod >/dev/null || true \
)
copy-assets:
$(info $(GREEN)Copying Assets$(RESET))
$(shell cp -R public $(RELEASE_PATH)/$(LATEST_RELEASE)/ && \
cp -R resources $(RELEASE_PATH)/$(LATEST_RELEASE)/ \
)
create-symlink:
$(info $(GREEN)Creating Current folder symlink$(RESET))
$(shell ln -snf $(SHARED_PATH)/$(STORAGE_PATH) $(RELEASE_PATH)/$(LATEST_RELEASE)/$(STORAGE_PATH))
$(shell ln -snf $(SHARED_PATH)/$(UPLOAD_PATH) $(RELEASE_PATH)/$(LATEST_RELEASE)/$(UPLOAD_PATH))
$(shell ln -snf $(RELEASE_PATH)/$(LATEST_RELEASE) $(CURRENT_PATH))
$(shell echo $(CURRENT_RELEASE) > $(CURRENT_PATH)/PREVIOUS-RELEASE)
$(shell echo $(LATEST_RELEASE_PATH) > $(CURRENT_PATH)/CURRENT-RELEASE)
migrate:
$(info $(GREEN)Starting migrating$(RESET))
cd $(CURRENT_PATH) && ./$(APPLICATION_NAME) --migrate
build: create-folder git-checkout build-app copy-config copy-assets create-symlink migrate
deploy: build restart
push: install-fe-dependencies compile-fe dev-push
start:
$(info $(GREEN)Starting application$(RESET))
cd $(CURRENT_PATH) && ./$(APPLICATION_NAME) </dev/null &>/dev/null &
kill:
ifneq ($(PID),)
$(info $(RED)Stopping application on port $(APP_PORT)$(RESET))
kill -9 $(PID)
else
$(info $(YELLOW)Application not found on port $(APP_PORT)$(RESET))
endif
restart: kill start
rollback:
ifneq ($(PREVIOUS_RELEASE),)
$(info Rolling Back to Previous Release: $(PREVIOUS_RELEASE))
$(shell ln -snf $(PREVIOUS_RELEASE) $(CURRENT_PATH))
endif
rollback-to:
ifneq ($(wildcard $(ROLLBACK_RELEASE)),)
$(info Rolling Back to Release: $(ROLLBACK_RELEASE))
$(shell ln -snf $(ROLLBACK_RELEASE) $(CURRENT_PATH))
endif
run:
go run $(FLAGS) main.go
install:
go install $(FLAGS)
There are various commands involved while deployment to production. These commands are useful for development purpose as well.
Before deploying make sure you change the repository name (if you have changed it) for Flags on line:25
FLAGS := -ldflags "-X github.com/sujit-baniya/fiber-boilerplate/app.Version=$(VERSION)"
This script uses .env file so make sure .env is in-place when running the commands.
Here for deployment above command will create a build directory inside the project with three sub-directories
current - This is the symlink of latest release
releases - Contains the directories with different release versions
shared - Any files or folders required to be shared between the releases
Each release will be versioned under the format: <project-name>-v<Tag>-<YMDHIS>-<commit-hash>
For e.g. fiber-boilerplate-v0.0.1-20210131120000-1b1843
Command
Description
make create-folder
This command will create above mentioned three folders
for the release if not already exists
make git-checkout
This command will checkout the master branch and
pull latest changes
make git-push
This command will push all changes done on
production to repository
make dev-push
This command accept an argument COMMIT_MESSAGE
and
push the changes to repository from developers platform
For e.g.
make dev-push COMMIT_MESSAGE="Test"
make build-app
This command will create build the project to binary
to latest release folder
make copy-config
This command will copy .env, config.yml and assets
from project to latest release folder
make install-fe-dependencies
This command will install front end dependencies using yarn
Make sure you've installed nodejs and yarn
make compile-fe
This command will compile the front end UI to respective
public folder
make copy-assets
This command will copy the JS, CSS, Images, Fonts, and
html files from project to current release
make create-symlink
This command will create symlink for latest release and
shared directories to current release
make migrate
This command will migrate all database changes
make build
This command is composed of:
create-folder, git-checkout, build-app, copy-config,
copy-assets, create-symlink and migrate
make kill
This command will try to kill the PID using the port
make start
This command will start the current release
make restart
This command is composed of kill
and start
make deploy
This command is composed of build
and restart
make rollback
This command will rollback the release to previous release
make rollback-to
This command will rollback to specific release provided
as argument.
For e.g.
make rollback-to RELEASE_TAG=project-name-20210115171923-7dc9021
Building Project
You can build the project using command make build
You can deploy the project to production using make deploy
Easy Rollback
With the command make rollback
and make rollback-to
you can easily rollback to previous release version or specific release version
Last updated
Was this helpful?