← back to NationalPaperHangers

scripts/deploy-kamatera-v3-data.sh

88 lines

#!/usr/bin/env bash
#
# v3 — post-deploy data + LinkedIn env push.
#
# After v2 stood up the prod stack, the Kamatera DB is empty and .env
# doesn't yet have the LinkedIn OAuth creds. This finishes both:
#   1. Merges LINKEDIN_CLIENT_ID + LINKEDIN_CLIENT_SECRET into Kamatera .env
#      (idempotent — won't clobber existing values)
#   2. pg_dump's the studio data tables from local Mac PG → ship over SSH →
#      pg_restore into Kamatera DB
#   3. pm2 restart to pick up new env
#   4. Smoke test installer pages
#
# Tables migrated: installers, installer_portfolio, installer_credentials,
# installer_reviews, installer_availability, installer_time_off.
# (consumer_accounts, bookings, consumer_leads stay empty on prod — those
#  are user-generated and shouldn't carry over.)

set -euo pipefail

REMOTE="${NPH_REMOTE_HOST:-root@45.61.58.125}"
RDIR="${NPH_REMOTE_DIR:-/root/Projects/NationalPaperHangers}"
DOMAIN="${NPH_DOMAIN:-nationalpaperhangers.com}"
LOCAL_DB="${NPH_LOCAL_DB:-national_paper_hangers}"

say() { printf '\n[deploy-v3] %s\n' "$*"; }

# --- 1. LinkedIn env push (read from local .env, merge into prod .env) ---
say "Merging LINKEDIN_* into Kamatera .env (non-clobbering) ..."
LI_BLOCK="$(grep -E '^LINKEDIN_(CLIENT_ID|CLIENT_SECRET)=' "$HOME/Projects/NationalPaperHangers/.env" || true)"
if [ -z "$LI_BLOCK" ]; then
  echo "  (no LINKEDIN_* values in local .env — skipping)"
else
  ssh "$REMOTE" "cd $RDIR && \
    awk -v new=\"\$(cat)\" 'BEGIN{n=split(new,arr,\"\\n\"); for(i=1;i<=n;i++){split(arr[i],kv,\"=\"); if(kv[1]) want[kv[1]]=arr[i]}} { for(k in want){ if(\$0 ~ \"^\"k\"=\"){ delete want[k]; break } } print } END { for(k in want) print want[k] }' .env > .env.new && \
    mv .env.new .env && chmod 600 .env && \
    echo \"  .env now has \$(grep -c '^LINKEDIN_' .env) LINKEDIN_* keys\"" <<< "$LI_BLOCK"
fi

# --- 2. pg_dump → Kamatera ------------------------------------------------
say "Dumping studio tables from local PG ..."
DUMP_FILE="$(mktemp -t nph-data-XXXXXX.sql)"
pg_dump --data-only --no-owner --no-privileges \
  --table=installers \
  --table=installer_portfolio \
  --table=installer_credentials \
  --table=installer_reviews \
  --table=installer_availability \
  --table=installer_time_off \
  "$LOCAL_DB" > "$DUMP_FILE"
ROWS=$(grep -c '^COPY ' "$DUMP_FILE" || true)
SIZE=$(wc -c <"$DUMP_FILE" | tr -d ' ')
echo "  $ROWS COPY blocks, $SIZE bytes"

say "Loading dump into Kamatera DB ..."
# Truncate target tables first so re-running is idempotent and we don't get
# PK collisions from the fresh-after-v2 row count of zero (defensive).
ssh "$REMOTE" "cd $RDIR && set -a && . .env && set +a && \
  psql \"\$DATABASE_URL\" -v ON_ERROR_STOP=1 -c 'TRUNCATE installers, installer_portfolio, installer_credentials, installer_reviews, installer_availability, installer_time_off RESTART IDENTITY CASCADE;'"

ssh "$REMOTE" "cd $RDIR && set -a && . .env && set +a && \
  psql \"\$DATABASE_URL\" -v ON_ERROR_STOP=1" < "$DUMP_FILE" 2>&1 | tail -8
rm -f "$DUMP_FILE"

# --- 3. Verify counts -----------------------------------------------------
say "Row counts on prod after restore ..."
ssh "$REMOTE" "cd $RDIR && set -a && . .env && set +a && \
  psql \"\$DATABASE_URL\" -At -c \"SELECT 'installers',COUNT(*) FROM installers
                                     UNION ALL SELECT 'portfolio',COUNT(*) FROM installer_portfolio
                                     UNION ALL SELECT 'credentials',COUNT(*) FROM installer_credentials
                                     UNION ALL SELECT 'reviews',COUNT(*) FROM installer_reviews;\""

# --- 4. Restart pm2 to pick up new env ------------------------------------
say "pm2 restart with --update-env ..."
ssh "$REMOTE" "pm2 restart national-paper-hangers --update-env" 2>&1 | tail -3
sleep 2

# --- 5. Smoke ------------------------------------------------------------
say "Smoke testing installer pages on https://$DOMAIN ..."
SLUG=$(ssh "$REMOTE" "cd $RDIR && set -a && . .env && set +a && psql \"\$DATABASE_URL\" -tAc \"SELECT slug FROM installers WHERE claim_status='unclaimed' ORDER BY id LIMIT 1\"")
echo "  test slug: $SLUG"
for path in "/installer/$SLUG" "/installer/$SLUG/book" "/find?segment=luxury_residential"; do
  code=$(curl -s -o /dev/null -w '%{http_code}' "https://$DOMAIN$path" --max-time 10 || echo "TIMEOUT")
  printf '  https://%s%s → %s\n' "$DOMAIN" "$path" "$code"
done

say "Done."