cefense/deploy.sh
2026-08-18 19:38:47 +05:30

107 lines
4.2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Build and deploy Cerebrus services (backend, frontend) and the scanner Cloud Run
# job to Cloud Run via Cloud Build.
#
# The backend config is baked into its image from apps/backend/.env.production.
# The frontend runtime proxy reads BACKEND_URL from apps/frontend/.env.production,
# which this script sets automatically on the Cloud Run service.
#
# ./deploy.sh <PROJECT_ID>
#
# Optional env overrides: REGION (default us-central1), AR_REPO (default cerebrus),
# DEPLOY_SCANNER (default 1).
set -euo pipefail
PROJECT_ID="${1:-}"
REGION="${REGION:-us-central1}"
AR_REPO="${AR_REPO:-cerebrus}"
DEPLOY_SCANNER="${DEPLOY_SCANNER:-1}"
if [[ -z "$PROJECT_ID" ]]; then
echo "Usage: ./deploy.sh <PROJECT_ID> (REGION / AR_REPO / DEPLOY_SCANNER overridable via env)" >&2
exit 1
fi
if [[ ! -f "apps/backend/.env.production" ]]; then
echo "ERROR: apps/backend/.env.production is missing — the backend image bakes it in." >&2
exit 1
fi
if [[ ! -f "apps/frontend/.env.production" ]]; then
echo "ERROR: apps/frontend/.env.production is missing." >&2
exit 1
fi
# Read a key=value line from a .env file, stripping optional surrounding quotes.
read_env() {
local file="$1" key="$2"
local value
value="$(grep "^${key}=" "$file" 2>/dev/null | head -n1 | cut -d= -f2- | sed -E "s/^['\"]//;s/['\"]$//")" || true
printf '%s' "$value"
}
FRONTEND_BACKEND_URL="$(read_env apps/frontend/.env.production BACKEND_URL)"
if [[ -z "$FRONTEND_BACKEND_URL" ]]; then
echo "ERROR: BACKEND_URL is not set in apps/frontend/.env.production" >&2
exit 1
fi
# Sanity-check the backend env that trips people up.
NODE_ENV="$(read_env apps/backend/.env.production NODE_ENV)"
if [[ "$NODE_ENV" != "production" ]]; then
echo "WARNING: NODE_ENV in apps/backend/.env.production is '${NODE_ENV:-(unset)}', expected 'production'." >&2
fi
SCAN_CALLBACK_URL="$(read_env apps/backend/.env.production SCAN_CALLBACK_URL)"
if [[ -n "$SCAN_CALLBACK_URL" && "$SCAN_CALLBACK_URL" == *"cerebrus-frontend"* ]]; then
echo "WARNING: SCAN_CALLBACK_URL points to the frontend ($SCAN_CALLBACK_URL)." >&2
echo " It must point to the backend URL or scanner /internal callbacks will fail." >&2
fi
echo "==> Project: $PROJECT_ID Region: $REGION Repo: $AR_REPO"
gcloud config set project "$PROJECT_ID" >/dev/null
echo "==> Enabling required APIs"
gcloud services enable run.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com
echo "==> Ensuring Artifact Registry repo '$AR_REPO'"
gcloud artifacts repositories describe "$AR_REPO" --location="$REGION" >/dev/null 2>&1 || \
gcloud artifacts repositories create "$AR_REPO" \
--repository-format=docker --location="$REGION" --description="Cerebrus images"
echo "==> Granting Cloud Build permission to deploy to Cloud Run"
PROJECT_NUMBER="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')"
CB_SA="${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${CB_SA}" --role="roles/run.admin" --condition=None >/dev/null
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${CB_SA}" --role="roles/iam.serviceAccountUser" --condition=None >/dev/null
# Build + push + deploy backend and frontend.
for app in backend frontend; do
IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO}/${app}"
echo "==> Building & deploying cerebrus-${app} (${IMAGE})"
SUBS="_REGION=${REGION},_IMAGE=${IMAGE}"
if [[ "$app" == "frontend" ]]; then
SUBS="${SUBS},_BACKEND_URL=${FRONTEND_BACKEND_URL}"
fi
gcloud builds submit \
--config "apps/${app}/cloudbuild.yaml" \
--substitutions="$SUBS" \
.
done
# Build + push + deploy the scanner Cloud Run job (used when SCAN_RUNNER=cloudrun).
if [[ "$DEPLOY_SCANNER" == "1" ]]; then
SCANNER_IMAGE="${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO}/scanner"
echo "==> Building & deploying scanner job (${SCANNER_IMAGE})"
gcloud builds submit \
--config "apps/cli/cloudbuild.yaml" \
--substitutions="_REGION=${REGION},_IMAGE=${SCANNER_IMAGE}" \
.
fi
echo "==> Done. Cerebrus services:"
gcloud run services list --platform=managed --region="$REGION" \
--filter="metadata.name~^cerebrus-(backend|frontend)$" \
--format='table(metadata.name, status.url)'