7.8 KiB
7.8 KiB
Google Cloud Build Setup Guide
Overview
This guide explains how to configure Google Cloud Build for automatic deployment of the XTablo API to Cloud Run.
Prerequisites
- Google Cloud Project with billing enabled
- Cloud Build API enabled
- Cloud Run API enabled
- Secret Manager API enabled
- Artifact Registry repository created
Required Substitution Variables
The cloudbuild.yaml uses substitution variables that must be configured in your Cloud Build trigger. Here's what each variable is for:
Build Configuration Variables
| Variable | Description | Example |
|---|---|---|
$_NODE_ENV |
Environment (staging/production) | production |
$_AR_PROJECT_ID |
Artifact Registry project ID | your-project-id |
$_AR_REPOSITORY |
Artifact Registry repository name | xtablo |
$_SERVICE_NAME |
Cloud Run service name | xtablo-api |
Application Environment Variables
| Variable | Description | Example |
|---|---|---|
$_SUPABASE_URL |
Supabase project URL | https://xxx.supabase.co |
$_STREAM_CHAT_API_KEY |
Stream Chat API key | your-stream-api-key |
$_EMAIL_USER |
Email sender address | noreply@xtablo.com |
$_EMAIL_CLIENT_ID |
OAuth2 client ID for email | your-client-id |
$_R2_ACCOUNT_ID |
Cloudflare R2 account ID | your-r2-account-id |
$_CORS_ORIGIN |
CORS allowed origin | https://app.xtablo.com |
$_XTABLO_URL |
Frontend application URL | https://app.xtablo.com |
Setting Up Substitution Variables
Option 1: Via Google Cloud Console
- Go to Cloud Build > Triggers
- Select your trigger (or create a new one)
- Scroll to "Substitution variables"
- Add each variable with its value:
_NODE_ENV = production _AR_PROJECT_ID = your-project-id _AR_REPOSITORY = xtablo _SERVICE_NAME = xtablo-api _SUPABASE_URL = https://your-project.supabase.co _STREAM_CHAT_API_KEY = your-key _EMAIL_USER = noreply@xtablo.com _EMAIL_CLIENT_ID = your-client-id _R2_ACCOUNT_ID = your-account-id _CORS_ORIGIN = https://app.xtablo.com _XTABLO_URL = https://app.xtablo.com
Option 2: Via gcloud CLI
gcloud builds triggers create github \
--name="xtablo-api-production" \
--repo-name="xtablo-source" \
--repo-owner="your-github-org" \
--branch-pattern="^main$" \
--build-config="apps/api/cloudbuild.yaml" \
--substitutions='
_NODE_ENV=production,
_AR_PROJECT_ID=your-project-id,
_AR_REPOSITORY=xtablo,
_SERVICE_NAME=xtablo-api,
_SUPABASE_URL=https://your-project.supabase.co,
_STREAM_CHAT_API_KEY=your-key,
_EMAIL_USER=noreply@xtablo.com,
_EMAIL_CLIENT_ID=your-client-id,
_R2_ACCOUNT_ID=your-account-id,
_CORS_ORIGIN=https://app.xtablo.com,
_XTABLO_URL=https://app.xtablo.com
'
Setting Up Secrets in Secret Manager
The sensitive values (API keys, tokens, etc.) are stored in Google Cloud Secret Manager. Create these secrets:
Required Secrets
# Supabase secrets
echo -n "your-service-role-key" | gcloud secrets create supabase-service-role-key --data-file=-
echo -n "your-connection-string" | gcloud secrets create supabase-connection-string --data-file=-
echo -n "your-ca-cert" | gcloud secrets create supabase-ca-cert --data-file=-
# Stream Chat secret
echo -n "your-stream-secret" | gcloud secrets create stream-chat-api-secret --data-file=-
# Stripe secrets
echo -n "your-stripe-key" | gcloud secrets create stripe-secret-key --data-file=-
echo -n "your-webhook-secret" | gcloud secrets create stripe-webhook-secret --data-file=-
# Email secrets
echo -n "your-client-secret" | gcloud secrets create email-client-secret --data-file=-
echo -n "your-refresh-token" | gcloud secrets create email-refresh-token --data-file=-
# R2 (Cloudflare) secrets
echo -n "your-access-key-id" | gcloud secrets create r2-access-key-id --data-file=-
echo -n "your-secret-access-key" | gcloud secrets create r2-secret-access-key --data-file=-
Grant Cloud Run Access to Secrets
# Get your Cloud Run service account
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT="${PROJECT_ID}@appspot.gserviceaccount.com"
# Grant access to each secret
for secret in \
supabase-service-role-key \
supabase-connection-string \
supabase-ca-cert \
stream-chat-api-secret \
stripe-secret-key \
stripe-webhook-secret \
email-client-secret \
email-refresh-token \
r2-access-key-id \
r2-secret-access-key
do
gcloud secrets add-iam-policy-binding $secret \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/secretmanager.secretAccessor"
done
Environment-Specific Configurations
Production Trigger
_NODE_ENV: production
_CORS_ORIGIN: https://app.xtablo.com
_XTABLO_URL: https://app.xtablo.com
Staging Trigger
_NODE_ENV: staging
_CORS_ORIGIN: https://staging.xtablo.com
_XTABLO_URL: https://staging.xtablo.com
_SERVICE_NAME: xtablo-api-staging
Verifying the Setup
After creating your trigger and setting up the secrets:
-
Test the trigger manually:
gcloud builds triggers run xtablo-api-production --branch=main -
Check the build logs:
gcloud builds list --limit=5 gcloud builds log BUILD_ID -
Verify the deployed service:
gcloud run services describe xtablo-api --region=europe-west1 -
Check environment variables:
gcloud run services describe xtablo-api --region=europe-west1 --format="value(spec.template.spec.containers[0].env)"
Troubleshooting
Build Fails with "Missing Substitution Variable"
- Ensure all
$_VARIABLEnames are defined in your trigger - Check for typos in variable names
Cloud Run Deployment Fails
- Verify the service account has necessary permissions
- Check that the Artifact Registry URL is correct
- Ensure the image was successfully pushed
Application Fails to Start
- Check Cloud Run logs:
gcloud run logs read --service=xtablo-api --region=europe-west1 - Verify all secrets are accessible to the service account
- Check that environment variables are properly set
Secret Access Denied
- Ensure the Cloud Run service account has
roles/secretmanager.secretAccessorfor each secret - Verify secrets exist:
gcloud secrets list
Additional Configuration
Service Account Permissions
Your Cloud Run service needs these roles:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/secretmanager.secretAccessor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/cloudsql.client" # If using Cloud SQL
Cloud Run Configuration Options
You can add these to your cloudbuild.yaml deploy step:
- '--memory'
- '512Mi'
- '--cpu'
- '1'
- '--max-instances'
- '10'
- '--min-instances'
- '0'
- '--concurrency'
- '80'
- '--timeout'
- '300'
- '--allow-unauthenticated' # If your API is public
Manual Deployment
If you need to deploy manually without Cloud Build:
# Build the image
docker build -f apps/api/Dockerfile --target production -t xtablo-api:latest .
# Tag for Artifact Registry
docker tag xtablo-api:latest europe-west1-docker.pkg.dev/PROJECT_ID/xtablo/xtablo-api:latest
# Push to Artifact Registry
docker push europe-west1-docker.pkg.dev/PROJECT_ID/xtablo/xtablo-api:latest
# Deploy to Cloud Run
gcloud run deploy xtablo-api \
--image=europe-west1-docker.pkg.dev/PROJECT_ID/xtablo/xtablo-api:latest \
--region=europe-west1 \
--set-env-vars="NODE_ENV=production,PORT=8080,..." \
--update-secrets="SUPABASE_SERVICE_ROLE_KEY=supabase-service-role-key:latest,..."
Support
For more information: