176 lines
8.4 KiB
YAML
176 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 }}
|
|
SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }}
|
|
run: |
|
|
set -e
|
|
APP_DIR=/home/tyler/route-commerce
|
|
|
|
# Setup SSH key
|
|
mkdir -p ~/.ssh
|
|
echo "$SERVER_SSH_KEY" > ~/.ssh/id_ed25519
|
|
chmod 600 ~/.ssh/id_ed25519
|
|
ssh-keyscan -H route.crispygoat.com >> ~/.ssh/known_hosts 2>/dev/null || true
|
|
|
|
# Test SSH connection
|
|
echo "Testing SSH connection..."
|
|
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no tyler@route.crispygoat.com "echo 'SSH OK' && hostname" || { echo "SSH FAILED"; exit 1; }
|
|
|
|
# Write production env file on server
|
|
ssh tyler@route.crispygoat.com "mkdir -p $APP_DIR && cat > $APP_DIR/.env.production" << 'ENVEOF'
|
|
DATABASE_URL=$DATABASE_URL
|
|
NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
|
|
NEON_AUTH_BASE_URL=$NEON_AUTH_BASE_URL
|
|
NEON_AUTH_COOKIE_SECRET=$NEON_AUTH_COOKIE_SECRET
|
|
AUTH_SECRET=$AUTH_SECRET
|
|
AUTH_URL=$AUTH_URL
|
|
NEXT_PUBLIC_AUTH_URL=$NEXT_PUBLIC_AUTH_URL
|
|
GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID
|
|
GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET
|
|
ALLOW_DEV_LOGIN=$ALLOW_DEV_LOGIN
|
|
ADMIN_ALLOWED_EMAILS=$ADMIN_ALLOWED_EMAILS
|
|
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
|
|
STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY
|
|
STRIPE_WEBHOOK_SECRET=$STRIPE_WEBHOOK_SECRET
|
|
STRIPE_PRICE_STARTER=$STRIPE_PRICE_STARTER
|
|
STRIPE_PRICE_FARM=$STRIPE_PRICE_FARM
|
|
STRIPE_PRICE_ENTERPRISE=$STRIPE_PRICE_ENTERPRISE
|
|
STRIPE_PRICE_HARVEST_REACH=$STRIPE_PRICE_HARVEST_REACH
|
|
STRIPE_PRICE_WHOLESALE_PORTAL=$STRIPE_PRICE_WHOLESALE_PORTAL
|
|
STRIPE_PRICE_WATER_LOG=$STRIPE_PRICE_WATER_LOG
|
|
STRIPE_PRICE_AI_TOOLS=$STRIPE_PRICE_AI_TOOLS
|
|
STRIPE_PRICE_SQUARE_SYNC=$STRIPE_PRICE_SQUARE_SYNC
|
|
STRIPE_PRICE_SMS_CAMPAIGNS=$STRIPE_PRICE_SMS_CAMPAIGNS
|
|
RESEND_API_KEY=$RESEND_API_KEY
|
|
FROM_EMAIL=$FROM_EMAIL
|
|
MINIO_ENDPOINT=$MINIO_ENDPOINT
|
|
MINIO_REGION=$MINIO_REGION
|
|
MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY
|
|
MINIO_SECRET_KEY=$MINIO_SECRET_KEY
|
|
MINIO_PUBLIC_URL=$MINIO_PUBLIC_URL
|
|
MINIO_BUCKET_PRODUCTS=$MINIO_BUCKET_PRODUCTS
|
|
MINIO_BUCKET_BRAND_LOGOS=$MINIO_BUCKET_BRAND_LOGOS
|
|
MINIO_BUCKET_WATER_LOGS=$MINIO_BUCKET_WATER_LOGS
|
|
MINIMAX_API_KEY=$MINIMAX_API_KEY
|
|
MINIMAX_BASE_URL=$MINIMAX_BASE_URL
|
|
CRON_SECRET=$CRON_SECRET
|
|
ENVEOF
|
|
|
|
# Sync build output to server using scp (no apt install needed)
|
|
echo "Copying .next/..."
|
|
scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no -r .next/* tyler@route.crispygoat.com:$APP_DIR/.next/
|
|
echo "Copying public/..."
|
|
scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no -r public/* tyler@route.crispygoat.com:$APP_DIR/public/
|
|
echo "Copying package.json..."
|
|
scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no package.json tyler@route.crispygoat.com:$APP_DIR/
|
|
scp -o ConnectTimeout=15 -o StrictHostKeyChecking=no next.config.ts tyler@route.crispygoat.com:$APP_DIR/ 2>/dev/null || true
|
|
|
|
# Install deps and restart on server
|
|
echo "Installing deps and restarting PM2..."
|
|
ssh -o ConnectTimeout=15 -o StrictHostKeyChecking=no tyler@route.crispygoat.com "cd $APP_DIR && npm install --omit=dev && pm2 restart route-commerce || pm2 start npm --name route-commerce -- start -- -p 3100 && pm2 save"
|
|
|
|
echo "Deployed successfully"
|