Deployment Guide

Bilko Deployment Guide

Last Updated: 2026-04-16
Current State: Stable Cloud Run deployment with custom domain provisioning

GCP Project Configuration

Secret Manager

Secret NameVersionPurpose
bilko-cors-originsv2Comma-separated list of allowed CORS origins
bilko-database-urllatestCloud SQL connection string (password reset 2026-04-16)
bilko-jwt-refresh-secretlatestJWT refresh token secret

CORS Parsing: Secret bilko-cors-origins is parsed by comma in apps/api/src/app.ts:61

Environment Variables

bilko-web

bilko-api

Custom Domain Setup

Current Domain

Domain Verification Constraint

Critical: Only alai.no is verified in GCP Search Console (via dev@alai.no).
basicconsulting.no is NOT verified. All custom domains MUST use *.alai.no subdomains until basicconsulting.no is verified.

Custom Domain Runbook

Prerequisites

  1. Domain must be verified in Google Search Console by the GCP account owner
  2. DNS provider access (one.com for alai.no, Vercel for basicconsulting.no)
  3. gcloud CLI authenticated: gcloud auth login

Step-by-Step

1. Create Domain Mapping

gcloud beta run domain-mappings create \
  --service=bilko-web \
  --domain=bilko-demo.alai.no \
  --region=europe-north1 \
  --project=tribal-sign-487920-k0

2. Configure DNS

Add CNAME record at DNS provider:

Type: CNAME
Host: bilko-demo
Value: ghs.googlehosted.com.
TTL: 3600

3. Wait for Certificate Provisioning

gcloud beta run domain-mappings describe bilko-demo.alai.no \
  --region=europe-north1 \
  --project=tribal-sign-487920-k0

Look for status.conditions → CertificateProvisioned: True

4. Update CORS Allowed Origins

# Get current value
gcloud secrets versions access latest --secret=bilko-cors-origins

# Add new domain
echo "https://bilko-demo.alai.no,https://bilko-web-dh4m46blja-lz.a.run.app" | \
  gcloud secrets versions add bilko-cors-origins --data-file=-

5. Deploy New Revision

gcloud run services update-traffic bilko-api \
  --to-latest \
  --region=europe-north1 \
  --project=tribal-sign-487920-k0

6. Verify CORS Preflight

curl -sSI -X OPTIONS \
  https://bilko-api-dh4m46blja-lz.a.run.app/api/v1/auth/login \
  -H "Origin: https://bilko-demo.alai.no" \
  -H "Access-Control-Request-Method: POST"

Expected: HTTP 204 with Access-Control-Allow-Origin: https://bilko-demo.alai.no

GitHub Actions CI/CD

Deployment Steps

  1. Authenticate via WIF
  2. Build Docker images (api + web)
  3. Push to Google Container Registry
  4. Deploy to Cloud Run (europe-north1)
  5. Run smoke tests (Playwright E2E)

Testing

Backend Tests

End-to-End Tests

Recent Fixes (2026-04-16)

Commits

Key Changes

  1. Service Naming: Production services now named bilko-api and bilko-web (no -staging suffix)
  2. API Enhancements: Invoice list now includes currency, new profile settings endpoint
  3. Frontend Fixes: Accessibility improvements (ARIA), avatar initials when no image, visual polish

Rollback Procedure

Rollback to Previous Revision

# List revisions
gcloud run revisions list --service=bilko-api --region=europe-north1

# Rollback
gcloud run services update-traffic bilko-api \
  --to-revisions=bilko-api-00036=100 \
  --region=europe-north1

Rollback via GitHub Actions

git revert HEAD
git push origin main  # Triggers deploy workflow

Troubleshooting

Issue: CORS errors in browser

Cause: Custom domain not in bilko-cors-origins secret
Fix: Update secret (see step 4 in Custom Domain Runbook), deploy new revision

Issue: 502 Bad Gateway

Cause: Service unhealthy or startup timeout
Fix: Check Cloud Run logs: gcloud run services logs read bilko-api --region=europe-north1 --limit=50

Issue: Database connection timeout

Cause: Cloud SQL Proxy misconfiguration or secret outdated
Fix: Verify bilko-database-url secret, check Cloud SQL instance status

Issue: Custom domain SSL pending

Cause: DNS not propagated or domain not verified in Search Console
Fix: Wait 15-30 min after DNS change, verify domain ownership in Search Console

Architecture Diagram

┌─────────────────┐
│  one.com DNS    │
│  bilko-demo.    │
│  alai.no        │
└────────┬────────┘
         │ CNAME
         ▼
┌─────────────────────────────┐
│  ghs.googlehosted.com       │
│  (Google Cloud Load Balancer)│
└────────┬────────────────────┘
         │
         ▼
┌─────────────────────────────┐       ┌──────────────────┐
│  bilko-web (Cloud Run)      │──────▶│  bilko-api       │
│  Next.js 15 + React 19      │  HTTP │  Express + TS    │
│  europe-north1              │       │  europe-north1   │
└─────────────────────────────┘       └────────┬─────────┘
                                               │
                                               ▼
                                      ┌─────────────────┐
                                      │  Cloud SQL      │
                                      │  PostgreSQL 16  │
                                      │  europe-north1  │
                                      └─────────────────┘

Revision #5
Created 2026-02-23 10:24:31 UTC by John
Updated 2026-05-24 20:01:37 UTC by John