- GitHub Actions workflow for SFP server deployment with multi-environment support - Comprehensive README with setup instructions and troubleshooting guide - Codacy instructions for code quality checks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
186 lines
8.0 KiB
YAML
186 lines
8.0 KiB
YAML
name: SFP Server Deployment
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
image_tag:
|
|
description: 'Docker image tag to deploy (overrides environment default, e.g., v1.2.3, latest, pr-123-dev)'
|
|
required: false
|
|
type: string
|
|
cli_version:
|
|
description: 'SFP CLI version to use (latest, or specific version like v48.3.0)'
|
|
required: false
|
|
default: 'latest'
|
|
|
|
jobs:
|
|
deploy-server:
|
|
name: 'deploy to ${{ matrix.environment }}'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
environment: ${{ fromJson(vars.DEPLOYMENT_ENVIRONMENTS || '["development"]') }}
|
|
environment: ${{ matrix.environment }}
|
|
|
|
steps:
|
|
- name: Install SFP CLI on Runner
|
|
run: |
|
|
echo "📦 Installing SFP CLI on GitHub runner..."
|
|
|
|
# Download and install CLI from source.flxbl.io releases
|
|
CLI_VERSION="${{ github.event.inputs.cli_version || 'latest' }}"
|
|
|
|
if [ "$CLI_VERSION" = "latest" ]; then
|
|
# Get the latest release info
|
|
RELEASE_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
|
"https://source.flxbl.io/api/v1/repos/flxbl/sfp-pro/releases/latest")
|
|
DEB_URL=$(echo "$RELEASE_DATA" | jq -r '.assets[] | select(.name | endswith("linux_amd64.deb")) | .browser_download_url')
|
|
else
|
|
# For specific version, get the deb filename from that release
|
|
RELEASE_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
|
"https://source.flxbl.io/api/v1/repos/flxbl/sfp-pro/releases/tags/$CLI_VERSION")
|
|
DEB_URL=$(echo "$RELEASE_DATA" | jq -r '.assets[] | select(.name | endswith("linux_amd64.deb")) | .browser_download_url')
|
|
fi
|
|
|
|
echo "📦 Using CLI version: $CLI_VERSION"
|
|
echo "📦 Downloading from: $DEB_URL"
|
|
|
|
# Download and install the deb package
|
|
curl -L -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" "$DEB_URL" -o /tmp/sfp-pro.deb
|
|
sudo dpkg -i /tmp/sfp-pro.deb || sudo apt-get install -f -y
|
|
|
|
# Verify installation
|
|
sfp --version
|
|
|
|
echo "✅ SFP CLI installed successfully on runner"
|
|
|
|
- name: Install Supabase CLI
|
|
run: |
|
|
echo "📥 Installing Supabase CLI..."
|
|
|
|
# Download and install Supabase CLI DEB package
|
|
curl -L -o supabase.deb 'https://github.com/supabase/cli/releases/download/v2.23.4/supabase_2.23.4_linux_amd64.deb'
|
|
sudo dpkg -i supabase.deb || sudo apt-get install -f -y
|
|
|
|
# Verify installation
|
|
echo "✅ Verifying installation..."
|
|
supabase --version
|
|
echo "✅ Supabase CLI installed successfully"
|
|
|
|
- name: Setup SSH
|
|
run: |
|
|
# Create SSH directory and key file
|
|
mkdir -p ~/.ssh
|
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
|
|
chmod 600 ~/.ssh/deploy_key
|
|
|
|
# Add host to known_hosts to avoid prompts
|
|
ssh-keyscan -H ${{ vars.SSH_HOST }} >> ~/.ssh/known_hosts
|
|
|
|
|
|
- name: Deploy Server Update
|
|
id: deploy
|
|
env:
|
|
SUPABASE_DB_URL: ${{ secrets.SUPABASE_DB_URL }}
|
|
DOCKER_REGISTRY: source.flxbl.io
|
|
DOCKER_REGISTRY_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|
IMAGE_FQDN: source.flxbl.io/flxbl/sfp-server
|
|
run: |
|
|
echo "🚀 Starting deployment to ${{ matrix.environment }}..."
|
|
|
|
# Set deployment parameters from environment variables
|
|
TENANT="${{ vars.SFP_TENANT || 'sfp-server' }}"
|
|
SSH_HOST="${{ vars.SSH_HOST }}"
|
|
SSH_USER="${{ vars.SSH_USER || 'root' }}"
|
|
|
|
# Set image tag priority: input > environment variable > default (latest)
|
|
IMAGE_TAG="${{ github.event.inputs.image_tag || vars.IMAGE_TAG || 'latest' }}"
|
|
|
|
# Validate required secrets
|
|
if [ -z "$SUPABASE_DB_URL" ]; then
|
|
echo "❌ SUPABASE_DB_URL secret is required"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$DOCKER_REGISTRY_TOKEN" ]; then
|
|
echo "❌ GITEA_TOKEN secret is required for pulling images from source.flxbl.io"
|
|
exit 1
|
|
fi
|
|
|
|
echo "📦 Deploying to environment: ${{ matrix.environment }}"
|
|
echo "🐳 Docker registry: $DOCKER_REGISTRY"
|
|
echo "🖼️ Image FQDN: $IMAGE_FQDN"
|
|
echo "🏷️ Image tag: $IMAGE_TAG"
|
|
echo "🗄️ Database configured"
|
|
|
|
# Export environment variables for sfp server update
|
|
export SUPABASE_DB_URL="$SUPABASE_DB_URL"
|
|
export DOCKER_REGISTRY="$DOCKER_REGISTRY"
|
|
export DOCKER_REGISTRY_TOKEN="$DOCKER_REGISTRY_TOKEN"
|
|
export IMAGE_FQDN="$IMAGE_FQDN"
|
|
export IMAGE_TAG="$IMAGE_TAG"
|
|
|
|
# Deploy server using sfp server update (handles stop/start automatically)
|
|
echo "🔄 Deploying server..."
|
|
sfp server update --tenant "$TENANT" --docker-tag "$IMAGE_TAG" --ssh-connection "$SSH_USER@$SSH_HOST" --identity-file ~/.ssh/deploy_key
|
|
|
|
# Wait for startup
|
|
echo "⏳ Waiting for server to start..."
|
|
sleep 30
|
|
|
|
echo "✅ Deployment completed"
|
|
|
|
- name: Post-Deployment Health Check
|
|
id: health_check
|
|
run: |
|
|
echo "🔍 Running post-deployment health checks..."
|
|
|
|
# Get environment configuration
|
|
TENANT="${{ vars.SFP_TENANT || 'sfp-server' }}"
|
|
SSH_HOST="${{ vars.SSH_HOST }}"
|
|
SSH_USER="${{ vars.SSH_USER || 'root' }}"
|
|
|
|
# Wait for services to be ready
|
|
timeout 300 bash -c 'until sfp server health --tenant "'"$TENANT"'" --ssh-connection "'"$SSH_USER@$SSH_HOST"'" --identity-file ~/.ssh/deploy_key; do sleep 5; done'
|
|
|
|
# Detailed health check
|
|
HEALTH_STATUS=$(sfp server health --tenant "$TENANT" --ssh-connection "$SSH_USER@$SSH_HOST" --identity-file ~/.ssh/deploy_key --json)
|
|
|
|
if echo "$HEALTH_STATUS" | jq -e '.healthy == true' > /dev/null; then
|
|
echo "✅ Server is healthy after deployment"
|
|
echo "healthy=true" >> $GITHUB_OUTPUT
|
|
|
|
# Get new version
|
|
NEW_VERSION=$(sfp server status --tenant "$TENANT" --ssh-connection "$SSH_USER@$SSH_HOST" --identity-file ~/.ssh/deploy_key --json | jq -r '.version')
|
|
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
echo "📦 New version: $NEW_VERSION"
|
|
else
|
|
echo "❌ Server health check failed"
|
|
echo "healthy=false" >> $GITHUB_OUTPUT
|
|
exit 1
|
|
fi
|
|
|
|
deployment-summary:
|
|
name: 'deployment summary'
|
|
needs: [deploy-server]
|
|
if: always()
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Generate Summary
|
|
run: |
|
|
echo "## 🚀 SFP Server Deployment Summary" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Image Tag:** ${{ github.event.inputs.image_tag || 'Environment default or latest' }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Environments:** ${{ vars.DEPLOYMENT_ENVIRONMENTS || '[\"development\"]' }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**CLI Version:** ${{ github.event.inputs.cli_version || 'latest' }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Triggered By:** @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "**Timestamp:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [ "${{ needs.deploy-server.result }}" == "success" ]; then
|
|
echo "✅ **Deployment:** Success across all environments" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "❌ **Deployment:** Failed (check individual environment results)" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "🔗 **Workflow:** [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY |