CI/CD Pipelines & Cloud Build
1. Monorepo Pipeline Architecture
Section titled “1. Monorepo Pipeline Architecture”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.
Pipeline Execution Graph (DAG)
Section titled “Pipeline Execution Graph (DAG)”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
Key Architectural Invariants:
Section titled “Key Architectural Invariants:”- Immutable Promotion Pattern (Build Once, Deploy Anywhere):
- On
stagingbranch: Compiles source code, runs tests, builds the single unified Docker image (gercia-server) using layer caching, and tags the image with$COMMIT_SHAandstaging. - On
mainbranch (Production): The pipeline never recompiles from source. It pulls the exact binary image validated in staging, retags it withmainand$COMMIT_SHA, and promotes it to production Cloud Run services and jobs. This guarantees 100% binary parity between environments.
- On
- 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)
- Repository URI:
- Automated FinOps Cleanup Policies: The
gercia-platformrepository 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
gerciarepository (1.51 GB) and obsolete microservice packages (gercia-api,gercia-web,gercia-worker,gercia-mcp,gercia-logshipper,gercia-notify) were permanently retired.
- Images are pushed exclusively to the canonical repository
- 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).
- Solution Filters & Workload Segregation (
Gercia.Server.slnf&Gercia.UnitTests.slnf):- The test step validates server compilation using
Gercia.Server.slnfand executes unit and architecture tests viaGercia.UnitTests.slnf(see Solution Filters & Workload Segregation), completely eliminating mobile toolchain dependencies in the Cloud Build Linux container.
- The test step validates server compilation using
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):
- Monorepo Directory:
apps/app/(@gercia/app). - Quality Gate (Automated Unit Tests): Executes
pnpm --filter @gercia/app test(14 unit tests acrossPortalService,AuthService, andAppComponent). If any test fails, deployment aborts immediately. - Application Build & Output Structure: Executes
pnpm --filter @gercia/app run build, compiling Angular 22 Zoneless Signals intoapps/app/dist/app/browser/. - Cloudflare SPA Routing Rule (
_redirects): Angular build copiesapps/app/public/_redirects(/* /index.html 200) intodist/app/browser/_redirects, ensuring all client-side routes resolve without HTTP 404. - Edge Functions & Wrangler Deployment: Executes
npx wrangler pages deploy dist/app/browserwith dynamic project resolution:- Production (Tags / Releases): Targets Cloudflare Pages project
gercia-app(branchmain), servingapp.gercia.com.br,ops.gercia.com.br, andapp.gercia.vet.br. - Staging (Branch
staging): Targets isolated projectgercia-app-stg(branchstaging), servingapp-stg.gercia.com.br,ops-stg.gercia.com.br, andapp-stg.gercia.vet.brbehind Cloudflare Zero Trust. - Wrangler compiles and uploads Edge Functions (
apps/app/functions/api/ops/me.ts) alongside static browser bundles.
- Production (Tags / Releases): Targets Cloudflare Pages project
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:
- 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.
- Private Architecture Portal: Builds
- Segregated Cloudflare Pages Deployments:
- Private Docs: Deploys
docs/private/distto projectgercia-docs-private(Production, branchmain->https://eng.gercia.com.br) orgercia-docs-private-stg(Staging, branchstaging->https://eng-stg.gercia.com.br), secured with Cloudflare Zero Trust. - Public Docs: Deploys
docs/public/distto projectgercia-docs-public(Production, branchmain->https://docs.gercia.com.br) orgercia-docs-public-stg(Staging, branchstaging->https://docs-stg.gercia.com.br).
- Private Docs: Deploys
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):
- Monorepo Directory:
apps/site/(@gercia/site). - Static Build: Executes
pnpm run build:site, compiling Astro 7, Tailwind CSS v4, and Svelte 5 intoapps/site/dist/. - Segregated Wrangler Deployment:
- Production (Tags / Releases): Deploys
disttargeting projectgercia(branchmain->https://gercia.com.br). - Staging (Branch
staging): Deploysdisttargeting isolated projectgercia-stg(branchstaging->https://site-stg.gercia.com.brbehind Cloudflare Zero Trust).
- Production (Tags / Releases): Deploys
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):
- Monorepo Directory:
apps/site-vet/(@gercia/site-vet). - Static Build: Executes
pnpm run build:site-vet, compiling Astro 7, Tailwind CSS v4, and Svelte 5 intoapps/site-vet/dist/. - Wrangler Deployment: Deploys
disttargeting Cloudflare Pages projectgercia-site-vet(bound tohttps://gercia.vet.brand previewing onhttps://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:
- Static Build: Installs dependencies and builds the Astro 7, Tailwind CSS v4, and Svelte 5 status application (
apps/status/). - Segregated Wrangler Deployment:
- Production (Tags / Releases): Deploys
disttargeting projectgercia-status(branchmain->https://status.gercia.com.br). - Staging (Branch
staging): Deploysdisttargeting isolated projectgercia-status-stgwith staging D1 database binding (cf415281-b355-40fb-96fa-ec49333c53a0, branchstaging->https://status-stg.gercia.com.brbehind Cloudflare Zero Trust).
- Production (Tags / Releases): Deploys
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 withproduction_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 withproduction_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 thestagingbranch 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 |