-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy.sh
More file actions
executable file
·135 lines (117 loc) · 5.85 KB
/
Copy pathdeploy.sh
File metadata and controls
executable file
·135 lines (117 loc) · 5.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env bash
#
# ProposalOS — Local deploy to GCP Cloud Run
# Builds Docker image, pushes to Artifact Registry, deploys to Cloud Run.
#
# Prerequisites:
# - gcloud CLI installed and authenticated (gcloud auth login)
# - Docker running
# - Artifact Registry API enabled
# - Cloud Run API enabled
#
# Usage:
# ./deploy.sh # Uses REGION and PROJECT_ID from env or below
# REGION=europe-west1 ./deploy.sh
#
set -e
# =============================================================================
# CONFIGURATION — Fill in or set via environment variables
# =============================================================================
REGION="${REGION:-us-central1}" # GCP region (e.g. us-central1, europe-west1)
PROJECT_ID="${PROJECT_ID:-}" # GCP project ID (required)
IMAGE_NAME="proposal-engine/app"
SERVICE_NAME="proposal-engine"
# Cloud SQL (required for production)
# Set DATABASE_URL to Cloud SQL connection string. Format:
# postgresql://USER:PASSWORD@/DB_NAME?host=/cloudsql/PROJECT:REGION:INSTANCE
CLOUD_SQL_INSTANCE="${CLOUD_SQL_INSTANCE:-${PROJECT_ID}:${REGION}:proposal-db}"
DATABASE_URL="${DATABASE_URL:-}" # Must be set for Cloud SQL (e.g. from .env.production or Secret Manager)
# =============================================================================
# Step 1: Validate configuration
# =============================================================================
if [ -z "$PROJECT_ID" ]; then
echo "❌ Error: PROJECT_ID is required."
echo " Set it: export PROJECT_ID=your-gcp-project-id"
echo " Or pass: PROJECT_ID=myproject ./deploy.sh"
exit 1
fi
if [ -z "$DATABASE_URL" ]; then
echo "⚠️ Warning: DATABASE_URL not set. Using DATABASE_URL from Secret Manager."
echo " Ensure DATABASE_URL secret exists: gcloud secrets describe DATABASE_URL --project=${PROJECT_ID}"
USE_DATABASE_SECRET=1
else
USE_DATABASE_SECRET=0
fi
# Get commit SHA for tagging (or use 'latest' if not in a git repo)
COMMIT_SHA="$(git rev-parse --short HEAD 2>/dev/null || echo 'latest')"
FULL_IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/${IMAGE_NAME}:${COMMIT_SHA}"
echo "📦 Deploying ProposalOS to Cloud Run"
echo " Project: ${PROJECT_ID}"
echo " Region: ${REGION}"
echo " Image: ${FULL_IMAGE}"
echo ""
# =============================================================================
# Step 2: Configure Docker for Artifact Registry
# =============================================================================
echo "🔐 Configuring Docker for Artifact Registry..."
gcloud auth configure-docker "${REGION}-docker.pkg.dev" --quiet
# =============================================================================
# Step 3: Build the Docker image
# =============================================================================
echo ""
echo "🏗️ Building Docker image (linux/amd64 for Cloud Run)..."
docker build --platform linux/amd64 -t "${FULL_IMAGE}" .
# =============================================================================
# Step 4: Push to Artifact Registry
# =============================================================================
echo ""
echo "📤 Pushing image to Artifact Registry..."
docker push "${FULL_IMAGE}"
# =============================================================================
# Step 5: Deploy to Cloud Run
# =============================================================================
# Add --set-secrets and --set-env-vars for production. Example:
# --set-secrets="DATABASE_URL=DATABASE_URL:latest,API_KEY=API_KEY:latest,..."
# --set-env-vars="GCP_PROJECT_ID=${PROJECT_ID},GCP_REGION=${REGION},..."
# --add-cloudsql-instances=PROJECT:REGION:INSTANCE # if using Cloud SQL
echo ""
echo "🚀 Deploying to Cloud Run..."
# App URL for emails, redirects (Cloud Run URL)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format='value(projectNumber)' 2>/dev/null || echo "")
APP_URL="https://${SERVICE_NAME}-${PROJECT_NUMBER}.${REGION}.run.app"
if [ -z "$PROJECT_NUMBER" ]; then
APP_URL="https://${SERVICE_NAME}.run.app"
fi
# Env vars (non-secret). DATABASE_URL from Secret Manager when using Cloud SQL or when unset.
ENV_VARS="GCP_PROJECT_ID=${PROJECT_ID},GCP_REGION=${REGION},BASE_URL=${APP_URL},NEXT_PUBLIC_APP_URL=${APP_URL},NEXTAUTH_URL=${APP_URL},NEXT_PUBLIC_BASE_URL=${APP_URL}"
if [ -n "$DATABASE_URL" ] && [[ "${DATABASE_URL}" != *"/cloudsql/"* ]]; then
ENV_VARS="${ENV_VARS},DATABASE_URL=${DATABASE_URL}"
fi
# Secrets from Secret Manager (run ./scripts/sync-secrets-to-gcp.sh first)
SECRETS="API_KEY=API_KEY:latest,GOOGLE_PAGESPEED_API_KEY=GOOGLE_PAGESPEED_API_KEY:latest,GOOGLE_PLACES_API_KEY=GOOGLE_PLACES_API_KEY:latest,SERP_API_KEY=SERP_API_KEY:latest,GOOGLE_AI_API_KEY=GOOGLE_AI_API_KEY:latest,RESEND_API_KEY=RESEND_API_KEY:latest"
if [ -n "$USE_DATABASE_SECRET" ] && [ "$USE_DATABASE_SECRET" = "1" ] || [[ "${DATABASE_URL:-}" == *"/cloudsql/"* ]]; then
SECRETS="${SECRETS},DATABASE_URL=DATABASE_URL:latest"
fi
DEPLOY_ARGS=(
--image "${FULL_IMAGE}"
--project "${PROJECT_ID}"
--region "${REGION}"
--platform managed
--allow-unauthenticated
--memory 1Gi
--cpu 1
--min-instances 0
--max-instances 5
--port 8080
--set-env-vars="${ENV_VARS}"
--set-secrets="${SECRETS}"
)
# Add Cloud SQL connection when DATABASE_URL uses /cloudsql/ socket or when using secret
if [[ "${DATABASE_URL:-}" == *"/cloudsql/"* ]] || [ "${USE_DATABASE_SECRET:-0}" = "1" ]; then
echo " Using Cloud SQL: ${CLOUD_SQL_INSTANCE}"
DEPLOY_ARGS+=(--add-cloudsql-instances="${CLOUD_SQL_INSTANCE}")
fi
gcloud run deploy "${SERVICE_NAME}" "${DEPLOY_ARGS[@]}"
echo ""
echo "✅ Deploy complete!"
echo " Service URL: $(gcloud run services describe ${SERVICE_NAME} --project ${PROJECT_ID} --region ${REGION} --format 'value(status.url)' 2>/dev/null || echo 'Run: gcloud run services describe proposal-engine --project '"${PROJECT_ID}"' --region '"${REGION}"' --format \"value(status.url)\"')"