Skip to content

Commit 5d1695e

Browse files
committed
feat: Add GitHub Actions auto-deploy with zero-downtime restarts
DEPLOYMENT AUTOMATION: - GitHub Actions workflow for automatic deployment on push to main - Zero-downtime deployments with Puma phased restarts - Health check verification after deployment - Manual trigger support via Actions tab PRODUCTION CONFIGURATION: - Puma production config with 2 workers and preload_app - Worker-specific setup for database reconnection - Phased restart support (SIGUSR1 signal) - Zero-downtime deployment capabilities SYSTEMD SERVICES: - core-puma.service: Puma web server with reload support - core-solidqueue.service: Background job worker - Both configured with auto-restart and logging COMPREHENSIVE DOCUMENTATION: - Complete deployment guide (docs/DEPLOYMENT.md) - Initial setup instructions (VPS, Ruby, PostgreSQL, Nginx, SSL) - GitHub Actions CI/CD setup with secrets - Manual deployment procedures - Troubleshooting guide and maintenance tasks DEPLOYMENT FLOW: 1. Push to main → GitHub Actions triggered 2. SSH to VPS → Pull + Bundle + Assets + Migrate 3. Reload Puma (zero-downtime) → Restart Solid Queue 4. Health check → Production live Benefits: - Automatic deployments (no manual SSH needed) - Zero-downtime (Puma phased restart) - Quick deployments (~2-3 minutes) - Rollback capability - Production-ready configuration Ready for VPS deployment!
1 parent 6d87fdd commit 5d1695e

5 files changed

Lines changed: 814 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: Deploy to Production
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch: # Allow manual trigger
8+
9+
jobs:
10+
deploy:
11+
name: Deploy to VPS
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Ruby
19+
uses: ruby/setup-ruby@v1
20+
with:
21+
ruby-version: '3.3'
22+
bundler-cache: true
23+
24+
- name: Install SSH key
25+
uses: shimataro/ssh-key-action@v2
26+
with:
27+
key: ${{ secrets.VPS_SSH_KEY }}
28+
known_hosts: unnecessary
29+
if_key_exists: replace
30+
31+
- name: Add VPS to known hosts
32+
run: ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts
33+
34+
- name: Deploy to VPS
35+
env:
36+
VPS_HOST: ${{ secrets.VPS_HOST }}
37+
VPS_USER: ${{ secrets.VPS_USER }}
38+
run: |
39+
ssh $VPS_USER@$VPS_HOST << 'ENDSSH'
40+
set -e
41+
42+
echo "🚀 Starting deployment..."
43+
44+
cd ~/core
45+
46+
# Pull latest changes
47+
echo "📥 Pulling latest code from main..."
48+
git fetch origin
49+
git reset --hard origin/main
50+
51+
# Install dependencies
52+
echo "📦 Installing dependencies..."
53+
bundle install --deployment --without development test
54+
55+
# Precompile assets
56+
echo "🎨 Precompiling assets..."
57+
RAILS_ENV=production bundle exec rails assets:precompile
58+
59+
# Run database migrations
60+
echo "🗄️ Running database migrations..."
61+
RAILS_ENV=production bundle exec rails db:migrate
62+
63+
# Restart services (zero-downtime)
64+
echo "🔄 Restarting Puma (zero-downtime)..."
65+
sudo systemctl reload core-puma
66+
67+
echo "🔄 Restarting Solid Queue..."
68+
sudo systemctl restart core-solidqueue
69+
70+
# Verify deployment
71+
echo "✅ Deployment complete!"
72+
echo "📊 App status:"
73+
sudo systemctl status core-puma --no-pager -l
74+
75+
ENDSSH
76+
77+
- name: Verify deployment
78+
env:
79+
VPS_HOST: ${{ secrets.VPS_HOST }}
80+
VPS_USER: ${{ secrets.VPS_USER }}
81+
run: |
82+
# Wait for app to be ready
83+
sleep 5
84+
85+
# Check if site is responding
86+
if curl -f -s -o /dev/null https://rectorspace.com/up; then
87+
echo "✅ Production site is healthy!"
88+
else
89+
echo "❌ Production site health check failed!"
90+
exit 1
91+
fi
92+
93+
- name: Notify deployment success
94+
if: success()
95+
run: |
96+
echo "✅ Deployment successful!"
97+
echo "🌐 Visit: https://rectorspace.com"
98+
99+
- name: Notify deployment failure
100+
if: failure()
101+
run: |
102+
echo "❌ Deployment failed!"
103+
echo "Check logs: https://github.com/${{ github.repository }}/actions"

config/puma.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,25 @@
4040
# Specify the PID file. Defaults to tmp/pids/server.pid in development.
4141
# In other environments, only set the PID file if requested.
4242
pidfile ENV["PIDFILE"] if ENV["PIDFILE"]
43+
44+
# Production-specific configuration
45+
if ENV["RAILS_ENV"] == "production"
46+
# Run 2 worker processes for production
47+
workers ENV.fetch("WEB_CONCURRENCY", 2)
48+
49+
# Preload application for memory efficiency
50+
preload_app!
51+
52+
# Allow phased restarts for zero-downtime deployments
53+
# When you run `systemctl reload core-puma`, Puma will:
54+
# 1. Start new workers with updated code
55+
# 2. Gradually kill old workers after requests complete
56+
# 3. No requests are dropped during deployment
57+
worker_timeout 30
58+
worker_boot_timeout 30
59+
60+
# Worker-specific setup (e.g., reconnect to database)
61+
on_worker_boot do
62+
ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
63+
end
64+
end

0 commit comments

Comments
 (0)