feat: declarative Cloud Run configs for backend services#5873
feat: declarative Cloud Run configs for backend services#5873
Conversation
Add per-service YAML configs exported from prod and dev Cloud Run,
mirroring the backend/charts/ convention for GKE. Update deploy
workflow to use `gcloud run services replace` instead of the
deploy-cloudrun@v2 action, making env vars and secrets git-tracked.
Structure:
backend/cloudrun/{service}/{dev|prod}_{service}.yaml
- All secrets use secretKeyRef (Secret Manager), no plain-text secrets
- Replaced hardcoded IP with vad.omiapi.com DNS name
- Added FAIR_USE env vars for PR #5863
- Converted LANGSMITH_API_KEY from plain text to secretKeyRef
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryThis PR migrates all three Cloud Run backend services ( Key changes and findings:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
actor Dev as Developer
participant GHA as GitHub Actions
participant GCR as Google Container Registry
participant FS as Filesystem (checkout)
participant CR as Cloud Run
Dev->>GHA: Trigger workflow (environment=dev|prod, branch)
GHA->>GHA: Validate environment input
GHA->>GHA: Set env prefix (dev/prod)
GHA->>GHA: Build Docker image
GHA->>GCR: Push image as :latest
loop For each service (backend, backend-sync, backend-integration)
GHA->>FS: sed -i replace image line in {prefix}_{service}.yaml
Note over GHA,FS: ⚠️ No verification that sed succeeded
GHA->>CR: gcloud run services replace {config}.yaml
CR-->>GHA: Deploy complete
end
GHA->>GHA: kubectl rollout restart backend-listen (GKE)
Last reviewed commit: "feat: add declarativ..." |
| # Update image in declarative config | ||
| IMAGE="gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }}:latest" | ||
| CONFIG="backend/cloudrun/${{ env.SERVICE }}/${{ steps.env-prefix.outputs.prefix }}_${{ env.SERVICE }}.yaml" | ||
| sed -i "s|image:.*|image: ${IMAGE}|" "$CONFIG" |
There was a problem hiding this comment.
Silent
sed failure with no verification
The sed -i "s|image:.*|image: ${IMAGE}|" command exits 0 even if no substitution was made (e.g., if the image: line is indented differently, commented out, or the file path is wrong). In that case, gcloud run services replace would be called with the stale image reference already present in the YAML file (gcr.io/based-hardware-dev/backend or gcr.io/based-hardware/backend without a tag), potentially deploying a different image than intended with no workflow failure.
Add a verification step after the sed:
sed -i "s|image:.*|image: ${IMAGE}|" "$CONFIG"
grep -q "${IMAGE}" "$CONFIG" || { echo "ERROR: image line not updated in $CONFIG"; exit 1; }
gcloud run services replace "$CONFIG" \
--region=${{ env.REGION }} --project=${{ vars.GCP_PROJECT_ID }}
This same issue affects the backend-sync deploy at line 95 and backend-integration deploy at line 114.
| tcpSocket: | ||
| port: 8080 | ||
| timeoutSeconds: 240 | ||
| serviceAccountName: 1031333818730-compute@developer.gserviceaccount.com |
There was a problem hiding this comment.
GCP project numbers exposed in public repository
The serviceAccountName field embeds the raw GCP project number in the service account email. These numeric project IDs are committed in this public repository:
1031333818730-compute@developer.gserviceaccount.com(dev) — appears indev_backend.yaml:305,dev_backend-sync.yaml:193, anddev_backend-integration.yaml:222208440318997-compute@developer.gserviceaccount.com(prod) — appears inprod_backend.yaml:438,prod_backend-sync.yaml:223, andprod_backend-integration.yaml:333
GCP project numbers in a public repo allow adversaries to enumerate project resources, craft targeted phishing/social-engineering attacks, or abuse project-number-based APIs. Consider replacing these with a named service account alias (e.g., backend-cloudrun@based-hardware.iam.gserviceaccount.com) that does not leak the project number.
| image: gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }} | ||
| run: | | ||
| # Update image in declarative config | ||
| IMAGE="gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }}:latest" |
There was a problem hiding this comment.
:latest tag makes deployments non-deterministic
Both the Docker build step (line 69) and all three deploy steps push/deploy the :latest tag. This means:
- There is no stable artifact tied to a specific commit — any concurrent build can overwrite
:latestmid-deploy. - Rollback from Git alone is not possible; you would need to rebuild the image.
Consider tagging the image with the Git SHA and using that tag in the deploy:
tags: |
gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }}:latest
gcr.io/${{ vars.GCP_PROJECT_ID }}/${{ env.SERVICE }}:${{ github.sha }}Then use ${{ github.sha }} for the IMAGE variable in the deploy steps.
| - name: GOOGLE_CLOUD_PROJECT | ||
| value: based-hardware |
There was a problem hiding this comment.
GOOGLE_CLOUD_PROJECT points to prod project in dev config
Both dev_backend-sync.yaml:56 and dev_backend.yaml:79 set GOOGLE_CLOUD_PROJECT: based-hardware, which is the production GCP project, while the rest of the dev config (image registry gcr.io/based-hardware-dev/..., service account 1031333818730-compute@developer.gserviceaccount.com, VPC network omi-dev-vpc-1) all target the dev project based-hardware-dev.
If this is intentional (e.g., both environments share the same Firebase/Firestore project), a comment explaining the reason would help avoid future confusion. If unintentional, this should be changed to based-hardware-dev to match the rest of the dev environment configuration.
Summary
backend/charts/for GKE:backend/cloudrun/{service}/{dev|prod}_{service}.yamlgcloud run services replaceinstead ofdeploy-cloudrun@v2action — env vars and secrets are now git-tracked and PR-reviewablesecretKeyRef(GCP Secret Manager) — no plain-text secrets committedvad.omiapi.comDNS nameStructure
How it works
gcloud run services replacedev_orprod_prefix based on the environment inputcc @thainguyensunya
🤖 Generated with Claude Code