Zum Hauptinhalt springen

Deployment

GitLab CI orchestriert das Ganze. Die Pipeline ist projekt-portabel (parametrisiert über RUN_PROJECT_ID, WIF_SERVICE_ACCOUNT, AR_HOST), sodass ein frisches GCP-Projekt durch erneutes Anwenden des Terraform-Stacks plus Updates dieser Variablen aufgesetzt werden kann.

Stage-Diagramm

Promotion-Modell

ServiceMaster-PushGit Tag
nano-server (run)Build + Deploy mit 0% TrafficLatest auf 100% promoten
nano-mcp-server (run)Build + Deploy mit 0% TrafficLatest auf 100% promoten
Frontend (Hosting)Preview Channel pro BranchLive-Deploy
Docs (Hosting)Preview Channel pro BranchLive-Deploy

Operators promoten eine Cloud-Run-Revision, indem sie einen Tag (v3.x.y) pushen. Der RUN_update_traffic-Branch im CICD-Template feuert nur, wenn $CI_COMMIT_TAG gesetzt ist.

Manuelles Promoten (falls nötig):

gcloud run services update-traffic nano-server --region=europe-west4 --project=cpl-gen-ai-marketing --to-latest
gcloud run services update-traffic nano-mcp-server --region=europe-west4 --project=cpl-gen-ai-marketing --to-latest

Firebase Hosting Multi-Site

Zwei Sites unter dem gleichen GCP-Projekt teilen sich Firestore, IAM und Billing:

TargetSite-NameURL (Firebase-Fallback)Primäre Custom Domain
appcpl-gen-ai-marketinghttps://cpl-gen-ai-marketing.web.apphttps://nano.cpl.ai
docscpl-gen-ai-marketing-docshttps://cpl-gen-ai-marketing-docs.web.apphttps://docs.nano.cpl.ai

Der MCP-Cloud-Run-Service hat eine eigene Custom-Domain-Mapping: https://mcp.nano.cpl.ainano-mcp-server (Cloud Run, Region europe-west1).

CI deployed jedes via firebase deploy --only hosting:<target>, gesteuert über die GitLab-Variable FIREBASE_TOKEN (erzeugt mit firebase login:ci, gespeichert als Masked + Protected).

One-Time-Setup für ein neues Projekt

  1. GCP-Projekt anlegen; Cloud Run, Cloud Tasks, Firestore, Firebase, Secret Manager und IAM APIs aktivieren.

  2. Den gitlab-ci@<project>.iam.gserviceaccount.com-SA manuell anlegen (Terraform codifiziert ihn später als data-Block).

  3. terraform apply in terraform/bootstrap/ laufen lassen, danach terraform/runtime/.

  4. Secret-Werte seeden: gemini-api-key, mcp-private-key, mcp-google-oauth-client-id, mcp-google-oauth-client-secret.

  5. Die Firebase-Hosting-Sites anlegen:

    firebase hosting:sites:create cpl-gen-ai-marketing --project cpl-gen-ai-marketing
    firebase hosting:sites:create cpl-gen-ai-marketing-docs --project cpl-gen-ai-marketing
    firebase target:apply hosting app cpl-gen-ai-marketing --project cpl-gen-ai-marketing
    firebase target:apply hosting docs cpl-gen-ai-marketing-docs --project cpl-gen-ai-marketing
  6. Die GitLab-CI/CD-Variable FIREBASE_TOKEN seeden (firebase login:ci).

  7. Google-OAuth-Client (Web Type) konfigurieren, Redirect-URI https://<mcp-url>/auth/google/callback eintragen, Client-ID + Secret in den Secret Manager schreiben.

  8. Nach master pushen. Die erste Pipeline baut ci-base, applied Terraform, baut + deployed die Cloud-Run-Services und einen Hosting-Preview-Channel pro Branch.

  9. Ein Release taggen (vX.Y.Z), um Traffic zu promoten und Hosting live zu deployen.

DNS für Custom Domains

Live-Domains: nano.cpl.ai, docs.nano.cpl.ai, mcp.nano.cpl.ai. DNS wird manuell in Cloud DNS gepflegt (noch nicht in Terraform).

Um eine neue Domain anzulegen oder eine umzubinden:

  1. Firebase-Hosting-Site (oder Cloud-Run-Service) → "Add custom domain".
  2. Verification-TXT-Record beim DNS-Provider eintragen.
  3. Auf Verification warten, dann die A- / CNAME-Records eintragen, die die Console ausspuckt. SSL-Provisioning läuft automatisch (managed Zertifikat).
  4. Damit Firebase Auth (Google Sign-In) auf der neuen Domain funktioniert, die Domain in Firebase Console → Authentication → Settings → Authorized domains hinzufügen. Sonst schlägt jeder Sign-in mit Firebase: Error (auth/unauthorized-domain) fehl.
  5. MCP_PUBLIC_URL auf nano-mcp-server muss zur öffentlichen URL passen (https://mcp.nano.cpl.ai), sonst scheitert jede OAuth-iss/aud-Prüfung. CLOUD_RUN_URL zeigt weiterhin auf die interne Cloud-Run-Service-URL — siehe ADR-0003.
  6. Die CORS-Allowlist in packages/server/src/index.ts muss das neue Frontend-Origin enthalten, sonst scheitern Browser-Fetches mit CORS-Fehlern.