docs: add troubleshooting section to README #5
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Production MCP Server Deployment | |
| # | |
| # Deploys the remote MCP server to mcp.digitalsamba.com | |
| # Triggers on push to main branch or manual dispatch | |
| # | |
| # GitHub Secrets Required: | |
| # Repository secrets: | |
| # - DOCKER_REGISTRY: Registry hostname | |
| # - REGISTRY_USERNAME: Docker registry username | |
| # - REGISTRY_PASSWORD: Docker registry password | |
| # - DEPLOYMENT_USER: SSH user for deployment | |
| # - DEPLOYMENT_SSH_KEY: SSH private key | |
| # | |
| # Environment secrets (production): | |
| # - DEPLOYMENT_SERVER: Target server hostname | |
| # - DEPLOYMENT_PATH: Server path for deployment files | |
| # - MCP_URL: Public URL (https://mcp.digitalsamba.com) | |
| name: Deploy Production MCP Server | |
| on: | |
| push: | |
| tags: | |
| - 'v*' # Triggers on v1.0.0, v1.0.1, etc. | |
| workflow_dispatch: # Manual trigger as backup | |
| env: | |
| IMAGE_NAME: digitalsamba-mcp-server | |
| jobs: | |
| test: | |
| name: Run Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20.x' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build | |
| run: npm run build | |
| - name: Run tests | |
| run: npm run test:ci | |
| build-and-deploy: | |
| name: Build and Deploy to Production | |
| needs: test | |
| runs-on: ubuntu-latest | |
| environment: production | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Docker Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ secrets.DOCKER_REGISTRY }} | |
| username: ${{ secrets.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Extract version | |
| id: version | |
| run: | | |
| if [[ "${{ github.ref }}" == refs/tags/v* ]]; then | |
| # Use git tag (e.g., v1.0.0 -> 1.0.0) | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| else | |
| # Fallback to package.json for manual dispatch | |
| VERSION=$(node -p "require('./package.json').version") | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Deploying version: $VERSION" | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: | | |
| ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} | |
| ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }} | |
| ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |
| ${{ secrets.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:production | |
| build-args: | | |
| GIT_COMMIT=${{ github.sha }} | |
| GIT_REF=${{ github.ref_name }} | |
| BUILD_TIME=${{ github.event.head_commit.timestamp }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Copy deployment files to server | |
| uses: appleboy/scp-action@v0.1.7 | |
| with: | |
| host: ${{ secrets.DEPLOYMENT_SERVER }} | |
| username: ${{ secrets.DEPLOYMENT_USER }} | |
| key: ${{ secrets.DEPLOYMENT_SSH_KEY }} | |
| source: "deployment/docker-compose.yml" | |
| target: ${{ secrets.DEPLOYMENT_PATH }} | |
| strip_components: 1 | |
| - name: Deploy to server | |
| uses: appleboy/ssh-action@v1.0.3 | |
| env: | |
| REGISTRY: ${{ secrets.DOCKER_REGISTRY }} | |
| IMAGE_NAME: ${{ env.IMAGE_NAME }} | |
| with: | |
| host: ${{ secrets.DEPLOYMENT_SERVER }} | |
| username: ${{ secrets.DEPLOYMENT_USER }} | |
| key: ${{ secrets.DEPLOYMENT_SSH_KEY }} | |
| envs: REGISTRY,IMAGE_NAME | |
| script: | | |
| cd ${{ secrets.DEPLOYMENT_PATH }} | |
| # Login to registry | |
| echo "${{ secrets.REGISTRY_PASSWORD }}" | sudo docker login ${{ secrets.DOCKER_REGISTRY }} -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin | |
| # Pull production image | |
| sudo docker pull ${REGISTRY}/${IMAGE_NAME}:production | |
| # Update docker-compose to use production tag | |
| sed -i 's/:latest/:production/g' docker-compose.yml | |
| # Set production network name (apps3 uses deployment_proxy) | |
| export PROXY_NETWORK=deployment_proxy | |
| # Stop and remove old container | |
| sudo PROXY_NETWORK=$PROXY_NETWORK docker compose down --remove-orphans || true | |
| # Start new container | |
| sudo PROXY_NETWORK=$PROXY_NETWORK docker compose up -d | |
| # Wait for service to be healthy | |
| echo "Waiting for service to be healthy..." | |
| sleep 15 | |
| # Cleanup old images | |
| sudo docker image prune -f | |
| - name: Verify deployment | |
| run: | | |
| echo "Waiting for service startup..." | |
| sleep 20 | |
| # Health check with retries | |
| for i in 1 2 3; do | |
| HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ secrets.MCP_URL }}/health || echo "000") | |
| if [ "$HTTP_STATUS" = "200" ]; then | |
| echo "Health check passed (HTTP $HTTP_STATUS)" | |
| exit 0 | |
| fi | |
| echo "Attempt $i: HTTP $HTTP_STATUS, retrying in 10s..." | |
| sleep 10 | |
| done | |
| echo "Health check failed after 3 attempts" | |
| curl -v ${{ secrets.MCP_URL }}/health || true | |
| exit 1 | |
| - name: Deployment summary | |
| run: | | |
| echo "## Production MCP Server Deployed!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Item | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Environment** | production |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **URL** | ${{ secrets.MCP_URL }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Version** | ${{ steps.version.outputs.version }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Commit** | ${{ github.sha }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| **Triggered by** | ${{ github.actor }} |" >> $GITHUB_STEP_SUMMARY | |
| - name: Sync develop branch with main | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git fetch origin develop | |
| git checkout develop | |
| git merge origin/main --no-edit -m "chore: sync develop with main after ${{ steps.version.outputs.version }} release" | |
| git push origin develop | |
| echo "✅ Develop branch synced with main" >> $GITHUB_STEP_SUMMARY |