Skip to content

CI/CD Pipelines & Cloud Build

The GERCIA platform leverages Google Cloud Build (Region: southamerica-east1 - São Paulo) as its enterprise continuous integration and continuous delivery (CI/CD) engine. The monorepo operates six specialized, high-performance pipelines under deploy/, ensuring deterministic compilation, immutable artifact promotion, and zero-trust deployment across our infrastructure:

flowchart TD
    subgraph TRIGGERS ["Git Triggers (Push to staging / main)"]
        T_DOTNET["dotnet/**<br>deploy/cloudbuild.dotnet.yaml"]
        T_APP["apps/app/**<br>deploy/cloudbuild.app.yaml"]
        T_SITE["apps/site/**<br>deploy/cloudbuild.site.yaml"]
        T_VET["apps/site-vet/**<br>deploy/cloudbuild.site-vet.yaml"]
        T_DOCS["docs/**<br>deploy/cloudbuild.docs.yaml"]
        T_STATUS["apps/status/**<br>deploy/cloudbuild.status.yaml"]
    end

    subgraph PIPELINES ["Google Cloud Build Pipelines (southamerica-east1)"]
        P_DOTNET["1. cloudbuild.dotnet.yaml<br>(.NET 10 Server Host & Tests)"]
        P_APP["2. cloudbuild.app.yaml<br>(Enterprise Angular 22 SPA)"]
        P_SITE["3. cloudbuild.site.yaml<br>(Institutional Public Site)"]
        P_VET["4. cloudbuild.site-vet.yaml<br>(Veterinary Public Site)"]
        P_DOCS["5. cloudbuild.docs.yaml<br>(Private & Public Starlight Docs)"]
        P_STATUS["6. cloudbuild.status.yaml<br>(Out-of-Band Status Page)"]
    end

    subgraph DESTINATIONS ["Deployment Targets"]
        D_RUN["Google Cloud Run (Serverless)<br>(Gercia.Server & gercia-migrator Job)"]
        D_GAR["Google Artifact Registry<br>(Standardized Container Images)"]
        D_CF_PRD["Cloudflare Pages (Production)<br>(gercia, gercia-app, gercia-docs-*, gercia-status)"]
        D_CF_STG["Cloudflare Pages (Staging Isolated)<br>(gercia-stg, gercia-app-stg, gercia-docs-*-stg, gercia-status-stg)"]
    end

    T_DOTNET --> P_DOTNET
    T_APP --> P_APP
    T_SITE --> P_SITE
    T_VET --> P_VET
    T_DOCS --> P_DOCS
    T_STATUS --> P_STATUS

    P_DOTNET --> D_GAR --> D_RUN
    P_APP --> D_CF_PRD & D_CF_STG
    P_SITE --> D_CF_PRD & D_CF_STG
    P_VET --> D_CF_PRD
    P_DOCS --> D_CF_PRD & D_CF_STG
    P_STATUS --> D_CF_PRD & D_CF_STG

2. Platform Backend Engine Pipeline (cloudbuild.dotnet.yaml)

Section titled “2. Platform Backend Engine Pipeline (cloudbuild.dotnet.yaml)”

The primary platform pipeline compiles, tests, containerizes, and deploys the unified .NET 10 backend host (Gercia.Server) and triggers ephemeral schema migrations via Cloud Run Jobs (gercia-migrator). It executes on Google Cloud’s E2_HIGHCPU_8 machine type (8 vCPUs, 8 GB RAM) to maximize build throughput.

To minimize CI/CD execution time, the pipeline uses Cloud Build’s native waitFor: directives, executing Docker builds and cache operations concurrently:

flowchart TD
    CACHE["1. Restore NuGet Cache (gsutil)"] --> TESTS["2. Run Unit & Architecture Tests<br>(Gercia.UnitTests.slnf)"]

    subgraph PIPELINE ["Unified Build & Cache (8 vCPUs)"]
        TESTS --> B_SERVER["3. Build or Promote Image: gercia-server"]
        TESTS --> S_CACHE["4. Save NuGet Cache to GCS"]
    end

    B_SERVER --> PUSH["5. Push Unified Image (Artifact Registry)"]
    PUSH --> MIGRATE["6. Execute Cloud Run Job: gercia-migrator<br>(--migrate & --seed)"]
    MIGRATE --> DEPLOY["7. Deploy Revision to Google Cloud Run<br>(api-stg / api-prd)"]
    DEPLOY --> NOTIFY["8. Notify Google Chat"]
    S_CACHE --> NOTIFY
  1. Immutable Promotion Pattern (Build Once, Deploy Anywhere):
    • On staging branch: Compiles source code, runs tests, builds the single unified Docker image (gercia-server) using layer caching, and tags the image with $COMMIT_SHA and staging.
    • On main branch (Production): The pipeline never recompiles from source. It pulls the exact binary image validated in staging, retags it with main and $COMMIT_SHA, and promotes it to production Cloud Run services and jobs. This guarantees 100% binary parity between environments.
  2. Standardized Artifact Registry & FinOps Lifecycle:
    • Images are pushed exclusively to the canonical repository $_LOCATION-docker.pkg.dev/$PROJECT_ID/$_REPOSITORY/<service>:<tag>:
      • Repository URI: southamerica-east1-docker.pkg.dev/gercia-gcp/gercia-platform
      • Canonical Image: gercia-server (Unified ASP.NET Core Host: REST API Gateway, OpenIddict STS, AI MCP Protocol, and Migration CLI Runner)
    • Automated FinOps Cleanup Policies: The gercia-platform repository enforces active automated lifecycle policies to prevent disk bloat and control GCP storage costs:
      • delete-untagged-after-14d: Automatically purges untagged (UNTAGGED) container digests older than 14 days (1,209,600s).
      • keep-recent-10-versions: Retains the latest 10 versions for active tags (staging, main, $COMMIT_SHA), guaranteeing immediate rollback capability while eliminating stale layers.
    • Decommissioned Legacy Repositories: The legacy gercia repository (1.51 GB) and obsolete microservice packages (gercia-api, gercia-web, gercia-worker, gercia-mcp, gercia-logshipper, gercia-notify) were permanently retired.
  3. Automated Serverless Rollout (Google Cloud Run):
    • Staging: Automatic continuous deployment to Cloud Run revisions with 100% traffic assignment upon build completion.
    • Production: Deploys zero-downtime rolling revisions with automated HTTP health checks (--health).
  4. Solution Filters & Workload Segregation (Gercia.Server.slnf & Gercia.UnitTests.slnf):
    • The test step validates server compilation using Gercia.Server.slnf and executes unit and architecture tests via Gercia.UnitTests.slnf (see Solution Filters & Workload Segregation), completely eliminating mobile toolchain dependencies in the Cloud Build Linux container.

3. Enterprise Angular SPA Pipeline (cloudbuild.app.yaml)

Section titled “3. Enterprise Angular SPA Pipeline (cloudbuild.app.yaml)”

The enterprise presentation layer (apps/app/, package @gercia/app) serves human healthcare (app.gercia.com.br), veterinary clinics (app.gercia.vet.br), and backoffice operations (ops.gercia.com.br):

  1. Monorepo Directory: apps/app/ (@gercia/app).
  2. Quality Gate (Automated Unit Tests): Executes pnpm --filter @gercia/app test (14 unit tests across PortalService, AuthService, and AppComponent). If any test fails, deployment aborts immediately.
  3. Application Build & Output Structure: Executes pnpm --filter @gercia/app run build, compiling Angular 22 Zoneless Signals into apps/app/dist/app/browser/.
  4. Cloudflare SPA Routing Rule (_redirects): Angular build copies apps/app/public/_redirects (/* /index.html 200) into dist/app/browser/_redirects, ensuring all client-side routes resolve without HTTP 404.
  5. Edge Functions & Wrangler Deployment: Executes npx wrangler pages deploy dist/app/browser with dynamic project resolution:
    • Production (Tags / Releases): Targets Cloudflare Pages project gercia-app (branch main), serving app.gercia.com.br, ops.gercia.com.br, and app.gercia.vet.br.
    • Staging (Branch staging): Targets isolated project gercia-app-stg (branch staging), serving app-stg.gercia.com.br, ops-stg.gercia.com.br, and app-stg.gercia.vet.br behind Cloudflare Zero Trust.
    • Wrangler compiles and uploads Edge Functions (apps/app/functions/api/ops/me.ts) alongside static browser bundles.

4. Unified Documentation Portals Pipeline (cloudbuild.docs.yaml)

Section titled “4. Unified Documentation Portals Pipeline (cloudbuild.docs.yaml)”

Builds and deploys both documentation portals simultaneously in parallel:

  1. Concurrent Static Builds (Astro Starlight):
    • Private Architecture Portal: Builds docs/private/ with Pagefind indexing and Mermaid diagram transformations.
    • Public Help Center: Builds docs/public/ with multilingual guides for doctors, pharmacies, and patients.
  2. Segregated Cloudflare Pages Deployments:
    • Private Docs: Deploys docs/private/dist to project gercia-docs-private (Production, branch main -> https://eng.gercia.com.br) or gercia-docs-private-stg (Staging, branch staging -> https://eng-stg.gercia.com.br), secured with Cloudflare Zero Trust.
    • Public Docs: Deploys docs/public/dist to project gercia-docs-public (Production, branch main -> https://docs.gercia.com.br) or gercia-docs-public-stg (Staging, branch staging -> https://docs-stg.gercia.com.br).

5. Institutional Public Site Pipeline (cloudbuild.site.yaml)

Section titled “5. Institutional Public Site Pipeline (cloudbuild.site.yaml)”

The institutional marketing site is consolidated under apps/site/ within the root monorepo, managed via pnpm workspaces (@gercia/site):

  1. Monorepo Directory: apps/site/ (@gercia/site).
  2. Static Build: Executes pnpm run build:site, compiling Astro 7, Tailwind CSS v4, and Svelte 5 into apps/site/dist/.
  3. Segregated Wrangler Deployment:
    • Production (Tags / Releases): Deploys dist targeting project gercia (branch main -> https://gercia.com.br).
    • Staging (Branch staging): Deploys dist targeting isolated project gercia-stg (branch staging -> https://site-stg.gercia.com.br behind Cloudflare Zero Trust).

6. Sovereign Veterinary Public Site Pipeline (cloudbuild.site-vet.yaml)

Section titled “6. Sovereign Veterinary Public Site Pipeline (cloudbuild.site-vet.yaml)”

The sovereign marketing site for the veterinary healthcare vertical is consolidated under apps/site-vet/ within the root monorepo, managed via pnpm workspaces (@gercia/site-vet):

  1. Monorepo Directory: apps/site-vet/ (@gercia/site-vet).
  2. Static Build: Executes pnpm run build:site-vet, compiling Astro 7, Tailwind CSS v4, and Svelte 5 into apps/site-vet/dist/.
  3. Wrangler Deployment: Deploys dist targeting Cloudflare Pages project gercia-site-vet (bound to https://gercia.vet.br and previewing on https://site-stg.gercia.vet.br).

7. Out-of-Band Status Page Pipeline (cloudbuild.status.yaml)

Section titled “7. Out-of-Band Status Page Pipeline (cloudbuild.status.yaml)”

Builds and deploys the out-of-band status and incident management portal (apps/status/) to Cloudflare Pages:

  1. Static Build: Installs dependencies and builds the Astro 7, Tailwind CSS v4, and Svelte 5 status application (apps/status/).
  2. Segregated Wrangler Deployment:
    • Production (Tags / Releases): Deploys dist targeting project gercia-status (branch main -> https://status.gercia.com.br).
    • Staging (Branch staging): Deploys dist targeting isolated project gercia-status-stg with staging D1 database binding (cf415281-b355-40fb-96fa-ec49333c53a0, branch staging -> https://status-stg.gercia.com.br behind Cloudflare Zero Trust).

8. Architectural Decision: Cloud Build Direct Upload vs Cloudflare Pages Native Git

Section titled “8. Architectural Decision: Cloud Build Direct Upload vs Cloudflare Pages Native Git”

The platform strictly enforces Google Cloud Build Push-Based Direct Upload over Cloudflare Pages native Git integration:

Evaluation Dimension Cloudflare Pages Native Git Integration Google Cloud Build + Wrangler Direct Upload (Standard)
Monorepo Build Concurrency ⚠️ 1 concurrent build limit across entire CF account. 5 frontends trigger serial queue stalls (15-20 min). ✅ Elastic multi-worker concurrency. Zero pipeline stalls.
Secret Management ⚠️ Decentralized. Requires manually maintaining tokens and variables in CF Web UI. ✅ Centralized in Google Secret Manager (GSM) (CF_API_TOKEN, CF_ACCOUNT_ID, WEBHOOK_URL).
Automated Test Gates ⚠️ No native test step. Failures only caught if embedded in npm build script. ✅ Strict test gates (ng test, architecture tests) aborting deploys on failure.
Edge Deployment Speed ⚠️ Clones entire monorepo and reinstalls pnpm on every build (3-5 min per project). ✅ 3 to 5 second atomic asset upload via Wrangler CLI to Anycast Edge.

8.1. Cloudflare Pages Direct Upload Custom Domain Routing Invariant

Section titled “8.1. Cloudflare Pages Direct Upload Custom Domain Routing Invariant”

In Cloudflare Pages Direct Upload architectures (npx wrangler pages deploy), custom domains bound to a project route strictly to the project’s canonical production_branch. Cloudflare Edge DNS proxying ignores branch-prefixed CNAME targets (such as staging.<project>.pages.dev or preview.<project>.pages.dev) for bound custom domains, unconditionally serving the latest deployment of the project’s configured production branch.

To achieve complete zero-blast-radius isolation between pre-release code and production traffic, the platform enforces the Twin Project Architecture:

  • Production Projects (<project>): Configured with production_branch: "main", bound to production apex/subdomains (gercia.com.br, app.gercia.com.br, ops.gercia.com.br, docs.gercia.com.br, eng.gercia.com.br, status.gercia.com.br). Deployed strictly upon verified Git release tags.
  • Staging Projects (<project>-stg): Configured with production_branch: "staging", bound to staging subdomains (site-stg.gercia.com.br, app-stg.gercia.com.br, ops-stg.gercia.com.br, app-stg.gercia.vet.br, docs-stg.gercia.com.br, eng-stg.gercia.com.br, status-stg.gercia.com.br). Deployed continuously upon merges to the staging branch and protected by Cloudflare Zero Trust.

9. Google Cloud Build Canonical Triggers Specification (12 Triggers)

Section titled “9. Google Cloud Build Canonical Triggers Specification (12 Triggers)”

All CI/CD automation runs in Google Cloud’s southamerica-east1 (São Paulo) region, orchestrated through 12 triggers separated strictly between continuous delivery for staging and tag-based release gates for production:

A. Staging Continuous Delivery Triggers (6 Triggers)

Section titled “A. Staging Continuous Delivery Triggers (6 Triggers)”

Activated automatically on code merge to the staging branch:

Specification Platform Backend (gercia-dotnet-stg) Enterprise SPA (gercia-app-stg) Documentation (gercia-docs-stg) Public Site (gercia-site-stg) Veterinary Site (gercia-site-vet-stg) Status Page (gercia-status-stg)
Trigger Name gercia-dotnet-stg gercia-app-stg gercia-docs-stg gercia-site-stg gercia-site-vet-stg gercia-status-stg
GCP Region southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1
Repository gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform
Event Type Push to branch Push to branch Push to branch Push to branch Push to branch Push to branch
Branch Regex ^staging$ ^staging$ ^staging$ ^staging$ ^staging$ ^staging$
Config File deploy/cloudbuild.dotnet.yaml deploy/cloudbuild.app.yaml deploy/cloudbuild.docs.yaml deploy/cloudbuild.site.yaml deploy/cloudbuild.site-vet.yaml deploy/cloudbuild.status.yaml
Included Files dotnet/**
deploy/cloudbuild.dotnet.yaml
apps/app/**
deploy/cloudbuild.app.yaml
docs/**
deploy/cloudbuild.docs.yaml
apps/site/**
deploy/cloudbuild.site.yaml
apps/site-vet/**
deploy/cloudbuild.site-vet.yaml
apps/status/**
deploy/cloudbuild.status.yaml
Machine Type E2_HIGHCPU_8 Standard Standard Standard Standard Standard
Build Timeout 1800s (30 min) 600s (10 min) 900s (15 min) 600s (10 min) 600s (10 min) 300s (5 min)
Logging Mode CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY

B. Production Component Release Triggers (6 Triggers)

Section titled “B. Production Component Release Triggers (6 Triggers)”

Activated strictly on CalVer release tags (<component>/YYYY.MM.DD.N), subject to Step 0 Ancestry Gate validation:

Specification Platform Backend (gercia-dotnet-prd) Enterprise SPA (gercia-app-prd) Documentation (gercia-docs-prd) Public Site (gercia-site-prd) Veterinary Site (gercia-site-vet-prd) Status Page (gercia-status-prd)
Trigger Name gercia-dotnet-prd gercia-app-prd gercia-docs-prd gercia-site-prd gercia-site-vet-prd gercia-status-prd
GCP Region southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1 southamerica-east1
Repository gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform gercia/gercia-platform
Event Type Push new tag Push new tag Push new tag Push new tag Push new tag Push new tag
Tag Regex ^server/.* ^app/.* ^docs/.* ^site/.* ^vet/.* ^status/.*
Config File deploy/cloudbuild.dotnet.yaml deploy/cloudbuild.app.yaml deploy/cloudbuild.docs.yaml deploy/cloudbuild.site.yaml deploy/cloudbuild.site-vet.yaml deploy/cloudbuild.status.yaml
Included Files dotnet/**
deploy/cloudbuild.dotnet.yaml
apps/app/**
deploy/cloudbuild.app.yaml
docs/**
deploy/cloudbuild.docs.yaml
apps/site/**
deploy/cloudbuild.site.yaml
apps/site-vet/**
deploy/cloudbuild.site-vet.yaml
apps/status/**
deploy/cloudbuild.status.yaml
Machine Type E2_HIGHCPU_8 Standard Standard Standard Standard Standard
Build Timeout 1800s (30 min) 600s (10 min) 900s (15 min) 600s (10 min) 600s (10 min) 300s (5 min)
Ancestry Gate Enforced (Step 0) Enforced (Step 0) Enforced (Step 0) Enforced (Step 0) Enforced (Step 0) Enforced (Step 0)
Logging Mode CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY CLOUD_LOGGING_ONLY