← 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."