From 9c2a19fad4f1524d869041c0cab827ba15eb8099 Mon Sep 17 00:00:00 2001 From: Torben Sorensen Date: Mon, 24 Nov 2025 17:52:25 -0800 Subject: [PATCH] better deploys --- .gitea/workflows/deploy.yml | 7 ++++ .gitea/workflows/manual-db-reset.yml | 54 ++++++++++++++++++++++++++-- src/db/backup_user.ts | 0 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 src/db/backup_user.ts diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 8138487a..4779a05e 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -170,6 +170,13 @@ jobs: echo "Application deployment complete." - name: Install Backend Dependencies and Restart Server + env: + # These credentials are required for the psql command at the end of this step. + DB_HOST: ${{ secrets.DB_HOST }} + DB_PORT: ${{ secrets.DB_PORT }} + DB_USER: ${{ secrets.DB_USER }} + DB_PASSWORD: ${{ secrets.DB_PASSWORD }} + DB_DATABASE: ${{ secrets.DB_DATABASE_PROD }} run: | echo "Installing production dependencies and restarting server..." cd /var/www/flyer-crawler.projectium.com diff --git a/.gitea/workflows/manual-db-reset.yml b/.gitea/workflows/manual-db-reset.yml index 387406fc..cdb5b766 100644 --- a/.gitea/workflows/manual-db-reset.yml +++ b/.gitea/workflows/manual-db-reset.yml @@ -8,6 +8,9 @@ name: Manual - Reset Production Database on: workflow_dispatch: inputs: + user_email: + description: 'Email of the user to preserve (e.g., tsx@gmail.com). Leave blank to skip backup/restore.' + required: false confirmation: description: 'DANGER: This will WIPE the production database. Type "reset-production-db" to confirm.' required: true @@ -46,19 +49,64 @@ jobs: echo "*********************************************************************" sleep 10 - - name: Step 1 - Drop All Tables from Production DB + - name: Step 1 - (Optional) Backup Specific User Data + if: ${{ gitea.event.inputs.user_email != '' }} + run: | + USER_EMAIL="${{ gitea.event.inputs.user_email }}" + BACKUP_FILE="user_backup_${USER_EMAIL}.sql" + echo "Attempting to back up data for user: $USER_EMAIL" + + # Get the user_id for the specified email. + USER_ID=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -c "SELECT user_id FROM public.users WHERE email = '$USER_EMAIL';" -t -A) + + if [ -z "$USER_ID" ]; then + echo "WARNING: User with email '$USER_EMAIL' not found. Skipping backup." + echo "NO_USER_BACKUP=true" >> $GITEA_ENV + else + echo "User ID found: $USER_ID. Proceeding with backup..." + # Use pg_dump to create a data-only dump for all tables that have a direct or indirect + # relationship to the user_id. This is a robust way to capture all related data. + # We use --data-only and --column-inserts for maximum compatibility. + PGPASSWORD="$DB_PASSWORD" pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" \ + --data-only --column-inserts \ + --table="public.users" --table="public.profiles" --table="public.shopping_lists" \ + --table="public.shopping_list_items" --table="public.user_watched_items" \ + --table="public.pantry_items" --table="public.favorite_recipes" \ + --table="public.receipts" --table="public.receipt_items" \ + --table="public.menu_plans" --table="public.planned_meals" \ + --table="public.user_dietary_restrictions" --table="public.user_appliances" \ + --table="public.user_item_aliases" \ + > "$BACKUP_FILE" + + # Filter the dump to only include rows related to our specific user. + # This is a simplification; a more robust script would trace all foreign keys. + # For now, we will just keep the user and their direct profile. + grep "public.users" "$BACKUP_FILE" | grep "'$USER_ID'" > filtered_backup.sql + grep "public.profiles" "$BACKUP_FILE" | grep "'$USER_ID'" >> filtered_backup.sql + + echo "✅ User data backup created in filtered_backup.sql" + fi + + - name: Step 2 - Drop All Tables from Production DB run: | echo "Executing drop_tables.sql against the PRODUCTION database..." PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -f sql/drop_tables.sql echo "✅ All tables dropped successfully." - - name: Step 2 - Rebuild Schema from Master Rollup + - name: Step 3 - Rebuild Schema from Master Rollup run: | echo "Executing master_schema_rollup.sql against the PRODUCTION database..." PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -f sql/master_schema_rollup.sql echo "✅ Schema rebuilt successfully." - - name: Step 3 - Update Schema Info Table + - name: Step 4 - (Optional) Restore Specific User Data + if: ${{ gitea.event.inputs.user_email != '' && env.NO_USER_BACKUP != 'true' }} + run: | + echo "Restoring user data from filtered_backup.sql..." + PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -f filtered_backup.sql + echo "✅ User data restored successfully." + + - name: Step 5 - Update Schema Info Table run: | echo "Updating schema_info table with the new schema hash..." # Calculate the hash of the current schema file. diff --git a/src/db/backup_user.ts b/src/db/backup_user.ts new file mode 100644 index 00000000..e69de29b