916ad39176
Deploy to route.crispygoat.com / deploy (push) Failing after 3m1s
- Add MinIO/S3-compatible storage client (src/lib/storage.ts) with uploadObject, deleteObject, presigned URL helpers, and BUCKETS constant - Wire product images, brand logos, and water log photos to MinIO via the new storage client - Migrate forgot-password to Neon Auth (remove Supabase /auth/v1/recover call) - Migrate send-scheduled cron to direct Postgres + Resend (remove Supabase Edge Function proxy) - Add logoUrl to email types (OrderReceipt, Welcome, PasswordReset) and pass brand_settings.logo_url from all call sites - Update email templates to use dynamic logoUrl instead of hardcoded Supabase bucket URLs - Remove hardcoded Supabase URLs from TuxedoVideoHero, TuxedoAboutPage, TimeTrackingFieldClient; use brand_settings props + local public/ fallback - Download brand logos (3) and tuxedo-hero.mp4 (36MB) from Supabase bucket to public/ for local development - Add MinIO env vars to .env.example (endpoint, access key, secret, buckets) - Fix TimeTrackingFieldClient to destructure logoUrl and brandAccent props - Fix admin/users.ts logoUrl type (null → undefined for optional string) - Remove stale sb- cookie from wholesale-auth - Migrate tuxedo/about page to remove supabase import and use pool query for wholesale_settings lookup
169 lines
8.4 KiB
YAML
169 lines
8.4 KiB
YAML
name: Deploy to route.crispygoat.com
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
|
|
- name: Install dependencies
|
|
run: npm install
|
|
|
|
- name: Run migrations
|
|
env:
|
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
run: |
|
|
npm run migrate:one || echo "No migration script or migrations already applied"
|
|
|
|
- name: Build
|
|
env:
|
|
NODE_ENV: production
|
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }}
|
|
NEON_AUTH_BASE_URL: ${{ secrets.NEON_AUTH_BASE_URL }}
|
|
NEON_AUTH_COOKIE_SECRET: ${{ secrets.NEON_AUTH_COOKIE_SECRET }}
|
|
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
|
|
AUTH_URL: ${{ secrets.AUTH_URL }}
|
|
NEXT_PUBLIC_AUTH_URL: ${{ secrets.NEXT_PUBLIC_AUTH_URL }}
|
|
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
|
|
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
|
|
ALLOW_DEV_LOGIN: ${{ secrets.ALLOW_DEV_LOGIN }}
|
|
ADMIN_ALLOWED_EMAILS: ${{ secrets.ADMIN_ALLOWED_EMAILS }}
|
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
|
|
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
|
|
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
|
|
STRIPE_PRICE_STARTER: ${{ secrets.STRIPE_PRICE_STARTER }}
|
|
STRIPE_PRICE_FARM: ${{ secrets.STRIPE_PRICE_FARM }}
|
|
STRIPE_PRICE_ENTERPRISE: ${{ secrets.STRIPE_PRICE_ENTERPRISE }}
|
|
STRIPE_PRICE_HARVEST_REACH: ${{ secrets.STRIPE_PRICE_HARVEST_REACH }}
|
|
STRIPE_PRICE_WHOLESALE_PORTAL: ${{ secrets.STRIPE_PRICE_WHOLESALE_PORTAL }}
|
|
STRIPE_PRICE_WATER_LOG: ${{ secrets.STRIPE_PRICE_WATER_LOG }}
|
|
STRIPE_PRICE_AI_TOOLS: ${{ secrets.STRIPE_PRICE_AI_TOOLS }}
|
|
STRIPE_PRICE_SQUARE_SYNC: ${{ secrets.STRIPE_PRICE_SQUARE_SYNC }}
|
|
STRIPE_PRICE_SMS_CAMPAIGNS: ${{ secrets.STRIPE_PRICE_SMS_CAMPAIGNS }}
|
|
RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
|
|
FROM_EMAIL: ${{ secrets.FROM_EMAIL }}
|
|
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
MINIO_REGION: ${{ secrets.MINIO_REGION }}
|
|
MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
MINIO_SECRET_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
|
|
MINIO_BUCKET_PRODUCTS: ${{ secrets.MINIO_BUCKET_PRODUCTS }}
|
|
MINIO_BUCKET_BRAND_LOGOS: ${{ secrets.MINIO_BUCKET_BRAND_LOGOS }}
|
|
MINIO_BUCKET_WATER_LOGS: ${{ secrets.MINIO_BUCKET_WATER_LOGS }}
|
|
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
|
|
MINIMAX_BASE_URL: ${{ secrets.MINIMAX_BASE_URL }}
|
|
run: npm run build
|
|
|
|
- name: Deploy
|
|
env:
|
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
NEXT_PUBLIC_SITE_URL: ${{ secrets.NEXT_PUBLIC_SITE_URL }}
|
|
NEON_AUTH_BASE_URL: ${{ secrets.NEON_AUTH_BASE_URL }}
|
|
NEON_AUTH_COOKIE_SECRET: ${{ secrets.NEON_AUTH_COOKIE_SECRET }}
|
|
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
|
|
AUTH_URL: ${{ secrets.AUTH_URL }}
|
|
NEXT_PUBLIC_AUTH_URL: ${{ secrets.NEXT_PUBLIC_AUTH_URL }}
|
|
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
|
|
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
|
|
ALLOW_DEV_LOGIN: ${{ secrets.ALLOW_DEV_LOGIN }}
|
|
ADMIN_ALLOWED_EMAILS: ${{ secrets.ADMIN_ALLOWED_EMAILS }}
|
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY }}
|
|
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
|
|
STRIPE_WEBHOOK_SECRET: ${{ secrets.STRIPE_WEBHOOK_SECRET }}
|
|
STRIPE_PRICE_STARTER: ${{ secrets.STRIPE_PRICE_STARTER }}
|
|
STRIPE_PRICE_FARM: ${{ secrets.STRIPE_PRICE_FARM }}
|
|
STRIPE_PRICE_ENTERPRISE: ${{ secrets.STRIPE_PRICE_ENTERPRISE }}
|
|
STRIPE_PRICE_HARVEST_REACH: ${{ secrets.STRIPE_PRICE_HARVEST_REACH }}
|
|
STRIPE_PRICE_WHOLESALE_PORTAL: ${{ secrets.STRIPE_PRICE_WHOLESALE_PORTAL }}
|
|
STRIPE_PRICE_WATER_LOG: ${{ secrets.STRIPE_PRICE_WATER_LOG }}
|
|
STRIPE_PRICE_AI_TOOLS: ${{ secrets.STRIPE_PRICE_AI_TOOLS }}
|
|
STRIPE_PRICE_SQUARE_SYNC: ${{ secrets.STRIPE_PRICE_SQUARE_SYNC }}
|
|
STRIPE_PRICE_SMS_CAMPAIGNS: ${{ secrets.STRIPE_PRICE_SMS_CAMPAIGNS }}
|
|
RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
|
|
FROM_EMAIL: ${{ secrets.FROM_EMAIL }}
|
|
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
|
|
MINIO_REGION: ${{ secrets.MINIO_REGION }}
|
|
MINIO_ACCESS_KEY: ${{ secrets.MINIO_ACCESS_KEY }}
|
|
MINIO_SECRET_KEY: ${{ secrets.MINIO_SECRET_KEY }}
|
|
MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
|
|
MINIO_BUCKET_PRODUCTS: ${{ secrets.MINIO_BUCKET_PRODUCTS }}
|
|
MINIO_BUCKET_BRAND_LOGOS: ${{ secrets.MINIO_BUCKET_BRAND_LOGOS }}
|
|
MINIO_BUCKET_WATER_LOGS: ${{ secrets.MINIO_BUCKET_WATER_LOGS }}
|
|
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
|
|
MINIMAX_BASE_URL: ${{ secrets.MINIMAX_BASE_URL }}
|
|
CRON_SECRET: ${{ secrets.CRON_SECRET }}
|
|
run: |
|
|
APP_DIR=/home/tyler/route-commerce
|
|
|
|
# Write production env file
|
|
{
|
|
printf "DATABASE_URL=%s\n" "$DATABASE_URL"
|
|
printf "NEXT_PUBLIC_SITE_URL=%s\n" "$NEXT_PUBLIC_SITE_URL"
|
|
printf "NEON_AUTH_BASE_URL=%s\n" "$NEON_AUTH_BASE_URL"
|
|
printf "NEON_AUTH_COOKIE_SECRET=%s\n" "$NEON_AUTH_COOKIE_SECRET"
|
|
printf "AUTH_SECRET=%s\n" "$AUTH_SECRET"
|
|
printf "AUTH_URL=%s\n" "$AUTH_URL"
|
|
printf "NEXT_PUBLIC_AUTH_URL=%s\n" "$NEXT_PUBLIC_AUTH_URL"
|
|
printf "GOOGLE_CLIENT_ID=%s\n" "$GOOGLE_CLIENT_ID"
|
|
printf "GOOGLE_CLIENT_SECRET=%s\n" "$GOOGLE_CLIENT_SECRET"
|
|
printf "ALLOW_DEV_LOGIN=%s\n" "$ALLOW_DEV_LOGIN"
|
|
printf "ADMIN_ALLOWED_EMAILS=%s\n" "$ADMIN_ALLOWED_EMAILS"
|
|
printf "NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=%s\n" "$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY"
|
|
printf "STRIPE_SECRET_KEY=%s\n" "$STRIPE_SECRET_KEY"
|
|
printf "STRIPE_WEBHOOK_SECRET=%s\n" "$STRIPE_WEBHOOK_SECRET"
|
|
printf "STRIPE_PRICE_STARTER=%s\n" "$STRIPE_PRICE_STARTER"
|
|
printf "STRIPE_PRICE_FARM=%s\n" "$STRIPE_PRICE_FARM"
|
|
printf "STRIPE_PRICE_ENTERPRISE=%s\n" "$STRIPE_PRICE_ENTERPRISE"
|
|
printf "STRIPE_PRICE_HARVEST_REACH=%s\n" "$STRIPE_PRICE_HARVEST_REACH"
|
|
printf "STRIPE_PRICE_WHOLESALE_PORTAL=%s\n" "$STRIPE_PRICE_WHOLESALE_PORTAL"
|
|
printf "STRIPE_PRICE_WATER_LOG=%s\n" "$STRIPE_PRICE_WATER_LOG"
|
|
printf "STRIPE_PRICE_AI_TOOLS=%s\n" "$STRIPE_PRICE_AI_TOOLS"
|
|
printf "STRIPE_PRICE_SQUARE_SYNC=%s\n" "$STRIPE_PRICE_SQUARE_SYNC"
|
|
printf "STRIPE_PRICE_SMS_CAMPAIGNS=%s\n" "$STRIPE_PRICE_SMS_CAMPAIGNS"
|
|
printf "RESEND_API_KEY=%s\n" "$RESEND_API_KEY"
|
|
printf "FROM_EMAIL=%s\n" "$FROM_EMAIL"
|
|
printf "MINIO_ENDPOINT=%s\n" "$MINIO_ENDPOINT"
|
|
printf "MINIO_REGION=%s\n" "$MINIO_REGION"
|
|
printf "MINIO_ACCESS_KEY=%s\n" "$MINIO_ACCESS_KEY"
|
|
printf "MINIO_SECRET_KEY=%s\n" "$MINIO_SECRET_KEY"
|
|
printf "MINIO_PUBLIC_URL=%s\n" "$MINIO_PUBLIC_URL"
|
|
printf "MINIO_BUCKET_PRODUCTS=%s\n" "$MINIO_BUCKET_PRODUCTS"
|
|
printf "MINIO_BUCKET_BRAND_LOGOS=%s\n" "$MINIO_BUCKET_BRAND_LOGOS"
|
|
printf "MINIO_BUCKET_WATER_LOGS=%s\n" "$MINIO_BUCKET_WATER_LOGS"
|
|
printf "MINIMAX_API_KEY=%s\n" "$MINIMAX_API_KEY"
|
|
printf "MINIMAX_BASE_URL=%s\n" "$MINIMAX_BASE_URL"
|
|
printf "CRON_SECRET=%s\n" "$CRON_SECRET"
|
|
} > $APP_DIR/.env.production
|
|
|
|
# Sync build output and required files
|
|
rsync -a --delete .next/ $APP_DIR/.next/
|
|
rsync -a --delete public/ $APP_DIR/public/
|
|
cp package.json $APP_DIR/
|
|
cp next.config.ts $APP_DIR/ 2>/dev/null || true
|
|
|
|
# Install production deps only
|
|
cd $APP_DIR
|
|
npm install --omit=dev
|
|
|
|
# Start or restart PM2
|
|
if pm2 describe route-commerce > /dev/null 2>&1; then
|
|
pm2 restart route-commerce
|
|
else
|
|
pm2 start npm --name route-commerce -- start -- -p 3100
|
|
pm2 save
|
|
fi
|
|
|
|
echo "Deployed successfully"
|