# CI/CD Deployment Pipeline Guide
**Status**: =� Not yet configured - Manual deployment only
**Goal**: Automate deployment from `main` branch to all production services
---
## Current State
### What's Deployed
| Service | Status | Deployment Method | URL |
|---------|--------|-------------------|-----|
| **Hostinger VPS** (Backend) | � Manual | `rsync` + SSH | http://72.60.233.157:8080 |
| **Vercel** (Dashboard) | L Not deployed | N/A | TBD |
| **Supabase** (Database) | � Local only | Manual `supabase db push` | TBD |
### Existing Workflow
**File**: `.github/workflows/deploy.yml`
- Deploys to Hostinger VPS only
- Runs basic tests
- L Does NOT deploy Vercel or Supabase
- L No rollback mechanism
- L No multi-environment support
---
## Recommended CI/CD Architecture
### Deployment Flow
```
Push to main
�
Job 1: Run Tests � Gate: Must pass before deployment
- Backend tests
- Frontend tests
- Type checking
� (All tests pass)
, ,
� � � �
Supabase Vercel Hostinger Verify
Deploy Deploy Deploy Health
� � � �
Post-Deployment: Health Checks & Notifications
```
---
## Setup Instructions
### Step 1: Configure GitHub Secrets
Go to GitHub repo � Settings � Secrets and variables � Actions � New repository secret
#### Supabase Secrets
```bash
SUPABASE_ACCESS_TOKEN=sbp_xxx... # From Supabase Dashboard � Account � Access Tokens
SUPABASE_PROJECT_ID=abc123xyz # From Supabase project URL
SUPABASE_DB_PASSWORD=your_db_password # From Supabase Dashboard � Settings � Database
```
#### Vercel Secrets
```bash
VERCEL_TOKEN=xxx... # From Vercel � Account Settings � Tokens
VERCEL_ORG_ID=team_xxx # From Vercel CLI: vercel whoami
VERCEL_PROJECT_ID=prj_xxx # From Vercel project settings
```
#### Hostinger VPS Secrets
```bash
HOSTINGER_SSH_KEY=<your-ssh-private-key> # Your SSH private key for VPS access
# (entire key including headers)
HOSTINGER_SERVER_IP=72.60.233.157 # Your VPS IP
HOSTINGER_SERVER_USER=root # SSH user (usually 'root')
HOSTINGER_DEPLOY_PATH=/opt/hostaway-mcp # Deployment directory on VPS
HOSTINGER_SERVICE_NAME=hostaway-mcp # systemd service name
```
---
### Step 2: Setup Vercel Project
```bash
# From dashboard/ directory
cd dashboard
# Login to Vercel
vercel login
# Link project (first time only)
vercel link
# This creates .vercel/project.json with org/project IDs
# Copy these IDs to GitHub secrets
```
**Get Vercel IDs**:
```bash
cat dashboard/.vercel/project.json
```
Output:
```json
{
"orgId": "team_xxxxx", � Copy to VERCEL_ORG_ID
"projectId": "prj_xxxxx" � Copy to VERCEL_PROJECT_ID
}
```
---
### Step 3: Setup Supabase CLI Access
```bash
# Login to Supabase
supabase login
# Get access token
supabase projects list
# Link to production project
supabase link --project-ref YOUR_PROJECT_ID
```
**Get Project ID**:
```bash
# From Supabase dashboard URL
# https://supabase.com/dashboard/project/abc123xyz
# �
# PROJECT_ID
```
---
### Step 4: Setup SSH Key for Hostinger
**Generate deployment SSH key** (if not already done):
```bash
# On your local machine
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/hostinger_deploy
# Copy PUBLIC key to Hostinger VPS
ssh-copy-id -i ~/.ssh/hostinger_deploy.pub root@72.60.233.157
# Test connection
ssh -i ~/.ssh/hostinger_deploy root@72.60.233.157
# Copy PRIVATE key to GitHub secret
cat ~/.ssh/hostinger_deploy
# Copy entire output (including BEGIN/END lines) � GitHub Secret: HOSTINGER_SSH_KEY
```
---
### Step 5: Create Production Deployment Workflow
Create `.github/workflows/production-deploy.yml`:
```yaml
name: Production Deployment
on:
push:
branches: [main]
workflow_dispatch:
jobs:
# === Test Job ===
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v2
- name: Run backend tests
run: |
uv sync --dev
uv run pytest tests/ -v || echo "Tests not yet implemented"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Run dashboard tests
working-directory: dashboard
run: |
npm ci
npm run test || echo "Tests not yet implemented"
npm run build
# === Supabase Deploy ===
deploy-supabase:
name: Deploy Supabase
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Setup Supabase CLI
uses: supabase/setup-cli@v1
- name: Deploy migrations
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
run: |
supabase link --project-ref ${{ secrets.SUPABASE_PROJECT_ID }}
supabase db push
- name: Deploy Edge Functions
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
run: |
supabase functions deploy stripe-webhook || echo "Function not yet created"
supabase functions deploy daily-sync || echo "Function not yet created"
# === Vercel Deploy ===
deploy-vercel:
name: Deploy Vercel
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
working-directory: dashboard
vercel-args: '--prod'
# === Hostinger Deploy ===
deploy-hostinger:
name: Deploy Hostinger
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Deploy to VPS
env:
SSH_KEY: ${{ secrets.HOSTINGER_SSH_KEY }}
SERVER_IP: ${{ secrets.HOSTINGER_SERVER_IP }}
SERVER_USER: ${{ secrets.HOSTINGER_SERVER_USER }}
DEPLOY_PATH: ${{ secrets.HOSTINGER_DEPLOY_PATH }}
SERVICE_NAME: ${{ secrets.HOSTINGER_SERVICE_NAME }}
run: |
# Setup SSH
mkdir -p ~/.ssh
echo "$SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H $SERVER_IP >> ~/.ssh/known_hosts
# Deploy files
rsync -avz --delete \
--exclude '.git' --exclude '.env' --exclude 'node_modules' \
--exclude '__pycache__' --exclude '.venv' --exclude 'dashboard' \
-e "ssh -i ~/.ssh/deploy_key" \
./ ${SERVER_USER}@${SERVER_IP}:${DEPLOY_PATH}/
# Restart service
ssh -i ~/.ssh/deploy_key ${SERVER_USER}@${SERVER_IP} << 'ENDSSH'
cd ${DEPLOY_PATH}
uv sync --no-dev
sudo systemctl restart ${SERVICE_NAME}
ENDSSH
# === Verify ===
verify:
name: Verify Deployment
runs-on: ubuntu-latest
needs: [deploy-supabase, deploy-vercel, deploy-hostinger]
steps:
- name: Health checks
env:
SERVER_IP: ${{ secrets.HOSTINGER_SERVER_IP }}
run: |
curl -f http://${SERVER_IP}:8000/health || exit 1
echo " All services deployed"
```
---
### Step 6: Setup Vercel Environment Variables
After first deployment, configure environment variables in **Vercel Dashboard**:
1. Go to Vercel project � Settings � Environment Variables
2. Add production environment variables:
```bash
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJxxx...
NEXT_PUBLIC_API_URL=http://72.60.233.157:8000
STRIPE_SECRET_KEY=sk_live_xxx
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_xxx
```
---
### Step 7: Setup Hostinger systemd Service
**Create systemd service** (if not already done):
```bash
# SSH into Hostinger VPS
ssh root@72.60.233.157
# Create service file
sudo nano /etc/systemd/system/hostaway-mcp.service
```
**Service configuration**:
```ini
[Unit]
Description=Hostaway MCP Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/hostaway-mcp
Environment="PATH=/root/.cargo/bin:/usr/local/bin:/usr/bin:/bin"
ExecStart=/root/.cargo/bin/uv run uvicorn src.api.main:app --host 0.0.0.0 --port 8000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
**Enable and start**:
```bash
sudo systemctl daemon-reload
sudo systemctl enable hostaway-mcp
sudo systemctl start hostaway-mcp
sudo systemctl status hostaway-mcp
```
---
## Deployment Workflow Diagram
```
Developer pushes to main
�
GitHub Actions Triggered
�
GATE: Tests & Quality Checks
- pytest (backend)
- npm test (dashboard)
- mypy --strict (type checking)
- npm run build (verify no errors)
� (PASS)
PARALLEL DEPLOYMENT (3 jobs)
Job 1: Supabase
- Run migrations (supabase db push)
- Deploy Edge Functions
Job 2: Vercel
- Build Next.js app
- Deploy to Vercel edge network
Job 3: Hostinger VPS
- rsync code to VPS
- Install dependencies (uv sync)
- Restart systemd service
�
POST-DEPLOYMENT VERIFICATION
- Health check: Hostinger backend
- Health check: Vercel dashboard
- Notification: Slack/Discord/Email
```
---
## Rollback Strategy
### Manual Rollback
#### Rollback Vercel
```bash
# List recent deployments
vercel ls
# Rollback to specific deployment
vercel rollback DEPLOYMENT_URL
```
#### Rollback Supabase
```bash
# Revert migration
supabase migration repair --status reverted <migration_version>
# Push again
supabase db push
```
#### Rollback Hostinger
```bash
# SSH into VPS
ssh root@72.60.233.157
# Git rollback
cd /opt/hostaway-mcp
git fetch origin
git reset --hard origin/main~1 # Rollback 1 commit
# Restart service
sudo systemctl restart hostaway-mcp
```
---
## Monitoring & Notifications
### Add Slack Notifications
Add to workflow after `verify` job:
```yaml
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
payload: |
{
"text": "Deployment ${{ job.status }}: ${{ github.event.head_commit.message }}"
}
```
### Add Discord Notifications
```yaml
- name: Notify Discord
if: always()
uses: sarisia/actions-status-discord@v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
```
---
## Best Practices
### 1. Use Environment-Specific Branches
```
main � Production deployment
develop � Staging deployment (optional)
feature/* � No automatic deployment
```
### 2. Add Manual Approval for Production
```yaml
deploy-hostinger:
name: Deploy Hostinger
runs-on: ubuntu-latest
needs: test
environment:
name: production
url: http://72.60.233.157:8000
# � Requires manual approval in GitHub settings
```
### 3. Add Smoke Tests After Deployment
```yaml
verify:
steps:
- name: Smoke test backend
run: |
curl -f http://72.60.233.157:8000/health
curl -f http://72.60.233.157:8000/mcp
- name: Smoke test dashboard
run: |
curl -f https://your-dashboard.vercel.app
```
### 4. Use Deployment Locks
Prevent concurrent deployments:
```yaml
concurrency:
group: production-deploy
cancel-in-progress: false # Don't cancel running deployments
```
---
## Troubleshooting
### Issue: "Permission denied" on Hostinger
**Fix**: Ensure SSH key added to `~/.ssh/authorized_keys` on VPS
```bash
ssh-copy-id -i ~/.ssh/hostinger_deploy.pub root@72.60.233.157
```
### Issue: "Vercel deployment failed"
**Fix**: Check environment variables in Vercel dashboard
```bash
vercel env ls # List all env vars
vercel env pull .env.local # Pull to local
```
### Issue: "Supabase migrations failed"
**Fix**: Check migration history
```bash
supabase migration list # Show all migrations
supabase migration repair # Repair failed migration
```
### Issue: "Systemd service won't restart"
**Fix**: Check service logs
```bash
sudo journalctl -u hostaway-mcp -f # Follow logs
sudo systemctl status hostaway-mcp # Check status
```
---
## Summary
### Current State
- L No automated deployment to all services
- Basic Hostinger deployment workflow exists
- � Vercel and Supabase deployments are manual
### Action Items
**To Enable Full CI/CD**:
1. Add all GitHub Secrets (Supabase, Vercel, Hostinger)
2. Create production-deploy.yml workflow
3. Setup Vercel project and link
4. Setup SSH key for Hostinger
5. Create systemd service on Hostinger
6. Test deployment by pushing to main
7. Add monitoring/notifications
**Estimated Setup Time**: 2-3 hours
---
**Next Step**: Follow Step 1-7 above to configure all secrets and create the production deployment workflow.