Skip to main content
Glama
cicd-deployment-guide.md14.5 kB
# 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.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/darrentmorgan/hostaway-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server