pclc-cloud / cloud /deploy_cloudrun.sh
HafsaZainab6's picture
Claude Opus 4.8
PCLC cloud: FastAPI train+sign+OTA service, Cloud Run deploy assets
9e7c196
Raw History Blame Contribute Delete
5.19 kB
#!/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 <<EOF || gcloud builds submit \
--project "$PROJECT_ID" --tag "$IMAGE" --file cloud/Dockerfile .
steps:
- name: gcr.io/cloud-builders/docker
args: ['build','-f','cloud/Dockerfile','-t','$IMAGE','.']
images: ['$IMAGE']
EOF
# 5. Deploy to Cloud Run (scale-to-zero; train can take a while β†’ 600s timeout, 2Gi RAM)
gcloud run deploy "$SERVICE" --project "$PROJECT_ID" --region "$REGION" \
--image "$IMAGE" \
--allow-unauthenticated \
--memory 2Gi --cpu 2 --timeout 600 \
--min-instances 0 --max-instances 3 \
--set-env-vars "STORAGE=gcs,PCLC_GCS_BUCKET=${BUCKET},PCLC_TRAIN_PYTHON=python,PCLC_MIN_ROWS=10,PCLC_EPOCHS=200,TF_CPP_MIN_LOG_LEVEL=2,TF_ENABLE_ONEDNN_OPTS=0" \
--set-secrets "PCLC_SIGNING_KEY_PEM=pclc-signing-key:latest" \
--update-env-vars "PCLC_API_KEY=${API_KEY}"
URL=$(gcloud run services describe "$SERVICE" --project "$PROJECT_ID" --region "$REGION" --format='value(status.url)')
echo ""
echo "════════════════════════════════════════════════════════════════"
echo " DEPLOYED: $URL"
echo ""
echo " 1) Health: curl $URL/healthz"
echo " 2) Pubkey: curl $URL/pubkey # paste into PclcConfig.MODEL_PUBLIC_KEY_B64"
echo " 3) App config (PclcConfig.kt):"
echo " BASE_URL = \"$URL/pclc/\""
echo " API_KEY = \"$API_KEY\""
echo " 4) Rebuild the app, install, done."
echo "════════════════════════════════════════════════════════════════"