Skip to content

Commit

Permalink
Chore/blue green deployment (#264)
Browse files Browse the repository at this point in the history
* ci: add initial blue-green deployment

* ci: init deployment using blue-green

* ci: remove nginx operation

* ci: check npm existence

* ci: re-run after creating symlink directly on machine

* ci: export nvm

* ci: perform nginx reload

* ci: use target_port as env.PORT

* ci: fix env

* ci: fix sed

* ci: comment out sed nginx

* ci: remove nginx

* ci: remove port

* ci: inject port directly during pm2 startup

* ci: disable env first

* ci: disable env first

* ci: write env via ssh

* ci: enable nginx update

* ci: use master branch
  • Loading branch information
wildan3105 authored Nov 18, 2024
1 parent 423d9fc commit 14f1183
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 60 deletions.
133 changes: 75 additions & 58 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,99 @@ on:
jobs:
deploy:
runs-on: ubuntu-latest

env:
PROJECT_REPO: git@github.com:wildan3105/github-langs.git
BLUE_NAME: "blue"
GREEN_NAME: "green"
BLUE_PORT: 3000
GREEN_PORT: 3001
NGINX_CONF: /etc/nginx/sites-available/gitstats.wildans.site
BLUE_DIR: /var/www/html/blue
GREEN_DIR: /var/www/html/green
steps:
- name: Check out the code
uses: actions/checkout@v3

- name: Verify SSH connection and deploy
uses: appleboy/ssh-action@v0.1.6
- name: Deployment
uses: appleboy/ssh-action@v1.2.0
env:
ACTIVE_ENV: ""
TARGET_ENV: ""
TARGET_DIR: ""
TARGET_PORT: ""
TOKEN: ""
ENV: ""
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USERNAME }}
password: ${{ secrets.VPS_PASSWORD }}
port: 22
envs: ACTIVE_ENV,TARGET_ENV,TARGET_DIR,TARGET_PORT, TOKEN, ENV
script: |
# Set paths for npm and node
export PATH=$PATH:/root/.nvm/versions/node/v18.10.0/bin
# Define directories
TARGET_DIR="/var/www/html"
TEMP_DIR="${TARGET_DIR}/tmp"
SYMLINK="${TARGET_DIR}/current"
# Prepare the temporary area
echo "Preparing the temporary deployment directory..."
sudo rm -rf $TEMP_DIR
sudo mkdir -p $TEMP_DIR
# Clone the repo into the temporary directory
echo "Cloning repository to the temporary directory..."
git clone git@github.com:wildan3105/github-langs.git $TEMP_DIR
# Ensure necessary files are present
if [ -f "$TEMP_DIR/src/index.js" ]; then
echo "Entry point found in the temporary directory"
echo "Deployment using blue-green is started..."
export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh
echo "Determining the current active environment..."
if grep -q "proxy_pass http://localhost:${{ env.BLUE_PORT }};" "${{ env.NGINX_CONF }}"; then
export ACTIVE_ENV="${{ env.BLUE_NAME }}"
elif grep -q "proxy_pass http://localhost:${{ env.GREEN_PORT }};" "${{ env.NGINX_CONF }}"; then
export ACTIVE_ENV="${{ env.GREEN_NAME }}"
else
echo "Error: Entry point not found in the temporary directory!"
echo "error: could not determine active environment" >&2
exit 1
fi
# Set environment variables
export ENV=${{ secrets.ENV }}
export TOKEN=${{ secrets.TOKEN }}
# Install dependencies
echo "Installing dependencies..."
cd $TEMP_DIR
npm install
# Gracefully stop the existing application if it's running on port 5000
if lsof -i:5000; then
echo "Stopping existing application running on port 5000..."
PID=$(lsof -t -i:5000)
sudo kill -9 $PID || echo "Failed to kill process with PID $PID"
echo "Active env is $ACTIVE_ENV"
echo "Set the target environment..."
if [ "$ACTIVE_ENV" == "blue" ]; then
export TARGET_ENV="${{ env.GREEN_NAME }}"
export TARGET_PORT="${{ env.GREEN_PORT }}"
export TARGET_DIR="${{ env.GREEN_DIR }}"
elif [ "$ACTIVE_ENV" == "green" ]; then
export TARGET_ENV="${{ env.BLUE_NAME }}"
export TARGET_PORT="${{ env.BLUE_PORT }}"
export TARGET_DIR="${{ env.BLUE_DIR }}"
else
echo "error: could not determine target environment" >&2
exit 1
fi
# Start the application in the background using Node
echo "Starting the application..."
ENV=$ENV TOKEN=$TOKEN npm run start-prod
echo "The upcoming target environment is as follows:"
echo "Target env: $TARGET_ENV"
echo "Target port: $TARGET_PORT"
echo "Target dir: $TARGET_DIR"
# Switch symlink atomically
echo "Updating symlink to point to the new temporary directory..."
sudo ln -sfn $TEMP_DIR $SYMLINK
echo "Cloning the repository..."
rm -rf $TARGET_DIR
mkdir -p $TARGET_DIR
git clone ${{ env.PROJECT_REPO }} $TARGET_DIR
echo "Repository cloned"
# Verify that the symlink points to the latest deployment
echo "Deployment verification:"
ls -l $SYMLINK
# delay before performing healthcheck
sleep 10s
echo "Writing to environment variables..."
export ENV="${{ secrets.ENV }}"
export TOKEN="${{ secrets.TOKEN }}"
echo "Environment variables written"
# perform healthcheck
echo "Performing health check on http://localhost:5000..."
STATUS_CODE=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:5000)
echo "Install and build application..."
cd $TARGET_DIR
npm install
echo "Dependencies installed and app built"
if [ "$STATUS_CODE" -ne 200 ]; then
echo "Health check failed with status code: $STATUS_CODE"
exit 1
echo "Start or restart application via PM2..."
if pm2 list | grep -q "$TARGET_ENV"; then
echo "App detected. Restarting the app..."
pm2 restart "$TARGET_ENV" || { echo "Failed to restart app"; exit 1; }
else
echo "Health check passed with status code: $STATUS_CODE"
echo "App is not started yet. Starting the app..."
PORT=$TARGET_PORT pm2 start npm --name "$TARGET_ENV" -- run start || { echo "Failed to start app"; exit 1; }
fi
echo "Application started/restarted"
echo "Adding delay to ensure the app is ready..."
sleep 10s
echo "Delay finished"
echo "Update nginx port..."
sudo sed -i "s|proxy_pass http://localhost:[0-9]*;|proxy_pass http://localhost:$TARGET_PORT;|" "${{ env.NGINX_CONF }}"
sudo nginx -s reload
echo "Nginx updated"
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
},
"main": "index.js",
"scripts": {
"start-dev": "node_modules/.bin/pm2 start src/index.js --watch --name githublangs | gulp",
"start-prod": "node_modules/.bin/pm2 stop githublangs || true && node_modules/.bin/pm2 start -f src/index.js --name githublangs | gulp",
"start": "node src/index.js | gulp",
"lint": "eslint '**/*.js' --ignore-pattern node_modules/",
"lint:fix": "eslint --fix '**/*.js' --ignore-pattern node_modules/",
"mocha": "mocha",
Expand Down

0 comments on commit 14f1183

Please sign in to comment.