← back to Watches
.github/workflows/ci-cd-production.yml
165 lines
name: Production CI/CD Pipeline
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
env:
NODE_VERSION: '22'
SERVER_IP: 45.61.58.125
APP_PORT: 7600
PM2_APP_NAME: omega-watches
jobs:
test:
name: Run Tests & Quality Checks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --production --audit-level=high || true
- name: Check code quality
run: |
echo "Running code quality checks..."
npx eslint --init || echo "ESLint not configured"
- name: Test API endpoints
run: |
echo "Starting server for testing..."
node server.js &
SERVER_PID=$!
sleep 5
echo "Testing health endpoint..."
curl -f http://localhost:7600/api/health || exit 1
echo "Testing watches endpoint..."
curl -f http://localhost:7600/api/watches?limit=5 || exit 1
echo "Testing statistics endpoint..."
curl -f http://localhost:7600/api/statistics || exit 1
kill $SERVER_PID
- name: Build frontend
run: |
npm run build
ls -la dist/
- name: Archive build artifacts
uses: actions/upload-artifact@v4
with:
name: production-build
path: dist/
retention-days: 30
deploy-production:
name: Deploy to Production
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: production-build
path: dist/
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ env.SERVER_IP }} >> ~/.ssh/known_hosts
- name: Deploy to server
run: |
echo "Deploying to production server..."
# Create backup before deployment
ssh root@${{ env.SERVER_IP }} "cd /root/Projects/watches && npm run backup || true"
# Sync files (excluding node_modules and data)
rsync -avz --exclude 'node_modules' \
--exclude 'data/backups' \
--exclude '.git' \
--exclude 'logs' \
./ root@${{ env.SERVER_IP }}:/root/Projects/watches/
# Install dependencies and restart
ssh root@${{ env.SERVER_IP }} "
cd /root/Projects/watches && \
npm ci --production && \
pm2 restart ${{ env.PM2_APP_NAME }} || pm2 start server.js --name ${{ env.PM2_APP_NAME }} && \
pm2 save
"
- name: Health check after deployment
run: |
echo "Waiting for service to start..."
sleep 10
echo "Checking health endpoint..."
for i in {1..5}; do
if curl -f http://${{ env.SERVER_IP }}:${{ env.APP_PORT }}/api/health; then
echo "✓ Service is healthy!"
exit 0
fi
echo "Attempt $i failed, retrying..."
sleep 5
done
echo "✗ Health check failed!"
exit 1
- name: Notify deployment status
if: always()
run: |
if [ "${{ job.status }}" == "success" ]; then
echo "✅ Deployment successful!"
else
echo "❌ Deployment failed!"
fi
rollback:
name: Rollback Deployment
runs-on: ubuntu-latest
if: failure()
environment: production
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ env.SERVER_IP }} >> ~/.ssh/known_hosts
- name: Restore from backup
run: |
ssh root@${{ env.SERVER_IP }} "
cd /root/Projects/watches && \
npm run restore-latest-backup && \
pm2 restart ${{ env.PM2_APP_NAME }}
"