142 lines
6.8 KiB
YAML
142 lines
6.8 KiB
YAML
# .gitea/workflows/deploy-to-prod.yml
|
|
#
|
|
# This workflow provides a MANUAL trigger to deploy the application to the
|
|
# PRODUCTION environment. This should only be run after the 'Deploy to Test'
|
|
# workflow has succeeded on the desired commit.
|
|
name: Manual - Deploy to Production
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
confirmation:
|
|
description: 'Type "deploy-to-prod" to confirm you want to deploy the main branch.'
|
|
required: true
|
|
default: 'do-not-run'
|
|
|
|
jobs:
|
|
deploy-production:
|
|
runs-on: projectium.com
|
|
|
|
steps:
|
|
- name: Verify Confirmation Phrase
|
|
run: |
|
|
if [ "${{ gitea.event.inputs.confirmation }}" != "deploy-to-prod" ]; then
|
|
echo "ERROR: Confirmation phrase did not match. Aborting deployment."
|
|
exit 1
|
|
fi
|
|
echo "✅ Confirmation accepted. Proceeding with production deployment."
|
|
|
|
- name: Checkout Code from 'main' branch
|
|
uses: actions/checkout@v3
|
|
with:
|
|
ref: 'main' # Explicitly check out the main branch for production deployment
|
|
fetch-depth: 0
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v3
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
cache-dependency-path: '**/package-lock.json'
|
|
|
|
- name: Install Dependencies
|
|
run: npm ci
|
|
|
|
- name: Check for Production Database Schema Changes
|
|
env:
|
|
DB_HOST: ${{ secrets.DB_HOST }}
|
|
DB_USER: ${{ secrets.DB_USER }}
|
|
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
|
DB_NAME: ${{ secrets.DB_DATABASE_PROD }}
|
|
run: |
|
|
if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ] || [ -z "$DB_NAME" ]; then
|
|
echo "ERROR: One or more production database secrets (DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE_PROD) are not set."
|
|
exit 1
|
|
fi
|
|
echo "--- Checking for production schema changes ---"
|
|
CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
|
|
echo "Current Git Schema Hash: $CURRENT_HASH"
|
|
DEPLOYED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c "SELECT schema_hash FROM public.schema_info WHERE id = 1;" -t -A || echo "none")
|
|
echo "Deployed DB Schema Hash: $DEPLOYED_HASH"
|
|
if [ "$DEPLOYED_HASH" = "none" ] || [ -z "$DEPLOYED_HASH" ]; then
|
|
echo "WARNING: No schema hash found in the production database. This is expected for a first-time deployment."
|
|
elif [ "$CURRENT_HASH" != "$DEPLOYED_HASH" ]; then
|
|
echo "ERROR: Database schema mismatch detected! A manual database migration is required."
|
|
exit 1
|
|
else
|
|
echo "✅ Schema is up to date. No changes detected."
|
|
fi
|
|
|
|
- name: Build React Application for Production
|
|
run: |
|
|
if [ -z "${{ secrets.VITE_GOOGLE_GENAI_API_KEY }}" ]; then
|
|
echo "ERROR: The VITE_GOOGLE_GENAI_API_KEY secret is not set."
|
|
exit 1
|
|
fi
|
|
GITEA_SERVER_URL="https://gitea.projectium.com"
|
|
COMMIT_MESSAGE=$(git log -1 --pretty=%s)
|
|
VITE_APP_VERSION="$(date +'%Y%m%d-%H%M'):$(git rev-parse --short HEAD)" \
|
|
VITE_APP_COMMIT_URL="$GITEA_SERVER_URL/${{ gitea.repository }}/commit/${{ gitea.sha }}" \
|
|
VITE_APP_COMMIT_MESSAGE="$COMMIT_MESSAGE" \
|
|
VITE_API_BASE_URL=/api VITE_API_KEY=${{ secrets.VITE_GOOGLE_GENAI_API_KEY }} npm run build
|
|
|
|
- name: Deploy Application to Production Server
|
|
run: |
|
|
echo "Deploying application files to /var/www/flyer-crawler.projectium.com..."
|
|
APP_PATH="/var/www/flyer-crawler.projectium.com"
|
|
mkdir -p "$APP_PATH"
|
|
mkdir -p "$APP_PATH/flyer-images/icons" "$APP_PATH/flyer-images/archive"
|
|
rsync -avz --delete --exclude 'node_modules' --exclude '.git' --exclude 'dist' --exclude 'flyer-images' ./ "$APP_PATH/"
|
|
rsync -avz dist/ "$APP_PATH"
|
|
echo "Application deployment complete."
|
|
|
|
- name: Install Backend Dependencies and Restart Production Server
|
|
env:
|
|
# --- Production Secrets Injection ---
|
|
DB_HOST: ${{ secrets.DB_HOST }}
|
|
DB_USER: ${{ secrets.DB_USER }}
|
|
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
|
DB_NAME: ${{ secrets.DB_DATABASE_PROD }}
|
|
REDIS_URL: "redis://localhost:6379"
|
|
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD_PROD }}
|
|
FRONTEND_URL: "https://flyer-crawler.projectium.com"
|
|
JWT_SECRET: ${{ secrets.JWT_SECRET }}
|
|
GEMINI_API_KEY: ${{ secrets.VITE_GOOGLE_GENAI_API_KEY }}
|
|
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
|
|
SMTP_HOST: "localhost"
|
|
SMTP_PORT: "1025"
|
|
SMTP_SECURE: "false"
|
|
SMTP_USER: ""
|
|
SMTP_PASS: ""
|
|
SMTP_FROM_EMAIL: "noreply@flyer-crawler.projectium.com"
|
|
run: |
|
|
if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ] || [ -z "$DB_NAME" ]; then
|
|
echo "ERROR: One or more production database secrets (DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE_PROD) are not set."
|
|
exit 1
|
|
fi
|
|
echo "Installing production dependencies and restarting server..."
|
|
cd /var/www/flyer-crawler.projectium.com
|
|
npm install --omit=dev
|
|
pm2 startOrReload ecosystem.config.cjs --env production && pm2 save
|
|
echo "Production backend server reloaded successfully."
|
|
|
|
echo "Updating schema hash in production database..."
|
|
CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
|
|
PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c \
|
|
"INSERT INTO public.schema_info (id, schema_hash, deployed_at) VALUES (1, '$CURRENT_HASH', NOW())
|
|
ON CONFLICT (id) DO UPDATE SET schema_hash = EXCLUDED.schema_hash, deployed_at = NOW();"
|
|
|
|
UPDATED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -v ON_ERROR_STOP=1 -h "$DB_HOST" -p 5432 -U "$DB_USER" -d "$DB_NAME" -c "SELECT schema_hash FROM public.schema_info WHERE id = 1;" -t -A)
|
|
if [ "$CURRENT_HASH" = "$UPDATED_HASH" ]; then
|
|
echo "✅ Schema hash successfully updated in the database to: $UPDATED_HASH"
|
|
else
|
|
echo "ERROR: Failed to update schema hash in the database."
|
|
fi
|
|
|
|
- name: Show PM2 Environment for Production
|
|
run: |
|
|
echo "--- Displaying recent PM2 logs for flyer-crawler-api ---"
|
|
sleep 5
|
|
pm2 describe flyer-crawler-api || echo "Could not find production pm2 process."
|
|
pm2 logs flyer-crawler-api --lines 20 --nostream || echo "Could not find production pm2 process."
|
|
pm2 env flyer-crawler-api || echo "Could not find production pm2 process." |