Skip to content

Commit 4ebb83d

Browse files
committed
feat: add GitHub Actions workflows for deployment and testing
1 parent b6831c2 commit 4ebb83d

2 files changed

Lines changed: 168 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: Deploy
2+
3+
on:
4+
workflow_dispatch: # Manual trigger only
5+
# Uncomment below when VPS is ready:
6+
# push:
7+
# branches: [ "main" ]
8+
# paths-ignore:
9+
# - 'docs/**'
10+
# - '.gitignore'
11+
# - 'LICENSE'
12+
13+
concurrency:
14+
group: ${{ github.workflow }}-${{ github.ref }}
15+
cancel-in-progress: false
16+
17+
jobs:
18+
build-test-and-deploy:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Setup Node.js
25+
uses: actions/setup-node@v4
26+
with:
27+
node-version-file: .nvmrc
28+
29+
- name: Install dependencies
30+
run: |
31+
if [ -f package-lock.json ]; then
32+
npm ci --no-audit --no-fund
33+
else
34+
npm install --no-audit --no-fund
35+
fi
36+
37+
- name: Lint
38+
run: npm run lint
39+
40+
- name: Build
41+
run: npm run build:ci
42+
env:
43+
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
44+
CLIENT_ID: ${{ secrets.CLIENT_ID }}
45+
46+
- name: Run tests
47+
run: npm test
48+
49+
- name: Package artifact
50+
run: |
51+
tar -czf release.tar.gz dist package.json package-lock.json .nvmrc || tar -czf release.tar.gz dist package.json .nvmrc
52+
53+
- name: Create .env file from secrets
54+
env:
55+
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
56+
APPLICATION_ID: ${{ secrets.APPLICATION_ID }}
57+
run: |
58+
set -euo pipefail
59+
printf "DISCORD_TOKEN=%s\n" "$DISCORD_TOKEN" > .env
60+
printf "APPLICATION_ID=%s\n" "$APPLICATION_ID" >> .env
61+
printf "NODE_ENV=production\n" >> .env
62+
63+
- name: Copy artifact to VPS
64+
env:
65+
SSH_HOST: ${{ secrets.SSH_HOST }}
66+
SSH_USER: ${{ secrets.SSH_USER }}
67+
SSH_PORT: ${{ secrets.SSH_PORT }}
68+
SSH_KEY: ${{ secrets.SSH_KEY }}
69+
run: |
70+
mkdir -p ~/.ssh
71+
echo "$SSH_KEY" > ~/.ssh/id_ed25519
72+
chmod 600 ~/.ssh/id_ed25519
73+
ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST "mkdir -p ~/apps/webdev-bot/releases"
74+
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
75+
76+
- name: Upload .env to VPS
77+
env:
78+
SSH_HOST: ${{ secrets.SSH_HOST }}
79+
SSH_USER: ${{ secrets.SSH_USER }}
80+
SSH_PORT: ${{ secrets.SSH_PORT }}
81+
SSH_KEY: ${{ secrets.SSH_KEY }}
82+
APP_DIR: ${{ secrets.APP_DIR }}
83+
run: |
84+
mkdir -p ~/.ssh
85+
echo "$SSH_KEY" > ~/.ssh/id_ed25519
86+
chmod 600 ~/.ssh/id_ed25519
87+
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"
88+
scp -i ~/.ssh/id_ed25519 -P ${SSH_PORT:-22} -o StrictHostKeyChecking=no .env $SSH_USER@$SSH_HOST:${APP_DIR:-"~/apps/webdev-bot"}/shared/.env
89+
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"
90+
91+
- name: Deploy on VPS
92+
env:
93+
SSH_HOST: ${{ secrets.SSH_HOST }}
94+
SSH_USER: ${{ secrets.SSH_USER }}
95+
SSH_PORT: ${{ secrets.SSH_PORT }}
96+
SSH_KEY: ${{ secrets.SSH_KEY }}
97+
APP_DIR: ${{ secrets.APP_DIR }}
98+
run: |
99+
mkdir -p ~/.ssh
100+
echo "$SSH_KEY" > ~/.ssh/id_ed25519
101+
chmod 600 ~/.ssh/id_ed25519
102+
ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 -p ${SSH_PORT:-22} $SSH_USER@$SSH_HOST << 'EOF'
103+
set -euo pipefail
104+
APP_DIR=${APP_DIR:-"~/apps/webdev-bot"}
105+
mkdir -p "$APP_DIR/current" "$APP_DIR/releases" "$APP_DIR/shared"
106+
cd "$APP_DIR"
107+
rm -rf current/*
108+
tar -xzf releases/release.tar.gz -C current
109+
cd current
110+
# Load env from shared/.env for the PM2 process
111+
set -a
112+
if [ -f "$APP_DIR/shared/.env" ]; then . "$APP_DIR/shared/.env"; fi
113+
set +a
114+
if [ -f package-lock.json ]; then
115+
npm ci --omit=dev --no-audit --no-fund || true
116+
else
117+
npm install --omit=dev --no-audit --no-fund || true
118+
fi
119+
pm2 describe webdev-bot >/dev/null 2>&1 && pm2 restart webdev-bot || pm2 start "node dist/index.js" --name webdev-bot
120+
pm2 save || true
121+
EOF
122+

.github/workflows/test.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Test
2+
3+
on:
4+
pull_request:
5+
branches: [ "**" ]
6+
paths-ignore:
7+
- 'docs/**'
8+
- '.gitignore'
9+
- 'LICENSE'
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
build-and-test:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
node-version-file: .nvmrc
26+
27+
- name: Install dependencies
28+
run: |
29+
if [ -f package-lock.json ]; then
30+
npm ci --no-audit --no-fund
31+
else
32+
npm install --no-audit --no-fund
33+
fi
34+
35+
- name: Lint
36+
run: npm run lint
37+
38+
- name: Build
39+
run: npm run build:ci
40+
env:
41+
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
42+
CLIENT_ID: ${{ secrets.CLIENT_ID }}
43+
44+
- name: Run tests
45+
run: npm test
46+

0 commit comments

Comments
 (0)