1- # This workflow builds and pushes Docker containers to Google Artifact Registry
2- # and deploys both backend and frontend on Cloud Run when a commit is pushed to the "production"
3- # branch.
1+ # Build and deploy QueryPal to Cloud Run.
2+ # Runs on pushes to the production branch.
3+ #
4+ # Infrastructure changes (VPC connector, Secret Manager, IAM) are managed by
5+ # Terraform in the terraform/ directory and must be applied before first deploy.
46
57name : ' Build and Deploy QueryPal to Cloud Run'
68
1618 BACKEND_SERVICE : ' querypal-backend'
1719 FRONTEND_SERVICE : ' querypal-frontend'
1820 WORKLOAD_IDENTITY_PROVIDER : ' projects/874216619692/locations/global/workloadIdentityPools/github/providers/querypal'
21+ # Cloud Run service account created by Terraform (terraform/iam.tf).
22+ CLOUD_RUN_SA : ' querypal-cloudrun-sa@gen-lang-client-0698668474.iam.gserviceaccount.com'
23+ # VPC connector created by Terraform (terraform/network.tf).
24+ VPC_CONNECTOR : ' querypal-vpc-connector'
1925
2026jobs :
2127 deploy :
@@ -29,80 +35,93 @@ jobs:
2935 - name : ' Checkout'
3036 uses : ' actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332' # actions/checkout@v4
3137
32- # Configure Workload Identity Federation and generate an access token.
3338 - id : ' auth'
3439 name : ' Authenticate to Google Cloud'
3540 uses : ' google-github-actions/auth@f112390a2df9932162083945e46d439060d66ec2' # google-github-actions/auth@v2
3641 with :
3742 workload_identity_provider : ' ${{ env.WORKLOAD_IDENTITY_PROVIDER }}'
38- service_account : ' github-actions@gen-lang-client-0698668474 .iam.gserviceaccount.com'
43+ service_account : ' github-actions@${{ env.PROJECT_ID }} .iam.gserviceaccount.com'
3944
40- # Set up Cloud SDK
4145 - name : ' Set up Cloud SDK'
4246 uses : ' google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200' # google-github-actions/setup-gcloud@v2
4347
44- # Configure Docker to use gcloud as a credential helper
4548 - name : ' Configure Docker for GCR'
46- run : |-
47- gcloud auth configure-docker --quiet
49+ run : gcloud auth configure-docker --quiet
50+
51+ # ── Backend ──────────────────────────────────────────────────────────────
4852
49- # Build and Push Backend Container
5053 - name : ' Build and Push Backend Container'
5154 run : |-
5255 cd backend
5356 DOCKER_TAG="gcr.io/${{ env.PROJECT_ID }}/${{ env.BACKEND_SERVICE }}:${{ github.sha }}"
5457 docker build --tag "${DOCKER_TAG}" --platform linux/amd64 .
5558 docker push "${DOCKER_TAG}"
5659
57- # Deploy Backend to Cloud Run
5860 - id : ' deploy-backend'
5961 name : ' Deploy Backend to Cloud Run'
6062 uses : ' google-github-actions/deploy-cloudrun@33553064113a37d688aa6937bacbdc481580be17' # google-github-actions/deploy-cloudrun@v2
6163 with :
6264 service : ' ${{ env.BACKEND_SERVICE }}'
6365 region : ' ${{ env.REGION }}'
6466 image : ' gcr.io/${{ env.PROJECT_ID }}/${{ env.BACKEND_SERVICE }}:${{ github.sha }}'
67+ # Non-secret runtime configuration only.
6568 env_vars : |
6669 ENVIRONMENT=production
67- AZURE_TENANT_ID=${{ secrets.AZURE_TENANT_ID }}
68- AZURE_CLIENT_ID=${{ secrets.AZURE_CLIENT_ID }}
69- AZURE_CLIENT_SECRET=${{ secrets.AZURE_CLIENT_SECRET }}
7070 ARM_SCOPE=https://management.azure.com/.default
71- GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY }}
72- DB_USER=${{ secrets.DB_USER }}
73- DB_PASS=${{ secrets.DB_PASS }}
7471 DB_NAME=querypal
75- DB_UNIX_SOCKET=/cloudsql/gen-lang-client-0698668474:europe-west1:querypal-db
72+ DB_UNIX_SOCKET=/cloudsql/${{ env.PROJECT_ID }}:${{ env.REGION }}:querypal-db
73+ # Sensitive values are read directly from Secret Manager at runtime.
74+ # Secret must exist before first deploy (created by terraform/secrets.tf).
75+ secrets : |
76+ AZURE_TENANT_ID=querypal-azure-tenant-id:latest
77+ AZURE_CLIENT_ID=querypal-azure-client-id:latest
78+ AZURE_CLIENT_SECRET=querypal-azure-client-secret:latest
79+ GEMINI_API_KEY=querypal-gemini-api-key:latest
80+ DB_USER=querypal-db-user:latest
81+ DB_PASS=querypal-db-pass:latest
7682 flags : |
7783 --port=8000
78- --add-cloudsql-instances=gen-lang-client-0698668474:europe-west1:querypal-db
84+ --service-account=${{ env.CLOUD_RUN_SA }}
85+ --add-cloudsql-instances=${{ env.PROJECT_ID }}:${{ env.REGION }}:querypal-db
86+ --vpc-connector=${{ env.VPC_CONNECTOR }}
87+ --vpc-egress=private-ranges-only
88+ --ingress=internal
7989 --allow-unauthenticated
8090
81- # Build and Push Frontend Container
91+ # ── Frontend ─────────────────────────────────────────────────────────────
92+
8293 - name : ' Build and Push Frontend Container'
8394 run : |-
8495 cd frontend
8596 DOCKER_TAG="gcr.io/${{ env.PROJECT_ID }}/${{ env.FRONTEND_SERVICE }}:${{ github.sha }}"
8697 docker build --tag "${DOCKER_TAG}" --platform linux/amd64 \
87- --build-arg VITE_API_BASE_URL=${{ steps.deploy-backend.outputs.url }} \
98+ --build-arg VITE_API_BASE_URL=/api \
8899 --build-arg VITE_AZURE_REDIRECT_URI=https://querypal.virtonomy.io \
89100 .
90101 docker push "${DOCKER_TAG}"
91102
92- # Deploy Frontend to Cloud Run
93103 - id : ' deploy-frontend'
94104 name : ' Deploy Frontend to Cloud Run'
95105 uses : ' google-github-actions/deploy-cloudrun@33553064113a37d688aa6937bacbdc481580be17' # google-github-actions/deploy-cloudrun@v2
96106 with :
97107 service : ' ${{ env.FRONTEND_SERVICE }}'
98108 region : ' ${{ env.REGION }}'
99109 image : ' gcr.io/${{ env.PROJECT_ID }}/${{ env.FRONTEND_SERVICE }}:${{ github.sha }}'
110+ # BACKEND_URL is the internal Cloud Run URL; nginx uses it at runtime to
111+ # proxy /api/* requests to the backend (which is not publicly reachable).
112+ env_vars : |
113+ BACKEND_URL=${{ steps.deploy-backend.outputs.url }}
100114 flags : |
101115 --port=4000
116+ --service-account=${{ env.CLOUD_RUN_SA }}
117+ --vpc-connector=${{ env.VPC_CONNECTOR }}
118+ --vpc-egress=all-traffic
119+ --ingress=all
102120 --allow-unauthenticated
103121
104- # Show output URLs
122+ # ── Summary ───────────────────────────────────────────────────────────────
123+
105124 - name : ' Show deployment URLs'
106125 run : |-
107- echo "Backend URL: ${{ steps.deploy-backend.outputs.url }}"
108126 echo "Frontend URL: ${{ steps.deploy-frontend.outputs.url }}"
127+ echo "Backend URL: ${{ steps.deploy-backend.outputs.url }} (internal only)"
0 commit comments