Skip to content

Cred API Commercial Review Environments

This guide explains how review environments are created, managed, and debugged.

Implementation code for this setup lives in: https://github.com/credinvest/infra-cred-review

1. Overview

Review environments are managed by the cluster-management Cloud Run service in cred-review.

For each branch:

  • A dedicated Kubernetes namespace is created in GKE (review-app-dev)
  • API + worker workloads are deployed in that namespace
  • A dedicated Redis instance is created in that namespace
  • A branch URL is exposed as https://<sanitized-branch>.k8s-dev.credplatform.com
  • A branch secret is created in Secret Manager as master-secrets-<sanitized-branch>

Database behavior:

  • By default, environments use the shared review DB in namespace review-dbs
  • If requested, a dedicated branch DB is created and wired into the branch secret
  • The shared review DB (commercial_dev) is refreshed weekly from the source commercial dev database (source-db-url) by the scheduled migration job (review-app-db-migration-weekly, Saturday 15:40 UTC)

2. Naming Rules (Important)

Branch names are sanitized before Kubernetes resources are created:

  • Lowercase only
  • Non-alphanumeric characters become -
  • Result is truncated to 25 chars
  • Kubernetes namespace, DNS subdomain, Cloud Build trigger suffix, and secret suffix use the sanitized value

If your original branch name is long or contains special characters, the final namespace/URL/secret name may differ from the Git branch literal.

3. Create a Review App (Normal Flow)

Create a PR in cred-api-commercial.

The review app GitHub Action will trigger environment creation through cluster-management and post a PR comment with:

  • Review URL
  • Secret Manager link
  • Namespace logs / app logs / worker logs links

After the initial review app creation, every new commit pushed to the same PR branch triggers automatic redeploy of both API and worker deployments.

When the PR is closed, the corresponding review environment is automatically deleted.

The URL may take a short time to become reachable after the action reports success (DNS and routing propagation).

3.1 Create with Dedicated DB

Add the database label to the PR before running review app creation.

That passes create_db=true in environment creation and provisions a dedicated PostgreSQL instance for that branch.

4. Connect to Databases

4.1 Prerequisites

gcloud auth login
gcloud config set project cred-review
gcloud container clusters get-credentials review-app-dev --region us-central1 --project cred-review

You can connect to PostgreSQL in two ways:

  • Option A: Kubernetes auth proxy (kubectl port-forward)
  • Option B: Direct internal IP through Twingate VPN

4.2 Option A - Kubernetes auth proxy (shared review DB default)

kubectl port-forward --namespace review-dbs \
  $(kubectl get pod --namespace review-dbs --selector="app=postgres-master" --output jsonpath='{.items[0].metadata.name}') \
  8080:5432

Then connect with your SQL client:

  • Host: localhost
  • Port: 8080 (or your forwarded port)
  • Credentials: same as development DB credentials

4.3 Option A - Kubernetes auth proxy (dedicated branch DB)

Open GKE Workloads/Services in project cred-review, locate the branch postgres service in the branch namespace, and use Port Forwarding from the UI (or run equivalent kubectl port-forward).

4.4 Option B - Direct DB access via Twingate

If you are connected to the internal network through Twingate VPN, you can connect directly using the PostgreSQL service IP.

  1. Find the PostgreSQL service IP (shared or branch DB), for example:
kubectl get svc -n review-dbs postgres-service-review-dbs -o wide
  1. Use your SQL client with:

  2. Host: <postgres-service-ip>

  3. Port: 5432
  4. Credentials: same DB credentials used for that environment

Use this only when your Twingate profile has access to the relevant network range and firewall rules allow it.

5. Connect to Redis

You can connect to Redis in two ways:

  • Option A: Kubernetes auth proxy (kubectl port-forward)
  • Option B: Direct internal IP through Twingate VPN

5.1 Option A - Kubernetes auth proxy

Locate your branch Redis service in the branch namespace and port-forward locally.

Connection settings:

  • Host: localhost
  • Port: local forwarded port
  • Password: from REDISCLOUD_URL inside master-secrets-<sanitized-branch>

5.2 Option B - Direct Redis access via Twingate

  1. Find Redis service IP in your branch namespace:
kubectl get svc -n <branch-namespace> redis-service-<branch-namespace> -o wide
  1. Connect with your Redis client:

  2. Host: <redis-service-ip>

  3. Port: 6379
  4. Password: from REDISCLOUD_URL inside master-secrets-<sanitized-branch>

Use this only when your Twingate profile has access to the relevant network range and firewall rules allow it.

6. Update Branch Secrets

Open Secret Manager in project cred-review and update:

master-secrets-<sanitized-branch>

Process:

  1. Open latest version and copy its value
  2. Edit needed keys/values locally
  3. Add a new secret version
  4. Optionally disable older versions

After a new version is added, redeploy is automatically triggered via the secret-change handler (Cloud Function + Cloud Build trigger), which updates API and worker deployments for that branch.

7. Recreate Environment

Re-run the review app workflow for the branch in cred-api-commercial:

https://github.com/credinvest/cred-api-commercial/actions/workflows/create-review-app.yml

Recreate logic deletes and recreates the branch namespace/resources.

8. Execute Worker Task

Get worker pod name in your branch namespace:

kubectl get pods -n <namespace> | grep worker

Run task command:

kubectl exec -it <worker-pod-name> -n <namespace> -- <your-task-command>

Example:

kubectl exec -it commercial-api-com-24311-main-contact-em-worker-644cfd8fc6-pfdlp \
  -n com-24311-main-contact-em \
  -- node dist/worker/tasks/execute-task.js --t CREATE_CUSTOM_FIELDS_FROM_TEMPLATE

9. Manual API Invocation (Only if Needed)

Use this if GitHub workflow is unavailable.

9.1 Auth

Cluster-management requires an identity token:

TOKEN="$(gcloud auth print-identity-token)"

9.2 Create Environment

Without dedicated DB:

curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  "https://cluster-management-398157627861.us-central1.run.app/environments/create/<branch_name>"

With dedicated DB:

curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  "https://cluster-management-398157627861.us-central1.run.app/environments/create/<branch_name>?create_db=true"

9.3 Get Environment Status

curl -H "Authorization: Bearer ${TOKEN}" \
  "https://cluster-management-398157627861.us-central1.run.app/environments/<branch_name>"

9.4 Delete Environment

curl -X DELETE \
  -H "Authorization: Bearer ${TOKEN}" \
  "https://cluster-management-398157627861.us-central1.run.app/environments/<branch_name>"

9.5 Emergency Cleanup (all managed envs)

curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  "https://cluster-management-398157627861.us-central1.run.app/environments/cleanup-all"

10. Monitoring and Troubleshooting

  • Cluster-management logs: Cloud Run service cluster-management in us-central1
  • Namespace workload health: GKE Workloads page in cred-review
  • Branch app/worker logs: use links from PR bot comment or query logs by namespace/workload label

Common pitfalls:

  • Branch name mismatch: check sanitized namespace/secret name
  • URL not ready immediately after success: wait for route/DNS propagation
  • Secret updated but no rollout yet: verify secret-change function and matching Cloud Build trigger commercial-api-<sanitized-branch>
  • DB connectivity issues: confirm cluster credentials and active port-forward session