name: GitOps Deployment Automation on: repository_dispatch: types: [deploy-staging, deploy-production, rollback] workflow_dispatch: inputs: environment: description: 'Environment to deploy to' required: true default: 'staging' type: choice options: - staging - production action: description: 'Deployment action' required: true default: 'deploy' type: choice options: - deploy - rollback - health-check version: description: 'Version/tag to deploy (leave empty for latest)' required: false type: string env: DEPLOYMENT_TIMEOUT: 300 HEALTH_CHECK_RETRIES: 5 BACKUP_RETENTION_DAYS: 30 jobs: validate-deployment: name: Validate Deployment Request runs-on: ubuntu-latest outputs: environment: ${{ steps.validate.outputs.environment }} action: ${{ steps.validate.outputs.action }} version: ${{ steps.validate.outputs.version }} proceed: ${{ steps.validate.outputs.proceed }} steps: - name: Validate Input id: validate run: | echo "๐Ÿ” Validating deployment request..." # Determine environment if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then ENV="${{ github.event.inputs.environment }}" ACTION="${{ github.event.inputs.action }}" VERSION="${{ github.event.inputs.version }}" elif [ "${{ github.event_name }}" = "repository_dispatch" ]; then ENV="${{ github.event.client_payload.environment }}" ACTION="${{ github.event.client_payload.action }}" VERSION="${{ github.event.client_payload.version }}" else echo "โŒ Invalid trigger event" exit 1 fi # Validate environment if [[ ! "$ENV" =~ ^(staging|production)$ ]]; then echo "โŒ Invalid environment: $ENV" exit 1 fi # Validate action if [[ ! "$ACTION" =~ ^(deploy|rollback|health-check)$ ]]; then echo "โŒ Invalid action: $ACTION" exit 1 fi # Production deployment additional validation if [ "$ENV" = "production" ] && [ "$ACTION" = "deploy" ]; then if [ "${{ github.ref_name }}" != "main" ]; then echo "โŒ Production deployments only allowed from main branch" exit 1 fi # Check if staging deployment was successful recently echo "๐Ÿ” Checking staging deployment status..." # This would typically query your monitoring/deployment system fi echo "โœ… Validation passed" echo "environment=$ENV" >> $GITHUB_OUTPUT echo "action=$ACTION" >> $GITHUB_OUTPUT echo "version=${VERSION:-latest}" >> $GITHUB_OUTPUT echo "proceed=true" >> $GITHUB_OUTPUT backup-environment: name: Create Environment Backup runs-on: ubuntu-latest needs: validate-deployment if: needs.validate-deployment.outputs.proceed == 'true' && needs.validate-deployment.outputs.action == 'deploy' steps: - name: Checkout Code uses: actions/checkout@v4 - name: Setup SSH run: | mkdir -p ~/.ssh if [ "${{ needs.validate-deployment.outputs.environment }}" = "staging" ]; then echo "${{ secrets.STAGING_SSH_KEY }}" > ~/.ssh/id_rsa HOST="${{ secrets.STAGING_HOST }}" USER="${{ secrets.STAGING_SSH_USER }}" WP_PATH="${{ secrets.STAGING_WP_PATH }}" else echo "${{ secrets.PRODUCTION_SSH_KEY }}" > ~/.ssh/id_rsa HOST="${{ secrets.PRODUCTION_HOST }}" USER="${{ secrets.PRODUCTION_SSH_USER }}" WP_PATH="${{ secrets.PRODUCTION_WP_PATH }}" fi chmod 600 ~/.ssh/id_rsa ssh-keyscan -H $HOST >> ~/.ssh/known_hosts echo "HOST=$HOST" >> $GITHUB_ENV echo "USER=$USER" >> $GITHUB_ENV echo "WP_PATH=$WP_PATH" >> $GITHUB_ENV - name: Create Full Backup run: | echo "๐Ÿ’พ Creating full environment backup..." TIMESTAMP=$(date +%Y%m%d-%H%M%S) BACKUP_NAME="hvac-plugin-${{ needs.validate-deployment.outputs.environment }}-$TIMESTAMP" ssh $USER@$HOST " cd $WP_PATH/wp-content/plugins # Create plugin backup tar -czf /tmp/${BACKUP_NAME}-plugin.tar.gz hvac-community-events/ # Create database backup wp db export /tmp/${BACKUP_NAME}-db.sql --path=$WP_PATH gzip /tmp/${BACKUP_NAME}-db.sql # Create uploads backup (if plugin stores files there) if [ -d '$WP_PATH/wp-content/uploads/hvac-events' ]; then tar -czf /tmp/${BACKUP_NAME}-uploads.tar.gz -C $WP_PATH/wp-content/uploads hvac-events/ fi echo 'โœ… Backup created: ${BACKUP_NAME}' echo 'BACKUP_NAME=${BACKUP_NAME}' >> backup_info.txt " # Store backup info for rollback echo "BACKUP_NAME=${BACKUP_NAME}" >> $GITHUB_ENV - name: Verify Backup run: | echo "๐Ÿ” Verifying backup integrity..." ssh $USER@$HOST " cd /tmp # Verify plugin backup if [ -f ${BACKUP_NAME}-plugin.tar.gz ]; then tar -tzf ${BACKUP_NAME}-plugin.tar.gz > /dev/null && echo 'โœ… Plugin backup verified' else echo 'โŒ Plugin backup missing' exit 1 fi # Verify database backup if [ -f ${BACKUP_NAME}-db.sql.gz ]; then gunzip -t ${BACKUP_NAME}-db.sql.gz && echo 'โœ… Database backup verified' else echo 'โŒ Database backup missing' exit 1 fi " deploy: name: Deploy Application runs-on: ubuntu-latest needs: [validate-deployment, backup-environment] if: needs.validate-deployment.outputs.proceed == 'true' && needs.validate-deployment.outputs.action == 'deploy' steps: - name: Checkout Code uses: actions/checkout@v4 with: ref: ${{ needs.validate-deployment.outputs.version != 'latest' && needs.validate-deployment.outputs.version || github.sha }} - name: Setup Deployment Environment run: | echo "๐Ÿš€ Setting up deployment for ${{ needs.validate-deployment.outputs.environment }}..." # Install deployment tools sudo apt-get update && sudo apt-get install -y rsync # Setup SSH mkdir -p ~/.ssh if [ "${{ needs.validate-deployment.outputs.environment }}" = "staging" ]; then echo "${{ secrets.STAGING_SSH_KEY }}" > ~/.ssh/id_rsa echo "DEPLOY_HOST=${{ secrets.STAGING_HOST }}" >> $GITHUB_ENV echo "DEPLOY_USER=${{ secrets.STAGING_SSH_USER }}" >> $GITHUB_ENV echo "DEPLOY_PATH=${{ secrets.STAGING_WP_PATH }}" >> $GITHUB_ENV echo "DEPLOY_URL=${{ secrets.STAGING_URL }}" >> $GITHUB_ENV else echo "${{ secrets.PRODUCTION_SSH_KEY }}" > ~/.ssh/id_rsa echo "DEPLOY_HOST=${{ secrets.PRODUCTION_HOST }}" >> $GITHUB_ENV echo "DEPLOY_USER=${{ secrets.PRODUCTION_SSH_USER }}" >> $GITHUB_ENV echo "DEPLOY_PATH=${{ secrets.PRODUCTION_WP_PATH }}" >> $GITHUB_ENV echo "DEPLOY_URL=${{ secrets.PRODUCTION_URL }}" >> $GITHUB_ENV fi chmod 600 ~/.ssh/id_rsa ssh-keyscan -H $DEPLOY_HOST >> ~/.ssh/known_hosts - name: Pre-deployment Health Check run: | echo "๐Ÿฅ Running pre-deployment health check..." # Check if site is accessible if ! curl -f -s -o /dev/null -w "%{http_code}" $DEPLOY_URL | grep -q "200"; then echo "โš ๏ธ Site health check failed - proceeding with caution" else echo "โœ… Pre-deployment health check passed" fi # Check plugin status ssh $DEPLOY_USER@$DEPLOY_HOST " cd $DEPLOY_PATH if wp plugin is-active hvac-community-events; then echo 'โœ… Plugin is currently active' else echo 'โš ๏ธ Plugin is currently inactive' fi " - name: Execute Deployment run: | echo "๐Ÿš€ Executing deployment..." # Use existing deployment script if available if [ -f scripts/deploy.sh ]; then chmod +x scripts/deploy.sh ./scripts/deploy.sh ${{ needs.validate-deployment.outputs.environment }} else echo "๐Ÿ“ฆ Manual deployment process..." # Sync plugin files rsync -avz --delete \ --exclude='.git*' \ --exclude='node_modules/' \ --exclude='tests/' \ --exclude='.forgejo/' \ ./ $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/wp-content/plugins/hvac-community-events/ # Activate plugin and flush rewrite rules ssh $DEPLOY_USER@$DEPLOY_HOST " cd $DEPLOY_PATH # Activate plugin wp plugin activate hvac-community-events # Flush rewrite rules wp rewrite flush # Clear any caches if wp plugin is-active w3-total-cache; then wp w3-total-cache flush fi if wp plugin is-active wp-super-cache; then wp super-cache flush fi echo 'โœ… Deployment completed successfully' " fi - name: Post-deployment Verification run: | echo "๐Ÿ” Running post-deployment verification..." # Wait for deployment to settle sleep 15 # Health check with retries for i in $(seq 1 $HEALTH_CHECK_RETRIES); do echo "Health check attempt $i/$HEALTH_CHECK_RETRIES..." if curl -f -s -o /dev/null -w "%{http_code}" $DEPLOY_URL | grep -q "200"; then echo "โœ… Site is responding" break elif [ $i -eq $HEALTH_CHECK_RETRIES ]; then echo "โŒ Site health check failed after $HEALTH_CHECK_RETRIES attempts" exit 1 else echo "โณ Waiting 10 seconds before retry..." sleep 10 fi done # Plugin-specific checks ssh $DEPLOY_USER@$DEPLOY_HOST " cd $DEPLOY_PATH # Verify plugin is active if wp plugin is-active hvac-community-events; then echo 'โœ… Plugin is active' else echo 'โŒ Plugin activation failed' exit 1 fi # Check for PHP errors in logs if tail -n 20 /var/log/apache2/error.log | grep -i 'hvac-community-events' | grep -i error; then echo 'โš ๏ธ PHP errors detected in logs' else echo 'โœ… No PHP errors detected' fi " rollback: name: Rollback Deployment runs-on: ubuntu-latest needs: validate-deployment if: needs.validate-deployment.outputs.proceed == 'true' && needs.validate-deployment.outputs.action == 'rollback' steps: - name: Setup Rollback Environment run: | echo "๐Ÿ”„ Setting up rollback for ${{ needs.validate-deployment.outputs.environment }}..." mkdir -p ~/.ssh if [ "${{ needs.validate-deployment.outputs.environment }}" = "staging" ]; then echo "${{ secrets.STAGING_SSH_KEY }}" > ~/.ssh/id_rsa echo "DEPLOY_HOST=${{ secrets.STAGING_HOST }}" >> $GITHUB_ENV echo "DEPLOY_USER=${{ secrets.STAGING_SSH_USER }}" >> $GITHUB_ENV echo "DEPLOY_PATH=${{ secrets.STAGING_WP_PATH }}" >> $GITHUB_ENV else echo "${{ secrets.PRODUCTION_SSH_KEY }}" > ~/.ssh/id_rsa echo "DEPLOY_HOST=${{ secrets.PRODUCTION_HOST }}" >> $GITHUB_ENV echo "DEPLOY_USER=${{ secrets.PRODUCTION_SSH_USER }}" >> $GITHUB_ENV echo "DEPLOY_PATH=${{ secrets.PRODUCTION_WP_PATH }}" >> $GITHUB_ENV fi chmod 600 ~/.ssh/id_rsa ssh-keyscan -H $DEPLOY_HOST >> ~/.ssh/known_hosts - name: Execute Rollback run: | echo "๐Ÿ”„ Executing rollback..." ssh $DEPLOY_USER@$DEPLOY_HOST " cd /tmp # Find most recent backup LATEST_BACKUP=\$(ls -t hvac-plugin-${{ needs.validate-deployment.outputs.environment }}-*-plugin.tar.gz 2>/dev/null | head -n1) if [ -z \"\$LATEST_BACKUP\" ]; then echo 'โŒ No backup found for rollback' exit 1 fi echo \"Rolling back to: \$LATEST_BACKUP\" # Deactivate current plugin wp plugin deactivate hvac-community-events --path=$DEPLOY_PATH # Remove current plugin directory rm -rf $DEPLOY_PATH/wp-content/plugins/hvac-community-events # Restore from backup cd $DEPLOY_PATH/wp-content/plugins tar -xzf /tmp/\$LATEST_BACKUP # Reactivate plugin wp plugin activate hvac-community-events --path=$DEPLOY_PATH wp rewrite flush --path=$DEPLOY_PATH echo 'โœ… Rollback completed successfully' " health-check: name: Environment Health Check runs-on: ubuntu-latest needs: validate-deployment if: needs.validate-deployment.outputs.proceed == 'true' && needs.validate-deployment.outputs.action == 'health-check' steps: - name: Comprehensive Health Check run: | echo "๐Ÿฅ Running comprehensive health check for ${{ needs.validate-deployment.outputs.environment }}..." # Setup environment variables if [ "${{ needs.validate-deployment.outputs.environment }}" = "staging" ]; then URL="${{ secrets.STAGING_URL }}" SSH_KEY="${{ secrets.STAGING_SSH_KEY }}" SSH_USER="${{ secrets.STAGING_SSH_USER }}" SSH_HOST="${{ secrets.STAGING_HOST }}" WP_PATH="${{ secrets.STAGING_WP_PATH }}" else URL="${{ secrets.PRODUCTION_URL }}" SSH_KEY="${{ secrets.PRODUCTION_SSH_KEY }}" SSH_USER="${{ secrets.PRODUCTION_SSH_USER }}" SSH_HOST="${{ secrets.PRODUCTION_HOST }}" WP_PATH="${{ secrets.PRODUCTION_WP_PATH }}" fi # Setup SSH mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts echo "๐ŸŒ Checking site accessibility..." HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" $URL) if [ "$HTTP_STATUS" = "200" ]; then echo "โœ… Site is accessible (HTTP $HTTP_STATUS)" else echo "โŒ Site accessibility issue (HTTP $HTTP_STATUS)" fi echo "๐Ÿ”Œ Checking plugin status..." ssh $SSH_USER@$SSH_HOST " cd $WP_PATH if wp plugin is-active hvac-community-events; then echo 'โœ… Plugin is active' wp plugin get hvac-community-events --field=version else echo 'โŒ Plugin is not active' fi # Check for errors if wp plugin list --status=error | grep hvac-community-events; then echo 'โŒ Plugin has errors' else echo 'โœ… Plugin has no errors' fi # Database connectivity if wp db check; then echo 'โœ… Database connection healthy' else echo 'โŒ Database connection issues' fi " cleanup: name: Cleanup Old Backups runs-on: ubuntu-latest needs: [validate-deployment, deploy, rollback, health-check] if: always() && needs.validate-deployment.outputs.proceed == 'true' steps: - name: Cleanup Old Backups run: | echo "๐Ÿงน Cleaning up old backups..." # Setup SSH based on environment mkdir -p ~/.ssh if [ "${{ needs.validate-deployment.outputs.environment }}" = "staging" ]; then echo "${{ secrets.STAGING_SSH_KEY }}" > ~/.ssh/id_rsa SSH_USER="${{ secrets.STAGING_SSH_USER }}" SSH_HOST="${{ secrets.STAGING_HOST }}" else echo "${{ secrets.PRODUCTION_SSH_KEY }}" > ~/.ssh/id_rsa SSH_USER="${{ secrets.PRODUCTION_SSH_USER }}" SSH_HOST="${{ secrets.PRODUCTION_HOST }}" fi chmod 600 ~/.ssh/id_rsa ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts ssh $SSH_USER@$SSH_HOST " cd /tmp # Remove backups older than retention period find . -name 'hvac-plugin-${{ needs.validate-deployment.outputs.environment }}-*' -type f -mtime +$BACKUP_RETENTION_DAYS -delete # Keep only the 5 most recent backups regardless of age ls -t hvac-plugin-${{ needs.validate-deployment.outputs.environment }}-*-plugin.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm ls -t hvac-plugin-${{ needs.validate-deployment.outputs.environment }}-*-db.sql.gz 2>/dev/null | tail -n +6 | xargs -r rm echo 'โœ… Backup cleanup completed' "