Skip to main content

Bilko Deploy — Standard Operating Procedure

Bilko Deploy — Standard Operating Procedure

Last updated: 2026-04-22
Owner: FlowForge (Kelsey Hightower)
Status: ACTIVE

Cloud Run Architecture

GCP Project: tribal-sign-487920-k0
Region: europe-north1
Services:

  • bilko-web — Next.js 15 frontend (main branch → bilko-demo.alai.no)
  • bilko-api — Express API (main branch → bilko-api-762788903040.europe-north1.run.app)
  • bilko-intesa-demo — Intesa pitch demo (feat/intesa-bih-demo → manual deploy only)

Deploy Map

Branch Service URL CI Workflow Last Verified
main bilko-web https://bilko-demo.alai.no gcp-deploy.yml (BROKEN) 2026-04-22
main bilko-api https://bilko-api-762788903040.europe-north1.run.app gcp-deploy.yml (BROKEN) 2026-04-18
feat/intesa-bih-demo bilko-intesa-demo https://bilko-intesa-demo-762788903040.europe-north1.run.app Manual gcloud only 2026-04-17

Pre-Flight Checks (ZAKON PI2 Check 2)

OBAVEZNO — Run these 4 commands and paste output into MC task BEFORE touching code:

# 1. Target URL alive?
curl -sI https://bilko-demo.alai.no | head -3

# 2. Branch state?
git log main --oneline -5

# 3. CI health?
gh run list --repo alai-holding/bilko --branch main --limit 3

# 4. Cloud Run service status?
gcloud run services describe bilko-web \
  --region europe-north1 \
  --project tribal-sign-487920-k0 \
  --format='value(status.latestReadyRevisionName,status.url,status.traffic)'

If any returns unexpected: STOP, escalate to John. Do not proceed.

CI Pipeline Status

Status: BROKEN (2026-04-15 onwards)
Root Causes:

  1. GitHub Actions minutes quota exhausted (monthly limit reached)
  2. --no-traffic flag on line 206 of gcp-deploy.yml prevents traffic promotion for existing services

Workaround: Use manual deploy path (see below) until CI fixed.

Manual Deploy Path (Emergency + CI Broken)

When CI is broken or for emergency fixes, follow this path:

Step 1: Build Docker Image

cd /Users/makinja/ALAI/products/Bilko

docker build \
  --platform linux/amd64 \
  -f apps/web/Dockerfile \
  --build-arg NEXT_PUBLIC_API_URL=https://bilko-api-762788903040.europe-north1.run.app/api/v1 \
  -t europe-north1-docker.pkg.dev/tribal-sign-487920-k0/bilko/web:fix-<purpose>-<DDmon> \
  .

Image tag convention:

  • fix-bugs-22apr, fix-logo-23apr
  • latest (not traceable)

Context reduction (.dockerignore): As of 2026-04-22, .dockerignore reduces build context from 4.1GB → 50MB by excluding node_modules, .next, apps/e2e, docs, etc.

Step 2: Push to Artifact Registry

gcloud auth configure-docker europe-north1-docker.pkg.dev

docker push europe-north1-docker.pkg.dev/tribal-sign-487920-k0/bilko/web:fix-<purpose>-<DDmon>

Step 3: Deploy to Cloud Run

CRITICAL: Do NOT use --no-traffic flag for existing services. It blocks traffic promotion.

gcloud run deploy bilko-web \
  --image europe-north1-docker.pkg.dev/tribal-sign-487920-k0/bilko/web:fix-<purpose>-<DDmon> \
  --region europe-north1 \
  --platform managed \
  --allow-unauthenticated \
  --max-instances 10 \
  --min-instances 0 \
  --memory 512Mi \
  --cpu 1 \
  --concurrency 100 \
  --timeout 60s \
  --port 3000 \
  --set-env-vars NEXT_PUBLIC_API_URL=https://bilko-api-762788903040.europe-north1.run.app/api/v1,NEXT_TELEMETRY_DISABLED=1 \
  --project=tribal-sign-487920-k0

Step 4: Verify Deployment

# Check revisions
gcloud run revisions list \
  --service bilko-web \
  --region europe-north1 \
  --project=tribal-sign-487920-k0 \
  --limit=5

# Verify traffic routing (should show 100% on latest revision)
gcloud run services describe bilko-web \
  --region europe-north1 \
  --project=tribal-sign-487920-k0 \
  --format='value(status.traffic)'

Post-Deploy Evidence Gate (ZAKON PI2 Check 5)

MC task CANNOT move to done without ALL three:

  1. curl checks: Paste output showing HTTP 200 for expected routes
    curl -sI https://bilko-demo.alai.no | head -3
    curl -sI https://bilko-demo.alai.no/invoices/new | head -3
    curl -sI https://bilko-demo.alai.no/settings | head -3
    curl -sI https://bilko-demo.alai.no/intesa-bridge | head -3  # Should be 404
    
  2. Playwright screenshots: Stored in docs/evidence/<task-id>/*.png
    • Home page
    • Feature verified (e.g., invoice template save button)
    • Any isolation checks (e.g., 404 for client routes on main)
  3. verification.json: Machine-readable evidence file
    {
      "task_id": 8730,
      "timestamp": "2026-04-22T21:41:10Z",
      "revision": "bilko-web-00019-7tl",
      "traffic_100_percent": true,
      "curl_checks": { "home": 200, "intesa-bridge": 404, ... },
      "playwright_pass": true,
      "screenshots": ["home.png", "invoices-new.png", ...]
    }
    

Deploy Flow Diagram

flowchart LR
    A[Code Change] --> B{CI Healthy?}
    B -->|Yes| C[CI: Build + Push]
    B -->|No| D[Manual Build]
    C --> E[Artifact Registry]
    D --> E
    E --> F[Cloud Run Deploy]
    F --> G{Traffic Routing}
    G -->|100%| H[Live]
    G -->|0%| I[Blocked - Check --no-traffic flag]
    H --> J[Evidence Gate]
    J --> K{All 3 checks pass?}
    K -->|Yes| L[MC task done]
    K -->|No| M[Block - Add evidence]

Known Issues + Workarounds

Issue 1: CI broken since 2026-04-15

Symptom: All main branch pushes fail at deploy step
Root cause: GitHub Actions quota + --no-traffic flag
Workaround: Use manual deploy path above

Issue 2: Intesa content leaked to public URL (fixed 2026-04-22)

Symptom: /intesa-bridge route returned 200 on bilko-demo.alai.no
Root cause: Intesa feature branch merged to main
Fix: Deleted intesa routes from main (commit 66d2220) + added branch-purity.yml CI check

Issue 3: Manual paste-copy anti-pattern

Symptom: CEO had to manually paste docker build output and gcloud commands
Root cause: FlowForge task dispatched after image built locally
Fix: Always dispatch FlowForge BEFORE build step, let agent own full flow

Branch Purity Rules

Client-specific routes MUST NOT appear on main. Reserved prefixes:

  • intesa-* → feat/intesa-bih-demo → bilko-intesa-demo Cloud Run
  • corpint-* → TBD client branch → TBD Cloud Run service

CI Enforcement: .github/workflows/branch-purity.yml runs on every PR to main:

find apps/web/app -type d \( -name "intesa-*" -o -name "corpint-*" \) | grep . && exit 1 || exit 0

Registry: ~/system/rules/client-prefix-registry.md

Domain Mapping

  • bilko-demo.alai.no → Cloud Run service bilko-web (configured via GCP Console)
  • DNS: Cloudflare proxy enabled
  • Mapping verified: 2026-04-22
  • DEPLOY-MAP.md: /Users/makinja/ALAI/products/Bilko/DEPLOY-MAP.md
  • Incident Postmortem: BookStack → ALAI / Incidents / incident-2026-04-22-bilko-deploy-fix
  • ZAKON PI2: ~/system/rules/zakon-pi2-deploy-verification.md
  • CI Workflow: .github/workflows/gcp-deploy.yml
  • Dockerfile: apps/web/Dockerfile

Escalation

Owner: FlowForge
Escalate to: John → pi-orchestrator
MC category: devops + priority: H


Created by ALAI Skillforge, 2026-04-22