name: Deploy to EC2 on: push: branches: - main permissions: contents: read jobs: build-and-deploy: runs-on: ubuntu-latest env: NODE_ENV: production EC2_ENV: ${{ secrets.EC2_ENV }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Deploy to EC2 with rollback uses: appleboy/ssh-action@v1.2.0 env: EC2_ENV: ${{ secrets.EC2_ENV }} with: host: ${{ secrets.EC2_HOST }} username: ${{ secrets.EC2_USER }} key: ${{ secrets.EC2_SSH_KEY }} port: ${{ secrets.EC2_SSH_PORT || '22' }} script: | set -e APP_DIR="${APP_DIR:-/var/www/pdc-poc}" echo "Using app directory: $APP_DIR" mkdir -p "$APP_DIR" cd "$APP_DIR" # Initialize git repo if needed if [ ! -d ".git" ]; then echo "Cloning repository for the first time..." git clone ${{ github.repositoryUrl }} . fi git remote set-url origin ${{ github.repositoryUrl }} PREV_COMMIT=$(git rev-parse HEAD || echo "") echo "Previous commit: $PREV_COMMIT" echo "Fetching latest changes..." git fetch origin git checkout ${{ github.ref_name }} git reset --hard ${{ github.sha }} echo "Writing .env file from EC2_ENV secret..." # Write .env file AFTER pulling latest code so it's in the right location # EC2_ENV is provided by GitHub as a multi-line secret matching your local .env printf '%s\n' "$EC2_ENV" > .env echo "Checking Docker and Docker Compose..." if ! command -v docker >/dev/null 2>&1; then echo "Error: Docker is not installed" exit 1 fi if command -v docker-compose >/dev/null 2>&1; then DC="docker-compose" elif docker compose version >/dev/null 2>&1; then DC="docker compose" else echo "Error: Docker Compose is not installed" exit 1 fi echo "Using: $DC" $DC version echo "Stopping existing containers..." $DC down || true echo "Building and starting containers with docker-compose..." set +e $DC up -d --build DEPLOY_EXIT=$? set -e if [ $DEPLOY_EXIT -ne 0 ]; then echo "Deployment failed, attempting rollback..." if [ -n "$PREV_COMMIT" ]; then git reset --hard "$PREV_COMMIT" printf '%s\n' "$EC2_ENV" > .env $DC up -d --build || true fi exit 1 fi echo "Waiting for containers to be healthy..." sleep 10 echo "Running health check..." HEALTH_URL="${HEALTH_URL:-http://localhost:3000/api/health}" for i in {1..15}; do if curl -fsS "$HEALTH_URL" >/dev/null 2>&1; then echo "Health check passed on attempt $i." echo "Deployment successful!" exit 0 fi echo "Health check attempt $i failed, retrying in 5 seconds..." sleep 5 done echo "Health check failed after multiple attempts, rolling back..." if [ -n "$PREV_COMMIT" ]; then git reset --hard "$PREV_COMMIT" printf '%s\n' "$EC2_ENV" > .env $DC up -d --build || true fi exit 1