#!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────────────── # PCLC Cloud → Google Cloud Run deploy (run in Google Cloud Shell). # # Prereqs (one-time): a GCP project with billing enabled. # Run from the REPO ROOT (the folder that contains BOTH cloud/ and finetune_user.py), # because the Docker build context needs the repo-root training files. # # bash cloud/deploy_cloudrun.sh # # Re-running redeploys a new revision (idempotent). Models/manifests live in GCS, # so they survive redeploys and scale-to-zero. # ───────────────────────────────────────────────────────────────────────────── set -euo pipefail # ── EDIT THESE ─────────────────────────────────────────────────────────────── PROJECT_ID="${PROJECT_ID:-$(gcloud config get-value project 2>/dev/null)}" REGION="${REGION:-europe-west2}" # London; pick one near you SERVICE="pclc-cloud" BUCKET="${BUCKET:-${PROJECT_ID}-pclc-models}" API_KEY="${API_KEY:?set API_KEY to a long random string, e.g. export API_KEY=$(openssl rand -hex 24)}" # ───────────────────────────────────────────────────────────────────────────── echo ">> Project: $PROJECT_ID Region: $REGION Bucket: gs://$BUCKET" # 1. Enable the APIs we use gcloud services enable run.googleapis.com artifactregistry.googleapis.com \ cloudbuild.googleapis.com storage.googleapis.com secretmanager.googleapis.com \ --project "$PROJECT_ID" # 2. GCS bucket for models + manifests (idempotent: ignore "already exists") gcloud storage buckets create "gs://$BUCKET" --project "$PROJECT_ID" \ --location "$REGION" --uniform-bucket-level-access 2>/dev/null || true # 3. Signing key → Secret Manager (generate once; reused on redeploys) if ! gcloud secrets describe pclc-signing-key --project "$PROJECT_ID" >/dev/null 2>&1; then echo ">> Generating EC P-256 signing key and storing as secret 'pclc-signing-key'" python - <<'PY' > /tmp/pclc_signing_key.pem from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec k = ec.generate_private_key(ec.SECP256R1()) print(k.private_bytes(serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()).decode(), end="") PY gcloud secrets create pclc-signing-key --project "$PROJECT_ID" \ --data-file=/tmp/pclc_signing_key.pem rm -f /tmp/pclc_signing_key.pem else echo ">> Reusing existing secret 'pclc-signing-key'" fi # 4. Build the image with Cloud Build (no local Docker needed) IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/pclc/${SERVICE}:$(date +%Y%m%d-%H%M%S)" gcloud artifacts repositories create pclc --repository-format=docker \ --location "$REGION" --project "$PROJECT_ID" 2>/dev/null || true echo ">> Building image: $IMAGE (context = repo root, Dockerfile = cloud/Dockerfile)" gcloud builds submit --project "$PROJECT_ID" --region "$REGION" \ --tag "$IMAGE" --config /dev/stdin <