better deploys
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 2m40s
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 2m40s
This commit is contained in:
@@ -103,6 +103,41 @@ jobs:
|
||||
name: code-coverage-report
|
||||
path: .coverage/
|
||||
|
||||
- name: Check for Database Schema Changes
|
||||
env:
|
||||
# Use production database credentials for this check.
|
||||
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 }} # Assumes a secret for the production DB name.
|
||||
run: |
|
||||
echo "--- Checking for schema changes ---"
|
||||
# Calculate the hash of the current schema file in the repository.
|
||||
# We normalize line endings to ensure the hash is consistent across different OS environments.
|
||||
CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
|
||||
echo "Current Git Schema Hash: $CURRENT_HASH"
|
||||
|
||||
# Query the production database to get the hash of the deployed schema.
|
||||
# The `psql` command requires PGPASSWORD to be set.
|
||||
# `\t` sets tuples-only mode and `\A` unaligns output to get just the raw value.
|
||||
# The `|| echo "none"` ensures the command doesn't fail if the table or row doesn't exist yet.
|
||||
DEPLOYED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -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" ]; then
|
||||
echo "WARNING: No schema hash found in the production database."
|
||||
echo "This is expected for a first-time deployment. The hash will be set after a successful deployment."
|
||||
# We allow the deployment to continue, but a manual schema update is required.
|
||||
# You could choose to fail here by adding `exit 1`.
|
||||
elif [ "$CURRENT_HASH" != "$DEPLOYED_HASH" ]; then
|
||||
echo "ERROR: Database schema mismatch detected!"
|
||||
echo "The schema file in the repository has changed. A manual database migration is required."
|
||||
exit 1 # Fail the deployment pipeline.
|
||||
else
|
||||
echo "✅ Schema is up to date. No changes detected."
|
||||
fi
|
||||
|
||||
# --- Frontend Deployment ---
|
||||
- name: Build React Application
|
||||
# We set the environment variable directly in the command line for this step.
|
||||
@@ -144,6 +179,22 @@ jobs:
|
||||
# We also add `&& pm2 save` to persist the process list across server reboots.
|
||||
pm2 startOrReload ecosystem.config.cjs --env production && pm2 save
|
||||
echo "Backend server reloaded successfully."
|
||||
|
||||
# After a successful deployment, update the schema hash in the database.
|
||||
# This ensures the next deployment will compare against this new state.
|
||||
echo "Updating schema hash in production database..."
|
||||
CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
|
||||
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -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();"
|
||||
|
||||
# Verify the hash was updated
|
||||
UPDATED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -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: |
|
||||
|
||||
80
.gitea/workflows/manual-db-reset.yml
Normal file
80
.gitea/workflows/manual-db-reset.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
# FILE: .gitea/workflows/manual-db-reset.yml
|
||||
#
|
||||
# DANGER: This workflow is DESTRUCTIVE and intended for manual execution only.
|
||||
# It will completely WIPE and RESET the PRODUCTION database.
|
||||
#
|
||||
name: Manual - Reset Production Database
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
confirmation:
|
||||
description: 'DANGER: This will WIPE the production database. Type "reset-production-db" to confirm.'
|
||||
required: true
|
||||
default: 'do-not-run'
|
||||
|
||||
jobs:
|
||||
reset-database:
|
||||
runs-on: projectium.com # This job runs on your self-hosted Gitea runner.
|
||||
|
||||
env:
|
||||
# Use production database credentials for this entire job.
|
||||
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 }} # Assumes a secret for the production DB name.
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Verify Confirmation Phrase
|
||||
run: |
|
||||
if [ "${{ gitea.event.inputs.confirmation }}" != "reset-production-db" ]; then
|
||||
echo "ERROR: Confirmation phrase did not match. Aborting database reset."
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ Confirmation accepted. Proceeding with database reset."
|
||||
|
||||
- name: 🚨 FINAL WARNING & PAUSE 🚨
|
||||
run: |
|
||||
echo "*********************************************************************"
|
||||
echo "WARNING: YOU ARE ABOUT TO WIPE AND RESET THE PRODUCTION DATABASE."
|
||||
echo "This action is IRREVERSIBLE. Press Ctrl+C in the runner terminal NOW to cancel."
|
||||
echo "Sleeping for 10 seconds..."
|
||||
echo "*********************************************************************"
|
||||
sleep 10
|
||||
|
||||
- name: Step 1 - 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
|
||||
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
|
||||
run: |
|
||||
echo "Updating schema_info table with the new schema hash..."
|
||||
# Calculate the hash of the current schema file.
|
||||
CURRENT_HASH=$(cat sql/master_schema_rollup.sql | dos2unix | sha256sum | awk '{ print $1 }')
|
||||
echo "New Schema Hash: $CURRENT_HASH"
|
||||
|
||||
# Insert the new hash into the freshly created schema_info table.
|
||||
PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -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();"
|
||||
|
||||
# Verify the hash was updated
|
||||
UPDATED_HASH=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_DATABASE" -c "SELECT schema_hash FROM public.schema_info WHERE id = 1;" -t -A)
|
||||
if [ "$CURRENT_HASH" = "$UPDATED_HASH" ]; then
|
||||
echo "✅ Schema hash successfully set in the database to: $UPDATED_HASH"
|
||||
else
|
||||
echo "ERROR: Failed to set schema hash in the database."
|
||||
exit 1
|
||||
fi
|
||||
@@ -57,4 +57,5 @@ DROP TABLE IF EXISTS public.categories CASCADE;
|
||||
DROP TABLE IF EXISTS public.profiles CASCADE;
|
||||
DROP TABLE IF EXISTS public.password_reset_tokens CASCADE;
|
||||
DROP TABLE IF EXISTS public.users CASCADE;
|
||||
DROP TABLE IF EXISTS public.schema_info CASCADE;
|
||||
DROP TABLE IF EXISTS public.unmatched_flyer_items CASCADE;
|
||||
|
||||
@@ -824,3 +824,13 @@ CREATE TABLE IF NOT EXISTS public.receipt_items (
|
||||
COMMENT ON TABLE public.receipt_items IS 'Stores individual line items extracted from a user receipt.';
|
||||
CREATE INDEX IF NOT EXISTS idx_receipt_items_receipt_id ON public.receipt_items(receipt_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_receipt_items_master_item_id ON public.receipt_items(master_item_id);
|
||||
|
||||
-- 54. Store schema metadata to detect changes during deployment.
|
||||
CREATE TABLE IF NOT EXISTS public.schema_info (
|
||||
id INT PRIMARY KEY DEFAULT 1,
|
||||
schema_hash TEXT NOT NULL,
|
||||
deployed_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
CONSTRAINT single_row_check CHECK (id = 1)
|
||||
);
|
||||
COMMENT ON TABLE public.schema_info IS 'Stores metadata about the deployed schema, such as a hash of the schema file, to detect changes.';
|
||||
COMMENT ON COLUMN public.schema_info.schema_hash IS 'A SHA-256 hash of the master_schema_rollup.sql file at the time of deployment.';
|
||||
|
||||
@@ -846,6 +846,17 @@ COMMENT ON TABLE public.receipt_items IS 'Stores individual line items extracted
|
||||
CREATE INDEX IF NOT EXISTS idx_receipt_items_receipt_id ON public.receipt_items(receipt_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_receipt_items_master_item_id ON public.receipt_items(master_item_id);
|
||||
|
||||
-- 54. Store schema metadata to detect changes during deployment.
|
||||
CREATE TABLE IF NOT EXISTS public.schema_info (
|
||||
id INT PRIMARY KEY DEFAULT 1,
|
||||
schema_hash TEXT NOT NULL,
|
||||
deployed_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
CONSTRAINT single_row_check CHECK (id = 1)
|
||||
);
|
||||
COMMENT ON TABLE public.schema_info IS 'Stores metadata about the deployed schema, such as a hash of the schema file, to detect changes.';
|
||||
COMMENT ON COLUMN public.schema_info.schema_hash IS 'A SHA-256 hash of the master_schema_rollup.sql file at the time of deployment.';
|
||||
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
-- PART 2: DATA SEEDING
|
||||
|
||||
Reference in New Issue
Block a user