1- name : Deploy
1+ name : Build, Test and Deploy Discord Bot to VPS
22
33on :
44 workflow_dispatch : # Manual trigger only
1010 # - '.gitignore'
1111 # - 'LICENSE'
1212
13- concurrency :
14- group : ${{ github.workflow }}-${{ github.ref }}
15- cancel-in-progress : false
16-
1713jobs :
18- build-test-and- deploy :
14+ build-test-deploy :
1915 runs-on : ubuntu-latest
16+
2017 steps :
21- - name : Checkout
18+ - name : Checkout code
2219 uses : actions/checkout@v4
2320
24- - name : Setup Node.js
21+ - name : Set up Node
2522 uses : actions/setup-node@v4
2623 with :
2724 node-version-file : .nvmrc
@@ -37,91 +34,41 @@ jobs:
3734 - name : Lint
3835 run : npm run lint
3936
40- - name : Build
37+ - name : Build bot
4138 run : npm run build:ci
42- env :
43- DISCORD_TOKEN : ${{ secrets.DISCORD_TOKEN }}
44- CLIENT_ID : ${{ secrets.CLIENT_ID }}
45- GUIDES_CHANNEL_ID : ${{ secrets.GUIDES_CHANNEL_ID }}
46- GUIDES_TRACKER_PATH : ~/apps/webdev-bot/shared/guides-tracker.json
4739
4840 - name : Run tests
4941 run : npm run test:ci
5042
51- - name : Package artifact
52- run : |
53- tar -czf release.tar.gz dist package.json package-lock.json .nvmrc || tar -czf release.tar.gz dist package.json .nvmrc
54-
55- - name : Create .env file from secrets
56- env :
57- DISCORD_TOKEN : ${{ secrets.DISCORD_TOKEN }}
58- CLIENT_ID : ${{ secrets.CLIENT_ID }}
59- GUIDES_CHANNEL_ID : ${{ secrets.GUIDES_CHANNEL_ID }}
60- run : |
61- set -euo pipefail
62- printf "DISCORD_TOKEN=%s\n" "$DISCORD_TOKEN" > .env
63- printf "CLIENT_ID=%s\n" "$CLIENT_ID" >> .env
64- printf "NODE_ENV=production\n" >> .env
65- printf "GUIDES_CHANNEL_ID=%s\n" "$GUIDES_CHANNEL_ID" >> .env
66- printf "GUIDES_TRACKER_PATH=~/apps/webdev-bot/shared/guides-tracker.json\n" >> .env
67-
68- - name : Copy artifact to VPS
69- env :
70- SSH_HOST : ${{ secrets.SSH_HOST }}
71- SSH_USER : ${{ secrets.SSH_USER }}
72- SSH_PORT : ${{ secrets.SSH_PORT }}
73- SSH_KEY : ${{ secrets.SSH_KEY }}
74- run : |
75- mkdir -p ~/.ssh
76- echo "$SSH_KEY" > ~/.ssh/id_ed25519
77- chmod 600 ~/.ssh/id_ed25519
78- ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST "mkdir -p ~/apps/webdev-bot/releases"
79- scp -i ~/.ssh/id_ed25519 -P ${SSH_PORT:-22} -o StrictHostKeyChecking=no release.tar.gz $SSH_USER@$SSH_HOST:~/apps/webdev-bot/releases/release.tar.gz
43+ - name : Package build output
44+ run : tar czf bot-build.tar.gz ./dist
8045
81- - name : Upload .env to VPS
82- env :
83- SSH_HOST : ${{ secrets.SSH_HOST }}
84- SSH_USER : ${{ secrets.SSH_USER }}
85- SSH_PORT : ${{ secrets.SSH_PORT }}
86- SSH_KEY : ${{ secrets.SSH_KEY }}
87- APP_DIR : ${{ secrets.APP_DIR }}
88- run : |
89- mkdir -p ~/.ssh
90- echo "$SSH_KEY" > ~/.ssh/id_ed25519
91- chmod 600 ~/.ssh/id_ed25519
92- ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST "mkdir -p ${APP_DIR:-\"~/apps/webdev-bot\"}/shared && chmod 700 ${APP_DIR:-\"~/apps/webdev-bot\"}/shared"
93- scp -i ~/.ssh/id_ed25519 -P ${SSH_PORT:-22} -o StrictHostKeyChecking=no .env $SSH_USER@$SSH_HOST:${APP_DIR:-"~/apps/webdev-bot"}/shared/.env
94- ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST "chmod 600 ${APP_DIR:-\"~/apps/webdev-bot\"}/shared/.env"
46+ - name : Copy build artifact to VPS
47+ 48+ with :
49+ host : ${{ secrets.VPS_HOST }}
50+ username : ${{ secrets.VPS_USER }}
51+ key : ${{ secrets.VPS_SSH_KEY }}
52+ source : " bot-build.tar.gz"
53+ target : " /home/${{ secrets.VPS_USER }}/discord-bot/"
9554
96- - name : Deploy on VPS
97- env :
98- SSH_HOST : ${{ secrets.SSH_HOST }}
99- SSH_USER : ${{ secrets.SSH_USER }}
100- SSH_PORT : ${{ secrets.SSH_PORT }}
101- SSH_KEY : ${{ secrets.SSH_KEY }}
102- APP_DIR : ${{ secrets.APP_DIR }}
103- run : |
104- mkdir -p ~/.ssh
105- echo "$SSH_KEY" > ~/.ssh/id_ed25519
106- chmod 600 ~/.ssh/id_ed25519
107- ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST << 'EOF'
108- set -euo pipefail
109- APP_DIR=${APP_DIR:-"~/apps/webdev-bot"}
110- mkdir -p "$APP_DIR/current" "$APP_DIR/releases" "$APP_DIR/shared"
111- cd "$APP_DIR"
112- rm -rf current/*
113- tar -xzf releases/release.tar.gz -C current
114- cd current
115- # Load env from shared/.env for the PM2 process
116- set -a
117- if [ -f "$APP_DIR/shared/.env" ]; then . "$APP_DIR/shared/.env"; fi
118- set +a
119- if [ -f package-lock.json ]; then
120- npm ci --omit=dev --no-audit --no-fund || true
121- else
122- npm install --omit=dev --no-audit --no-fund || true
123- fi
124- pm2 describe webdev-bot >/dev/null 2>&1 && pm2 restart webdev-bot || pm2 start "node dist/index.js" --name webdev-bot
125- pm2 save || true
126- EOF
55+ - name : Create .env file on VPS
56+ 57+ with :
58+ host : ${{ secrets.VPS_HOST }}
59+ username : ${{ secrets.VPS_USER }}
60+ key : ${{ secrets.VPS_SSH_KEY }}
61+ script : |
62+ echo "DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }}" > /home/${{ secrets.VPS_USER }}/discord-bot/.env
63+ echo "CLIENT_ID=${{ secrets.CLIENT_ID }}" >> /home/${{ secrets.VPS_USER }}/discord-bot/.env
12764
65+ - name : Extract and restart bot on VPS
66+ 67+ with :
68+ host : ${{ secrets.VPS_HOST }}
69+ username : ${{ secrets.VPS_USER }}
70+ key : ${{ secrets.VPS_SSH_KEY }}
71+ script : |
72+ cd /home/${{ secrets.VPS_USER }}/discord-bot/
73+ tar xzf bot-build.tar.gz
74+ pm2 restart bot || pm2 start ./dist/index.js --name bot
0 commit comments