# 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

1. Google Cloud Project with billing enabled
2. Cloud Build API enabled
3. Cloud Run API enabled
4. Secret Manager API enabled
5. 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

1. Go to Cloud Build > Triggers
2. Select your trigger (or create a new one)
3. Scroll to "Substitution variables"
4. 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

```bash
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

```bash
# 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

```bash
# 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

```yaml
_NODE_ENV: production
_CORS_ORIGIN: https://app.xtablo.com
_XTABLO_URL: https://app.xtablo.com
```

### Staging Trigger

```yaml
_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:

1. **Test the trigger manually:**
   ```bash
   gcloud builds triggers run xtablo-api-production --branch=main
   ```

2. **Check the build logs:**
   ```bash
   gcloud builds list --limit=5
   gcloud builds log BUILD_ID
   ```

3. **Verify the deployed service:**
   ```bash
   gcloud run services describe xtablo-api --region=europe-west1
   ```

4. **Check environment variables:**
   ```bash
   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 `$_VARIABLE` names 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.secretAccessor` for each secret
- Verify secrets exist: `gcloud secrets list`

## Additional Configuration

### Service Account Permissions

Your Cloud Run service needs these roles:

```bash
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:

```yaml
- '--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:

```bash
# 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:
- [Cloud Build Documentation](https://cloud.google.com/build/docs)
- [Cloud Run Documentation](https://cloud.google.com/run/docs)
- [Secret Manager Documentation](https://cloud.google.com/secret-manager/docs)

