Skip to content

Always keep a caster's signature attack cantrip #7

Always keep a caster's signature attack cantrip

Always keep a caster's signature attack cantrip #7

Workflow file for this run

name: Deploy to Cloud Run
# Builds the single-container app (SPA + API + WebSocket) and deploys it to
# Cloud Run, wired to Cloud SQL (Postgres+pgvector), Memorystore (Redis, via a
# Serverless VPC connector), and a GCS bucket for generated images.
# One-time GCP/GitHub setup is in DEPLOY.md.
on:
push:
branches: [main]
workflow_dispatch:
env:
SERVICE: ai-dm
REGION: europe-west2 # London (infra + Gemini DM + Imagen)
# The image-consistency model (gemini-2.5-flash-image) isn't served in
# europe-west2, so reference-conditioned calls go to europe-west1.
EDIT_LOCATION: europe-west1
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build --workspace @ai-dm/engine # other packages resolve @ai-dm/engine via its dist
- run: npm run typecheck
- run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # required for Workload Identity Federation
steps:
- uses: actions/checkout@v4
- id: auth
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
service_account: ${{ secrets.DEPLOY_SERVICE_ACCOUNT }}
- uses: google-github-actions/setup-gcloud@v2
# Build the image and push to Artifact Registry (repo provisioned by
# Terraform — see infra/), then deploy it to Cloud Run.
- name: Build & push image
run: |
gcloud auth configure-docker "${REGION}-docker.pkg.dev" --quiet
echo "IMAGE=${REGION}-docker.pkg.dev/${{ secrets.GCP_PROJECT }}/aidm/ai-dm:${GITHUB_SHA}" >> "$GITHUB_ENV"
- run: docker build -t "$IMAGE" .
- run: docker push "$IMAGE"
# Env vars use the ^##^ delimiter so URLs with special characters pass
# through cleanly. Live session state is shared in Redis with a per-session
# lock, so it's safe to scale out: min-instances=1 (warm), max-instances=5
# (scale under load). --timeout=3600 keeps WebSockets long-lived.
- name: Deploy
run: |
gcloud run deploy "$SERVICE" \
--image "$IMAGE" \
--project "${{ secrets.GCP_PROJECT }}" \
--region "$REGION" \
--platform managed \
--allow-unauthenticated \
--min-instances=1 --max-instances=5 \
--timeout=3600 --memory=1Gi --cpu=1 \
--execution-environment=gen2 \
--service-account "${{ secrets.RUNTIME_SERVICE_ACCOUNT }}" \
--add-cloudsql-instances "${{ secrets.CLOUDSQL_INSTANCE }}" \
--vpc-connector "${{ secrets.VPC_CONNECTOR }}" \
--vpc-egress private-ranges-only \
--add-volume=name=images,type=cloud-storage,bucket=${{ secrets.IMAGE_BUCKET }} \
--add-volume-mount=volume=images,mount-path=/images \
--set-env-vars="^##^DM_PROVIDER=gemini##IMAGE_PROVIDER=gemini##GEMINI_MODEL=gemini-2.5-flash##GCP_PROJECT=${{ secrets.GCP_PROJECT }}##GCP_LOCATION=$REGION##GEMINI_EDIT_LOCATION=$EDIT_LOCATION##IMAGE_DIR=/images##DATABASE_URL=${{ secrets.DATABASE_URL }}##REDIS_URL=${{ secrets.REDIS_URL }}"
- name: Show URL
run: gcloud run services describe "$SERVICE" --project "${{ secrets.GCP_PROJECT }}" --region "$REGION" --format='value(status.url)'