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.
- Find the PostgreSQL service IP (shared or branch DB), for example:
kubectl get svc -n review-dbs postgres-service-review-dbs -o wide
-
Use your SQL client with:
-
Host:
<postgres-service-ip> - Port:
5432 - 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_URLinsidemaster-secrets-<sanitized-branch>
5.2 Option B - Direct Redis access via Twingate
- Find Redis service IP in your branch namespace:
kubectl get svc -n <branch-namespace> redis-service-<branch-namespace> -o wide
-
Connect with your Redis client:
-
Host:
<redis-service-ip> - Port:
6379 - Password: from
REDISCLOUD_URLinsidemaster-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:
- Open latest version and copy its value
- Edit needed keys/values locally
- Add a new secret version
- 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-managementinus-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