134 lines
4.9 KiB
Bash
134 lines
4.9 KiB
Bash
#!/bin/bash
|
|
# 05-cloudrun-deploy.sh — Deploy OSVauco agent to Cloud Run via Docker + gcloud
|
|
# Run in: Cloud Shell or local terminal
|
|
# Requires: gcloud CLI (no ADK CLI needed)
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
ENV_FILE="${SCRIPT_DIR}/../.env"
|
|
if [ -f "${ENV_FILE}" ]; then
|
|
set -a; source "${ENV_FILE}"; set +a
|
|
fi
|
|
|
|
: "${PROJECT_ID:?Set PROJECT_ID in .env}"
|
|
: "${REGION:?Set REGION in .env}"
|
|
: "${CLOUD_RUN_SERVICE:?Set CLOUD_RUN_SERVICE in .env}"
|
|
: "${AGENT_SA:?Set AGENT_SA in .env}"
|
|
|
|
# ── Region Guard ────────────────────────────────────────────────────────
|
|
source "$(dirname "$0")/99-region-guard.sh"
|
|
DEPLOY_REGION="${DEPLOY_REGION:-${REGION}}"
|
|
log_region_context "Cloud-Run" "$DEPLOY_REGION" "SELECTED"
|
|
|
|
REPO="${DEPLOY_REGION}-docker.pkg.dev/${PROJECT_ID}/osvauco-repo"
|
|
IMAGE="${REPO}/osvauco-agent:latest"
|
|
AGENT_PATH="${SCRIPT_DIR}/../agents/core-logic"
|
|
AGENT_SA_NAME=$(echo "${AGENT_SA}" | cut -d@ -f1)
|
|
|
|
echo "=== 05: Cloud Run Deploy to ${DEPLOY_REGION} ==="
|
|
|
|
bash "${SCRIPT_DIR}/00-authcheck.sh"
|
|
|
|
# Enable required APIs
|
|
gcloud services enable \
|
|
run.googleapis.com \
|
|
artifactregistry.googleapis.com \
|
|
cloudbuild.googleapis.com \
|
|
iam.googleapis.com \
|
|
--project="${PROJECT_ID}" --quiet
|
|
|
|
# Create agent service account if it doesn't exist (idempotent)
|
|
if ! gcloud iam service-accounts describe "${AGENT_SA}" \
|
|
--project="${PROJECT_ID}" &>/dev/null; then
|
|
gcloud iam service-accounts create "${AGENT_SA_NAME}" \
|
|
--display-name="OSVauco Agent SA" \
|
|
--project="${PROJECT_ID}"
|
|
echo "✓ Service account created: ${AGENT_SA}"
|
|
else
|
|
echo "✓ Service account already exists: ${AGENT_SA}"
|
|
fi
|
|
|
|
# Grant the SA roles it needs at runtime
|
|
for ROLE in \
|
|
roles/aiplatform.user \
|
|
roles/secretmanager.secretAccessor \
|
|
roles/logging.logWriter \
|
|
roles/cloudtrace.agent \
|
|
roles/monitoring.metricWriter; do
|
|
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
|
|
--member="serviceAccount:${AGENT_SA}" \
|
|
--role="${ROLE}" --quiet
|
|
done
|
|
echo "✓ Runtime roles granted to ${AGENT_SA}"
|
|
|
|
# Grant caller iam.serviceAccountUser on the SA (needed for --service-account flag)
|
|
CALLER=$(gcloud config get-value account 2>/dev/null)
|
|
gcloud iam service-accounts add-iam-policy-binding "${AGENT_SA}" \
|
|
--member="user:${CALLER}" \
|
|
--role="roles/iam.serviceAccountUser" \
|
|
--project="${PROJECT_ID}" --quiet
|
|
echo "✓ iam.serviceAccountUser granted to ${CALLER}"
|
|
|
|
# Create Artifact Registry repo if it doesn't exist
|
|
gcloud artifacts repositories describe osvauco-repo \
|
|
--location="${DEPLOY_REGION}" --project="${PROJECT_ID}" &>/dev/null || \
|
|
gcloud artifacts repositories create osvauco-repo \
|
|
--repository-format=docker \
|
|
--location="${DEPLOY_REGION}" \
|
|
--project="${PROJECT_ID}" --quiet
|
|
echo "✓ Artifact Registry repo ready"
|
|
|
|
# IAM for Cloud Build compute SA
|
|
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
|
|
COMPUTE_SA="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
|
|
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
|
|
--member="serviceAccount:${COMPUTE_SA}" \
|
|
--role="roles/cloudbuild.builds.builder" --quiet
|
|
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
|
|
--member="serviceAccount:${COMPUTE_SA}" \
|
|
--role="roles/secretmanager.secretAccessor" --quiet
|
|
echo "✓ Cloud Build IAM bindings applied"
|
|
|
|
# Configure Docker for Artifact Registry
|
|
gcloud auth configure-docker "${DEPLOY_REGION}-docker.pkg.dev" --quiet
|
|
|
|
# Build image via Cloud Build
|
|
echo "Building image via Cloud Build..."
|
|
gcloud builds submit "${AGENT_PATH}" \
|
|
--tag="${IMAGE}" \
|
|
--project="${PROJECT_ID}" \
|
|
--region="${DEPLOY_REGION}"
|
|
echo "✓ Image built: ${IMAGE}"
|
|
|
|
# Deploy to Cloud Run
|
|
echo "Deploying to Cloud Run..."
|
|
gcloud run deploy "${CLOUD_RUN_SERVICE}" \
|
|
--image="${IMAGE}" \
|
|
--region="${DEPLOY_REGION}" \
|
|
--project="${PROJECT_ID}" \
|
|
--service-account="${AGENT_SA}" \
|
|
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_CLOUD_LOCATION=${DEPLOY_REGION},GOOGLE_GENAI_USE_VERTEXAI=True,VERTEX_MODEL=gemini-2.5-pro" \
|
|
--no-allow-unauthenticated \
|
|
--port=8080 \
|
|
--memory=1Gi \
|
|
--cpu=1 \
|
|
--min-instances=0 \
|
|
--max-instances=3 \
|
|
--quiet
|
|
|
|
echo ""
|
|
echo "=== 05: Cloud Run Deploy COMPLETE ==="
|
|
SERVICE_URL=$(gcloud run services describe "${CLOUD_RUN_SERVICE}" \
|
|
--region="${DEPLOY_REGION}" --project="${PROJECT_ID}" \
|
|
--format="value(status.url)" 2>/dev/null || echo "(pending)")
|
|
echo " Service URL: ${SERVICE_URL}"
|
|
echo ""
|
|
echo " To call (authenticated):"
|
|
echo " TOKEN=\$(gcloud auth print-identity-token)"
|
|
echo " curl -H \"Authorization: Bearer \$TOKEN\" -H 'Content-Type: application/json' \\"
|
|
echo " -d '{\"message\": \"Hello\"}' \${SERVICE_URL}/run"
|
|
echo ""
|
|
echo " COST NOTE: Cloud Run scales to 0. No idle cost."
|
|
echo " Delete with: gcloud run services delete ${CLOUD_RUN_SERVICE} --region=${DEPLOY_REGION} --quiet"
|