image cache on cloudflare r2
1name: Deploy L4 to Production
2
3on:
4 push:
5 branches:
6 - main
7 workflow_dispatch:
8
9jobs:
10 deploy:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v4
14
15 - name: Setup Tailscale
16 uses: tailscale/github-action@v3
17 with:
18 oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
19 oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
20 tags: tag:ci
21 use-cache: "true"
22
23 - name: Configure SSH
24 run: |
25 mkdir -p ~/.ssh
26 echo "StrictHostKeyChecking accept-new" >> ~/.ssh/config
27
28 - name: Deploy to terebithia
29 run: |
30 ssh l4@terebithia << 'EOF'
31 cd /var/lib/l4/app
32 git fetch --all
33 git reset --hard origin/main
34 bun install
35 sudo /run/current-system/sw/bin/systemctl restart l4.service
36 EOF
37 - name: Health check
38 run: |
39 HEALTH_URL="https://l4.dunkirk.sh/health"
40 MAX_RETRIES=6
41 RETRY_DELAY=5
42
43 for i in $(seq 1 $MAX_RETRIES); do
44 echo "Health check attempt $i/$MAX_RETRIES..."
45
46 RESPONSE=$(curl -s -w "\n%{http_code}" "$HEALTH_URL" || echo "000")
47 HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
48 BODY=$(echo "$RESPONSE" | head -n-1)
49
50 if [ "$HTTP_CODE" = "200" ]; then
51 # Validate response contains "status":"ok"
52 if echo "$BODY" | grep -q '"status":"ok"'; then
53 echo "✅ Service is healthy (HTTP $HTTP_CODE)"
54 echo "Response: $BODY"
55 exit 0
56 else
57 echo "❌ Health check returned 200 but invalid body"
58 echo "Response: $BODY"
59 fi
60 else
61 echo "❌ Health check failed with HTTP $HTTP_CODE"
62 echo "Response: $BODY"
63 fi
64
65 if [ $i -lt $MAX_RETRIES ]; then
66 echo "Retrying in ${RETRY_DELAY}s..."
67 sleep $RETRY_DELAY
68 fi
69 done
70
71 echo "❌ Health check failed after $MAX_RETRIES attempts"
72 exit 1