Skip to content

Build and deploy

Build and deploy #1167

Workflow file for this run

name: Build and deploy
on:
# workflow_run:
# workflows: [Test and build]
# types:
# - completed
# branches:
# - master
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: false
default: 'info'
type: choice
options:
- info
- warning
- debug
env:
SSH_USER: ${{ secrets.SSH_USER }}
SSH_HOST: ${{ secrets.SSH_HOST }}
APP_NAME: market_data_notification
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
REGISTRY_USER: ${{ github.actor }}
jobs:
build_and_upload:
runs-on: ubuntu-latest
# TODO: Build and push multi-arch docker image locally, github ci supports arm64 or a better solution is found
steps:
# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v2
# - name: Login to GitHub Container Registry
# uses: docker/login-action@v2
# with:
# registry: ghcr.io
# # Can't use self-defined environment variables for some reason
# username: ${{ github.actor }}
# password: ${{ secrets.DOCKER_BUILD_PUSH_TOKEN }}
# - name: Setup SSH key
# env:
# REPO_SSH_PRIVATE_KEY: ${{ secrets.REPO_SSH_PRIVATE_KEY }}
# run: |
# mkdir secret
# echo "$REPO_SSH_PRIVATE_KEY" > secret/id_rsa
# - name: Build and push image
# uses: docker/build-push-action@v3
# with:
# secret-files: |
# "ssh_private_key=secret/id_rsa"
# push: true
# target: release
# tags: ghcr.io/${{ github.repository_owner }}/market_data_notification:${{ github.sha }}
# cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/market_data_notification:buildcache
# cache-to: type=registry,ref=ghcr.io/${{ github.repository_owner }}/market_data_notification:buildcache,mode=max
# - name: Teardown SSH key
# run: |
# rm -rf secret/id_rsa
- name: Delete old github package versions
uses: actions/delete-package-versions@v4
with:
package-name: 'market_data_notification'
package-type: 'container'
min-versions-to-keep: 50
token: ${{ secrets.DELETE_OLD_PACKAGE_TOKEN }}
health_check:
runs-on: ubuntu-latest
needs: [build_and_upload]
steps:
- name: Check whether market data notification is up
id: health_check
run: |
curl $SSH_HOST/healthz
notify_unsuccessful_health_check:
runs-on: ubuntu-latest
needs: [health_check]
if: ${{ failure() }}
steps:
- name: Send telegram notification unsuccessful run
env:
STOCKS_TELEGRAM_DEV_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_DEV_BOT_TOKEN }}
STOCKS_TELEGRAM_DEV_ID: ${{ secrets.STOCKS_TELEGRAM_DEV_ID }}
run: |
now=$(date +%Y-%m-%dT%H:%M:%S%:z)
text=$(echo "\[Github action\] Market data notification backend build and deploy failed at $now. Workflow: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | sed 's~[[:blank:]]~%20~g')
curl "https://api.telegram.org/bot${STOCKS_TELEGRAM_DEV_BOT_TOKEN}/sendMessage?chat_id=${STOCKS_TELEGRAM_DEV_ID}&text=$text"
exit 1
deploy:
runs-on: ubuntu-latest
needs: [health_check]
steps:
- uses: actions/checkout@v3
- name: Configure SSH
id: ssh
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh/
echo "$SSH_PRIVATE_KEY" > ~/.ssh/market_data_notification_rsa
chmod 600 ~/.ssh/market_data_notification_rsa
SSH_HOST_IP=$(nslookup $SSH_HOST | tail -n 2 | head -n 1 | cut -d ' ' -f 2)
echo "host name: $SSH_HOST, host ip address: $SSH_HOST_IP"
cat << EOF >> ~/.ssh/config
Host production
HostName $SSH_HOST
User $SSH_USER
IdentityFile ~/.ssh/market_data_notification_rsa
StrictHostKeyChecking no
EOF
- name: SSH into server, pull image, run container
id: deploy
env:
DOCKER_PULL_PASSWORD: ${{ secrets.DOCKER_PULL_TOKEN }}
STOCKS_TELEGRAM_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_BOT_TOKEN }}
STOCKS_TELEGRAM_CHANNEL_ID: ${{ secrets.STOCKS_TELEGRAM_CHANNEL_ID }}
STOCKS_TELEGRAM_ADMIN_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_ADMIN_BOT_TOKEN }}
STOCKS_TELEGRAM_ADMIN_ID: ${{ secrets.STOCKS_TELEGRAM_ADMIN_ID }}
STOCKS_TELEGRAM_DEV_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_DEV_BOT_TOKEN }}
STOCKS_TELEGRAM_DEV_ID: ${{ secrets.STOCKS_TELEGRAM_DEV_ID }}
CRYPTO_TELEGRAM_BOT_TOKEN: ${{ secrets.CRYPTO_TELEGRAM_BOT_TOKEN }}
CRYPTO_TELEGRAM_CHANNEL_ID: ${{ secrets.CRYPTO_TELEGRAM_CHANNEL_ID }}
CRYPTO_TELEGRAM_ADMIN_BOT_TOKEN: ${{ secrets.CRYPTO_TELEGRAM_ADMIN_BOT_TOKEN }}
CRYPTO_TELEGRAM_ADMIN_ID: ${{ secrets.CRYPTO_TELEGRAM_ADMIN_ID }}
CRYPTO_TELEGRAM_DEV_BOT_TOKEN: ${{ secrets.CRYPTO_TELEGRAM_DEV_BOT_TOKEN }}
CRYPTO_TELEGRAM_DEV_ID: ${{ secrets.CRYPTO_TELEGRAM_DEV_ID }}
SIMULATE_TRADINGVIEW_TRAFFIC: ${{ secrets.SIMULATE_TRADINGVIEW_TRAFFIC }}
IS_TESTING_TELEGRAM: ${{ secrets.IS_TESTING_TELEGRAM }}
TRADING_VIEW_IPS: ${{ secrets.TRADING_VIEW_IPS }}
WHITELIST_IPS: ${{ secrets.WHITELIST_IPS }}
TRADING_VIEW_WEBHOOK_SECRET: ${{ secrets.TRADING_VIEW_WEBHOOK_SECRET }}
DISABLE_TELEGRAM: ${{ secrets.DISABLE_TELEGRAM }}
REDIS_HOST: ${{ secrets.REDIS_HOST }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}
REDIS_DB: ${{ secrets.REDIS_DB }}
MESSARI_ASSET_METRICS_SHA256: ${{ secrets.MESSARI_ASSET_METRICS_SHA256 }}
API_AUTH_TOKEN: ${{ secrets.API_AUTH_TOKEN }}
AUTH_EXCLUDE_ENDPOINTS: ${{ secrets.AUTH_EXCLUDE_ENDPOINTS }}
SHOULD_COMPARE_STOCKS_VOLUME_RANK: ${{ vars.SHOULD_COMPARE_STOCKS_VOLUME_RANK }}
DISPLAY_VIX_FUTURES_CONTANGO_DECREASE_PAST_N_DAYS: ${{ vars.DISPLAY_VIX_FUTURES_CONTANGO_DECREASE_PAST_N_DAYS }}
SELENIUM_REMOTE_MODE: ${{ vars.SELENIUM_REMOTE_MODE }}
SELENIUM_STEALTH: ${{ vars.SELENIUM_STEALTH }}
ENV: ${{ vars.ENV }}
SHOULD_SEND_STOCKS_SENTIMENT_MESSAGE: ${{ vars.SHOULD_SEND_STOCKS_SENTIMENT_MESSAGE }}
CMC_COIN_PRICE_CHANGE_24H_PERCENTAGE_THRESHOLD: ${{ vars.CMC_COIN_PRICE_CHANGE_24H_PERCENTAGE_THRESHOLD }}
CMC_COIN_MARKET_CAP_CHANGE_24H_PERCENTAGE_THRESHOLD: ${{ vars.CMC_COIN_MARKET_CAP_CHANGE_24H_PERCENTAGE_THRESHOLD }}
run: |
ssh production << EOF
set -e
echo "Logging into container registry"
echo $DOCKER_PULL_PASSWORD | docker login ghcr.io -u $REGISTRY_USER --password-stdin
echo "Pulling image"
docker pull "$IMAGE_REGISTRY/$APP_NAME:$GITHUB_SHA"
echo "Stopping existing container"
docker stop $APP_NAME || true
docker rm $APP_NAME || true
docker stop chrome || true
docker rm chrome || true
echo "Starting new container"
docker run --name $APP_NAME -p 8080:8080 --network host --memory="512m" --cpus="0.5" -e ENV=$ENV -e STOCKS_TELEGRAM_BOT_TOKEN=$STOCKS_TELEGRAM_BOT_TOKEN \
-e STOCKS_TELEGRAM_CHANNEL_ID=$STOCKS_TELEGRAM_CHANNEL_ID -e STOCKS_TELEGRAM_ADMIN_BOT_TOKEN=$STOCKS_TELEGRAM_ADMIN_BOT_TOKEN \
-e STOCKS_TELEGRAM_ADMIN_ID=$STOCKS_TELEGRAM_ADMIN_ID -e STOCKS_TELEGRAM_DEV_BOT_TOKEN=$STOCKS_TELEGRAM_DEV_BOT_TOKEN \
-e STOCKS_TELEGRAM_DEV_ID=$STOCKS_TELEGRAM_DEV_ID -e CRYPTO_TELEGRAM_BOT_TOKEN=$CRYPTO_TELEGRAM_BOT_TOKEN \
-e CRYPTO_TELEGRAM_CHANNEL_ID=$CRYPTO_TELEGRAM_CHANNEL_ID -e CRYPTO_TELEGRAM_ADMIN_BOT_TOKEN=$CRYPTO_TELEGRAM_ADMIN_BOT_TOKEN \
-e CRYPTO_TELEGRAM_ADMIN_ID=$CRYPTO_TELEGRAM_ADMIN_ID -e CRYPTO_TELEGRAM_DEV_BOT_TOKEN=$CRYPTO_TELEGRAM_DEV_BOT_TOKEN \
-e CRYPTO_TELEGRAM_DEV_ID=$CRYPTO_TELEGRAM_DEV_ID -e SIMULATE_TRADINGVIEW_TRAFFIC=$SIMULATE_TRADINGVIEW_TRAFFIC \
-e IS_TESTING_TELEGRAM=$IS_TESTING_TELEGRAM -e TRADING_VIEW_IPS=$TRADING_VIEW_IPS -e WHITELIST_IPS=$WHITELIST_IPS \
-e TRADING_VIEW_WEBHOOK_SECRET=$TRADING_VIEW_WEBHOOK_SECRET \
-e DISABLE_TELEGRAM=$DISABLE_TELEGRAM -e REDIS_HOST=$REDIS_HOST -e REDIS_PORT=$REDIS_PORT -e REDIS_DB=$REDIS_DB \
-e MESSARI_ASSET_METRICS_SHA256=$MESSARI_ASSET_METRICS_SHA256 -e SHOULD_COMPARE_STOCKS_VOLUME_RANK=$SHOULD_COMPARE_STOCKS_VOLUME_RANK \
-e DISPLAY_VIX_FUTURES_CONTANGO_DECREASE_PAST_N_DAYS=$DISPLAY_VIX_FUTURES_CONTANGO_DECREASE_PAST_N_DAYS \
-e SELENIUM_REMOTE_MODE=$SELENIUM_REMOTE_MODE -e SELENIUM_STEALTH=$SELENIUM_STEALTH \
-e SHOULD_SEND_STOCKS_SENTIMENT_MESSAGE=$SHOULD_SEND_STOCKS_SENTIMENT_MESSAGE \
-e API_AUTH_TOKEN=$API_AUTH_TOKEN -e AUTH_EXCLUDE_ENDPOINTS=$AUTH_EXCLUDE_ENDPOINTS \
-e CMC_COIN_PRICE_CHANGE_24H_PERCENTAGE_THRESHOLD=$CMC_COIN_PRICE_CHANGE_24H_PERCENTAGE_THRESHOLD \
-e CMC_COIN_MARKET_CAP_CHANGE_24H_PERCENTAGE_THRESHOLD=$CMC_COIN_MARKET_CAP_CHANGE_24H_PERCENTAGE_THRESHOLD \
-d "$IMAGE_REGISTRY/$APP_NAME:$GITHUB_SHA"
echo "Starting chrome container"
# peak memory usage is around 600m
docker run --name chrome -p 4444:4444 -p 5900:5900 -p 7900:7900 --network host --memory="1g" --cpus="1" -d seleniarm/standalone-chromium:114.0-20230615
sleep 3
docker ps
docker image prune -fa
EOF
rm -rf ~/.ssh
notify_unsuccessful:
runs-on: ubuntu-latest
needs: [deploy]
if: ${{ failure() }}
steps:
- name: Send telegram notification unsuccessful run
env:
STOCKS_TELEGRAM_DEV_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_DEV_BOT_TOKEN }}
STOCKS_TELEGRAM_DEV_ID: ${{ secrets.STOCKS_TELEGRAM_DEV_ID }}
run: |
now=$(date +%Y-%m-%dT%H:%M:%S%:z)
text=$(echo "\[Github action\] Market data notification backend build and deploy failed at $now. Workflow: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | sed 's~[[:blank:]]~%20~g')
curl "https://api.telegram.org/bot${STOCKS_TELEGRAM_DEV_BOT_TOKEN}/sendMessage?chat_id=${STOCKS_TELEGRAM_DEV_ID}&text=$text"
notify_successful:
runs-on: ubuntu-latest
needs: [deploy]
steps:
- name: Send telegram notification successful run
env:
STOCKS_TELEGRAM_DEV_BOT_TOKEN: ${{ secrets.STOCKS_TELEGRAM_DEV_BOT_TOKEN }}
STOCKS_TELEGRAM_DEV_ID: ${{ secrets.STOCKS_TELEGRAM_DEV_ID }}
run: |
now=$(date +%Y-%m-%dT%H:%M:%S%:z)
text=$(echo "\[Github action\] Market data notification backend build and deploy succeeded at $now. Workflow: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | sed 's~[[:blank:]]~%20~g')
curl "https://api.telegram.org/bot${STOCKS_TELEGRAM_DEV_BOT_TOKEN}/sendMessage?chat_id=${STOCKS_TELEGRAM_DEV_ID}&text=$text"