deploy-mcp-sap-docs.ymlā¢11.3 kB
name: Deploy MCP stack
on:
push:
branches: [ main ]
# Allow manual triggering
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-22.04
# š must match the environment where you stored the secrets
environment:
name: remove server
steps:
- name: Check out repo (for action context only)
uses: actions/checkout@v4
with:
# Fetch more than just the triggering commit to handle workflow reruns
fetch-depth: 10
- name: Ensure we have the latest main branch
run: |
git fetch origin main
git checkout main
git reset --hard origin/main
echo "Current HEAD: $(git rev-parse HEAD)"
echo "Latest main: $(git rev-parse origin/main)"
- name: Preflight verify required secrets are present
run: |
set -euo pipefail
for s in SERVER_IP SERVER_USERNAME SSH_PRIVATE_KEY; do
[ -n "${!s}" ] || { echo "Missing $s"; exit 1; }
done
env:
SERVER_IP: ${{ secrets.SERVER_IP }}
SERVER_USERNAME: ${{ secrets.SERVER_USERNAME }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Auto-increment version
run: |
# Get current version and increment patch
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo "Current version: $CURRENT_VERSION"
# Extract major.minor.patch
IFS='.' read -ra PARTS <<< "$CURRENT_VERSION"
MAJOR=${PARTS[0]}
MINOR=${PARTS[1]}
PATCH=${PARTS[2]}
# Increment patch version
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
echo "New version: $NEW_VERSION"
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
# Update package.json
npm version $NEW_VERSION --no-git-tag-version
- name: Update hardcoded version in streamable server
run: |
# Update the hardcoded version in streamable-http-server.ts
sed -i 's/const VERSION = "[0-9]*\.[0-9]*\.[0-9]*";/const VERSION = "'${{ env.NEW_VERSION }}'";/g' src/streamable-http-server.ts
- name: Commit version bump
id: version_bump
continue-on-error: true
run: |
set -e
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
# Check if there are any changes to commit
git add package.json package-lock.json src/streamable-http-server.ts
if ! git diff --staged --quiet; then
if git commit -m "chore: bump version to ${{ env.NEW_VERSION }} [skip ci]"; then
echo "Version bump committed successfully"
# Handle potential conflicts from concurrent pushes or workflow reruns
echo "Attempting to push version bump..."
if ! git push; then
echo "Push failed, likely due to remote changes. Pulling and retrying..."
git fetch origin main
# Try rebase first
if git rebase origin/main; then
echo "Rebase successful, pushing again..."
git push
else
echo "Rebase failed, attempting merge strategy..."
git rebase --abort
git merge origin/main --no-edit
git push
fi
fi
echo "ā
Version bump pushed successfully"
else
echo "ā¹ļø No version changes to commit"
fi
else
echo "ā¹ļø No version changes detected"
fi
- name: Handle version bump failure
if: steps.version_bump.outcome == 'failure'
run: |
echo "ā ļø Version bump failed, but continuing with deployment"
echo "This can happen with concurrent workflows or when rerunning failed deployments"
echo "The deployment will proceed with the current version"
# Reset any partial git state
git reset --hard HEAD
git clean -fd
- name: Deploy to server via SSH
uses: appleboy/ssh-action@v1.0.3
env:
NEW_VERSION: ${{ env.NEW_VERSION }}
with:
host: ${{ secrets.SERVER_IP }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
envs: NEW_VERSION
script: |
set -Eeuo pipefail
echo "==> Database Health Pre-Check"
cd /opt/mcp-sap/mcp-sap-docs || { echo "Directory not found, will be created"; }
# Function to check SQLite database integrity
check_db_integrity() {
local db_path="$1"
if [ -f "$db_path" ]; then
echo "š Checking database integrity: $db_path"
if sqlite3 "$db_path" "PRAGMA integrity_check;" 2>/dev/null | grep -q "ok"; then
echo "ā
Database integrity OK"
return 0
else
echo "ā Database corruption detected"
return 1
fi
else
echo "ā¹ļø Database file does not exist: $db_path"
return 1
fi
}
# Check existing database and create backup
DB_PATH="/opt/mcp-sap/mcp-sap-docs/dist/data/docs.sqlite"
if [ -f "$DB_PATH" ]; then
if ! check_db_integrity "$DB_PATH"; then
echo "==> Database corruption detected - will rebuild"
rm -f "$DB_PATH"
else
echo "==> Creating database backup before deployment"
BACKUP_PATH="/opt/mcp-sap/backups/deploy-backup-$(date +%Y%m%d-%H%M%S).sqlite"
mkdir -p /opt/mcp-sap/backups
cp "$DB_PATH" "$BACKUP_PATH"
echo "ā
Database backed up to $BACKUP_PATH"
# Keep only last 5 backups
ls -t /opt/mcp-sap/backups/deploy-backup-*.sqlite 2>/dev/null | tail -n +6 | xargs -r rm --
fi
fi
echo "==> Ensure base path exists and owned by user"
sudo mkdir -p /opt/mcp-sap
sudo chown -R "$USER":"$USER" /opt/mcp-sap
echo "==> Clone or update repo (with submodules)"
if [ -d /opt/mcp-sap/mcp-sap-docs/.git ]; then
cd /opt/mcp-sap/mcp-sap-docs
git config --global url."https://github.com/".insteadOf git@github.com:
git fetch --prune
git reset --hard origin/main
else
cd /opt/mcp-sap
git config --global url."https://github.com/".insteadOf git@github.com:
git clone https://github.com/marianfoo/mcp-sap-docs.git
cd mcp-sap-docs
fi
echo "==> Deploying version: $NEW_VERSION"
echo "==> Configure BM25 search environment"
# Ensure metadata file exists for centralized configuration
[ -f /opt/mcp-sap/mcp-sap-docs/data/metadata.json ] || echo "Metadata file will be created during build"
echo "==> Check system resources before build"
AVAILABLE_MB=$(df /opt/mcp-sap --output=avail -m | tail -n1)
if [ "$AVAILABLE_MB" -lt 1000 ]; then
echo "ā ERROR: Insufficient disk space. Available: ${AVAILABLE_MB}MB, Required: 1000MB"
exit 1
fi
echo "ā
Disk space OK: ${AVAILABLE_MB}MB available"
AVAILABLE_KB=$(awk '/MemAvailable/ { print $2 }' /proc/meminfo)
AVAILABLE_MB_MEM=$((AVAILABLE_KB / 1024))
if [ "$AVAILABLE_MB_MEM" -lt 512 ]; then
echo "ā ERROR: Insufficient memory. Available: ${AVAILABLE_MB_MEM}MB, Required: 512MB"
exit 1
fi
echo "ā
Memory OK: ${AVAILABLE_MB_MEM}MB available"
echo "==> Stop MCP services gracefully before build"
pm2 stop mcp-sap-proxy mcp-sap-http mcp-sap-streamable || true
sleep 3
echo "==> Run setup (shallow, single-branch submodules + build)"
SKIP_NESTED_SUBMODULES=1 bash setup.sh
echo "==> Verify database integrity after build"
if ! check_db_integrity "$DB_PATH"; then
echo "ā ERROR: Database corruption after build - deployment failed"
exit 1
fi
echo "ā
Database integrity verified after build"
echo "==> Create logs directory with proper permissions"
mkdir -p /opt/mcp-sap/logs
chown -R "$USER":"$USER" /opt/mcp-sap/logs
echo "==> (Re)start MCP services with BM25 search support"
# Proxy (SSE) on 127.0.0.1:18080; HTTP status on 127.0.0.1:3001; Streamable HTTP on 127.0.0.1:3122
pm2 start /opt/mcp-sap/mcp-sap-docs/ecosystem.config.cjs --only mcp-sap-proxy || pm2 restart mcp-sap-proxy
pm2 start /opt/mcp-sap/mcp-sap-docs/ecosystem.config.cjs --only mcp-sap-http || pm2 restart mcp-sap-http
pm2 start /opt/mcp-sap/mcp-sap-docs/ecosystem.config.cjs --only mcp-sap-streamable || pm2 restart mcp-sap-streamable
pm2 save
echo "==> Enhanced health checks with database verification"
sleep 5
for i in $(seq 1 30); do curl -fsS http://127.0.0.1:18080/status >/dev/null && break || sleep 2; done
curl -fsS http://127.0.0.1:18080/status
for i in $(seq 1 30); do curl -fsS http://127.0.0.1:3001/status >/dev/null && break || sleep 2; done
curl -fsS http://127.0.0.1:3001/status
# Streamable HTTP server health on 127.0.0.1:3122
for i in $(seq 1 30); do curl -fsS http://127.0.0.1:3122/health >/dev/null && break || sleep 2; done
curl -fsS http://127.0.0.1:3122/health
# Test actual search functionality to ensure no SQLite corruption
echo "==> Testing search functionality"
SEARCH_TEST=$(curl -s -X POST http://127.0.0.1:3001/mcp -H "Content-Type: application/json" -d '{"role": "user", "content": "test search"}')
if echo "$SEARCH_TEST" | grep -q "SqliteError\|SQLITE_CORRUPT\|Tool execution failed"; then
echo "ā ERROR: Search test failed - possible database corruption"
echo "Response: $SEARCH_TEST"
exit 1
fi
echo "ā
Search functionality verified - no corruption detected"
echo "==> Final database integrity check"
if ! check_db_integrity "$DB_PATH"; then
echo "ā WARNING: Database corruption detected after deployment"
# Don't fail deployment, but alert
else
echo "ā
Final database integrity check passed"
fi
echo "ā
Deployment completed successfully - Version: $NEW_VERSION"